OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [software/] [CC64/] [source/] [CSETable.cpp] - Blame information for rev 48

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 48 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2017-2018  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
// CC64 - 'C' derived language compiler
9
//  - 64 bit CPU
10
//
11
// This source file is free software: you can redistribute it and/or modify 
12
// it under the terms of the GNU Lesser General Public License as published 
13
// by the Free Software Foundation, either version 3 of the License, or     
14
// (at your option) any later version.                                      
15
//                                                                          
16
// This source file is distributed in the hope that it will be useful,      
17
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
18
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
19
// GNU General Public License for more details.                             
20
//                                                                          
21
// You should have received a copy of the GNU General Public License        
22
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
23
//                                                                          
24
// ============================================================================
25
//
26
#include "stdafx.h"
27
 
28
void CSETable::Assign(CSETable *t)
29
{
30
        memcpy(this, t, sizeof(CSETable));
31
}
32
 
33
static int CSECmp(const void *a, const void *b)
34
{
35
        CSE *csp1, *csp2;
36
        int aa, bb;
37
 
38
        csp1 = (CSE *)a;
39
        csp2 = (CSE *)b;
40
        aa = csp1->OptimizationDesireability();
41
        bb = csp2->OptimizationDesireability();
42
        if (aa < bb)
43
                return (1);
44
        else if (aa == bb)
45
                return (0);
46
        else
47
                return (-1);
48
}
49
 
50
 
51
void CSETable::Sort(int(*cmp)(const void *a, const void *b))
52
{
53
        qsort(table, (size_t)csendx, sizeof(CSE), cmp);
54
}
55
 
56
// InsertNodeIntoCSEList will enter a reference to an expression node into the
57
// common expression table. duse is a flag indicating whether or not
58
// this reference will be dereferenced.
59
 
60
CSE *CSETable::InsertNode(ENODE *node, int duse)
61
{
62
        CSE *csp;
63
 
64
        if ((csp = Search(node)) == nullptr) {   /* add to tree */
65
                if (csendx > 499)
66
                        throw new C64PException(ERR_CSETABLE, 0x01);
67
                csp = &table[csendx];
68
                csendx++;
69
                if (loop_active > 1) {
70
                        csp->uses = (loop_active - 1) * 5;
71
                        csp->duses = (duse != 0) * ((loop_active - 1) * 5);
72
                }
73
                else {
74
                        csp->uses = 1;
75
                        csp->duses = (duse != 0);
76
                }
77
                csp->exp = node->Clone();
78
                csp->voidf = 0;
79
                csp->reg = 0;
80
                csp->isfp = csp->exp->IsFloatType();
81
                return (csp);
82
        }
83
        if (loop_active < 2) {
84
                (csp->uses)++;
85
                if (duse)
86
                        (csp->duses)++;
87
        }
88
        else {
89
                (csp->uses) += ((loop_active - 1) * 5);
90
                if (duse)
91
                        (csp->duses) += ((loop_active - 1) * 5);
92
        }
93
        return (csp);
94
}
95
 
96
//
97
// SearchCSEList will search the common expression table for an entry
98
// that matches the node passed and return a pointer to it.
99
//
100
CSE *CSETable::Search(ENODE *node)
101
{
102
        int cnt;
103
 
104
        for (cnt = 0; cnt < csendx; cnt++) {
105
                if (ENODE::IsEqual(node, table[cnt].exp))
106
                        return (&table[cnt]);
107
        }
108
        return ((CSE *)nullptr);
109
}
110
 
111
// voidauto2 searches the entire CSE table for auto dereferenced node which
112
// point to the passed node. There might be more than one LValue that matches.
113
// voidauto will void an auto dereference node which points to
114
// the same auto constant as node.
115
//
116
int CSETable::voidauto2(ENODE *node)
117
{
118
        int uses;
119
        bool voided;
120
        int cnt;
121
 
122
        uses = 0;
123
        voided = false;
124
        for (cnt = 0; cnt < csendx; cnt++) {
125
                if (IsLValue(table[cnt].exp) && ENODE::IsEqual(node, table[cnt].exp->p[0])) {
126
                        table[cnt].voidf = 1;
127
                        voided = true;
128
                        uses += table[cnt].uses;
129
                }
130
        }
131
        return (voided ? uses : -1);
132
}
133
 
134
// Make multiple passes over the CSE table in order to use
135
// up all temporary registers. Allocates on the progressively
136
// less desirable.
137
 
138
int CSETable::AllocateGPRegisters()
139
{
140
        CSE *csp;
141
        bool alloc;
142
        int pass;
143
        int reg;
144
 
145
        reg = regFirstRegvar;
146
        for (pass = 0; pass < 4; pass++) {
147
                for (csp = First(); csp; csp = Next()) {
148
                        if (csp->OptimizationDesireability() != 0) {
149
                                if (!csp->voidf && csp->reg == -1) {
150
                                        if (csp->exp->etype != bt_vector && !csp->isfp) {
151
                                                switch (pass)
152
                                                {
153
                                                case 0:
154
                                                case 1:
155
                                                case 2: alloc = (csp->OptimizationDesireability() >= 4) && reg < regLastRegvar; break;
156
                                                case 3: alloc = (csp->OptimizationDesireability() >= 4) && reg < regLastRegvar; break;
157
                                                }
158
                                                if (alloc)
159
                                                        csp->reg = reg++;
160
                                                else
161
                                                        csp->reg = -1;
162
                                        }
163
                                }
164
                        }
165
                }
166
        }
167
        return (reg);
168
}
169
 
170
int CSETable::AllocateFPRegisters()
171
{
172
        CSE *csp;
173
        bool alloc;
174
        int pass;
175
        int reg;
176
 
177
        reg = regFirstRegvar;
178
        for (pass = 0; pass < 4; pass++) {
179
                for (csp = First(); csp; csp = Next()) {
180
                        if (csp->OptimizationDesireability() != 0) {
181
                                if (!csp->voidf && csp->reg == -1) {
182
                                        if (csp->isfp) {
183
                                                switch (pass)
184
                                                {
185
                                                case 0:
186
                                                case 1:
187
                                                case 2: alloc = (csp->OptimizationDesireability() >= 4) && reg < regLastRegvar; break;
188
                                                case 3: alloc = (csp->OptimizationDesireability() >= 4) && reg < regLastRegvar; break;
189
                                                        //                                      if(( csp->duses > csp->uses / (8 << nn)) && reg < regLastRegvar )       // <- address register assignments
190
                                                }
191
                                                if (alloc)
192
                                                        csp->reg = reg++;
193
                                                else
194
                                                        csp->reg = -1;
195
                                        }
196
                                }
197
                        }
198
                }
199
        }
200
        return (reg);
201
}
202
 
203
int CSETable::AllocateVectorRegisters()
204
{
205
        int nn, vreg;
206
        CSE *csp;
207
        bool alloc;
208
 
209
        vreg = regFirstRegvar;
210
        for (nn = 0; nn < 4; nn++) {
211
                for (csp = First(); csp; csp = Next()) {
212
                        if (csp->exp) {
213
                                if (csp->exp->etype == bt_vector && csp->reg == -1 && vreg < regLastRegvar) {
214
                                        switch (nn) {
215
                                        case 0:
216
                                        case 1:
217
                                        case 2: alloc = (csp->OptimizationDesireability() >= 4 - nn)
218
                                                && (csp->duses > csp->uses / (8 << nn));
219
                                                break;
220
                                        case 3: alloc = (!csp->voidf) && (csp->uses > 3);
221
                                                break;
222
                                        }
223
                                        if (alloc)
224
                                                csp->reg = vreg++;
225
                                        else
226
                                                csp->reg = -1;
227
                                }
228
                        }
229
                }
230
        }
231
        return (vreg);
232
}
233
 
234
void CSETable::InitializeTempRegs()
235
{
236
        Operand *ap, *ap2, *ap3;
237
        CSE *csp;
238
        ENODE *exptr;
239
        int size;
240
 
241
        for (csp = First(); csp; csp = Next()) {
242
                if (csp->reg != -1)
243
                {               // see if preload needed
244
                        exptr = csp->exp;
245
                        if (1 || !IsLValue(exptr) || (exptr->p[0]->i > 0))
246
                        {
247
                                initstack();
248
                                {
249
                                        ap = GenerateExpression(exptr, F_REG | F_IMMED | F_MEM | F_FPREG, sizeOfWord);
250
                                        ap2 = csp->isfp ? makefpreg(csp->reg) : makereg(csp->reg);
251
                                        if (csp->isfp)
252
                                                ap2->type = ap->type;
253
                                        ap2->isPtr = ap->isPtr;
254
                                        if (ap->mode == am_imm) {
255
                                                if (ap2->mode == am_fpreg) {
256
                                                        ap3 = GetTempRegister();
257
                                                        GenLdi(ap3, ap);
258
                                                        GenerateDiadic(op_mov, 0, ap2, ap3);
259
                                                        ReleaseTempReg(ap3);
260
                                                }
261
                                                else
262
                                                        GenLdi(ap2, ap);
263
                                        }
264
                                        else if (ap->mode == am_reg)
265
                                                GenerateDiadic(op_mov, 0, ap2, ap);
266
                                        else {
267
                                                size = GetNaturalSize(exptr);
268
                                                ap->isUnsigned = exptr->isUnsigned;
269
                                                GenLoad(ap2, ap, size, size);
270
                                        }
271
                                }
272
                                ReleaseTempReg(ap);
273
                        }
274
                }
275
        }
276
 
277
}
278
 
279
void CSETable::GenerateRegMask(CSE *csp, uint64_t *mask, uint64_t *rmask)
280
{
281
        if (csp->reg != -1)
282
        {
283
                *rmask = *rmask | (1LL << (63 - csp->reg));
284
                *mask = *mask | (1LL << csp->reg);
285
        }
286
}
287
 
288
// ----------------------------------------------------------------------------
289
// AllocateRegisterVars will allocate registers for the expressions that have
290
// a high enough desirability.
291
// ----------------------------------------------------------------------------
292
 
293
int CSETable::AllocateRegisterVars()
294
{
295
        CSE *csp;
296
        uint64_t mask, rmask;
297
        uint64_t fpmask, fprmask;
298
        uint64_t vmask, vrmask;
299
 
300
        mask = 0;
301
        rmask = 0;
302
        fpmask = 0;
303
        fprmask = 0;
304
        vmask = 0;
305
        vrmask = 0;
306
 
307
        // Sort the CSE table according to desirability of allocating
308
        // a register.
309
        if (pass == 1)
310
                Sort(CSECmp);
311
 
312
        // Initialize to no allocated registers
313
        for (csp = First(); csp; csp = Next())
314
                csp->reg = -1;
315
 
316
        AllocateGPRegisters();
317
        AllocateFPRegisters();
318
        AllocateVectorRegisters();
319
 
320
        // Generate bit masks of allocated registers
321
        for (csp = First(); csp; csp = Next()) {
322
                if (csp->exp) {
323
                        if (csp->exp->IsFloatType())
324
                                GenerateRegMask(csp, &fpmask, &fprmask);
325
                        else if (csp->exp->etype == bt_vector)
326
                                GenerateRegMask(csp, &vrmask, &vmask);
327
                        else
328
                                GenerateRegMask(csp, &mask, &rmask);
329
                }
330
                else
331
                        GenerateRegMask(csp, &mask, &rmask);
332
        }
333
 
334
        Dump();
335
 
336
        // Push temporaries on the stack.
337
        SaveRegisterVars(mask, rmask);
338
        SaveFPRegisterVars(fpmask, fprmask);
339
 
340
        save_mask = mask;
341
        fpsave_mask = fpmask;
342
 
343
        InitializeTempRegs();
344
        return (popcnt(mask));
345
}
346
 
347
/*
348
*      opt1 is the externally callable optimization routine. it will
349
*      collect and allocate common subexpressions and substitute the
350
*      tempref for all occurrances of the expression within the block.
351
*/
352
int CSETable::Optimize(Statement *block)
353
{
354
        int nn;
355
 
356
        //csendx = 0;
357
        dfs.printf("<CSETable__Optimize>");
358
        nn = 0;
359
        if (pass == 1) {
360
                if (currentFn->csetbl == nullptr) {
361
                        currentFn->csetbl = new CSETable;
362
                }
363
                Clear();
364
        }
365
        else if (pass == 2) {
366
                //Assign(currentFn->csetbl);
367
        }
368
        dfs.printf("Pass:%d ", pass);
369
        if (opt_noregs == FALSE) {
370
                if (pass == 1)
371
                        block->scan();            /* collect expressions */
372
                nn = AllocateRegisterVars();
373
                if (pass == 2)
374
                        block->repcse();          /* replace allocated expressions */
375
        }
376
        if (pass == 1)
377
                ;// currentFn->csetbl->Assign(pCSETable);
378
        else if (pass == 2) {
379
                if (currentFn->csetbl && !currentFn->IsInline) {
380
                        delete currentFn->csetbl;
381
                        currentFn->csetbl = nullptr;
382
                }
383
        }
384
        dfs.printf("</CSETable__Optimize>\n");
385
        return (nn);
386
}
387
 
388
// Immediate constants have low priority.
389
// Even though their use might be high, they are given a low priority.
390
 
391
void CSETable::Dump()
392
{
393
        int nn;
394
        CSE *csp;
395
 
396
        dfs.printf("<CSETable>For %s\n", (char *)currentFn->sym->name->c_str());
397
        dfs.printf(
398
                "*The expression must be used three or more times before it will be allocated\n"
399
                "to a register.\n");
400
        dfs.printf("N OD Uses DUses Void Reg Sym\n");
401
        for (nn = 0; nn < csendx; nn++) {
402
                csp = &table[nn];
403
                dfs.printf("%d: ", nn);
404
                dfs.printf("%d   ", csp->OptimizationDesireability());
405
                dfs.printf("%d   ", csp->uses);
406
                dfs.printf("%d   ", csp->duses);
407
                dfs.printf("%d   ", (int)csp->voidf);
408
                dfs.printf("%d   ", csp->reg);
409
                if (csp->exp && csp->exp->sym)
410
                        dfs.printf("%s   ", (char *)csp->exp->sym->name->c_str());
411
                if (csp->exp && csp->exp->sp)
412
                        dfs.printf("%s   ", (char *)((std::string *)(csp->exp->sp))->c_str());
413
                dfs.printf("\n");
414
        }
415
        dfs.printf("</CSETable>\n");
416
}
417
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.