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

Subversion Repositories eco32

[/] [eco32/] [trunk/] [lcc/] [src/] [gen.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 hellwig
#include "c.h"
2
 
3
static char rcsid[] = "$Id: gen.c,v 1.1 2002/08/28 23:12:43 drh Exp $";
4
 
5
#define readsreg(p) \
6
        (generic((p)->op)==INDIR && (p)->kids[0]->op==VREG+P)
7
#define setsrc(d) ((d) && (d)->x.regnode && \
8
        (d)->x.regnode->set == src->x.regnode->set && \
9
        (d)->x.regnode->mask&src->x.regnode->mask)
10
 
11
#define relink(a, b) ((b)->x.prev = (a), (a)->x.next = (b))
12
 
13
static Symbol   askfixedreg(Symbol);
14
static Symbol   askreg(Symbol, unsigned*);
15
static void     blkunroll(int, int, int, int, int, int, int[]);
16
static void     docall(Node);
17
static void     dumpcover(Node, int, int);
18
static void     dumpregs(char *, char *, char *);
19
static void     dumprule(int);
20
static void     dumptree(Node);
21
static void     genreload(Node, Symbol, int);
22
static void     genspill(Symbol, Node, Symbol);
23
static Symbol   getreg(Symbol, unsigned*, Node);
24
static int      getrule(Node, int);
25
static void     linearize(Node, Node);
26
static int      moveself(Node);
27
static void     prelabel(Node);
28
static Node*    prune(Node, Node*);
29
static void     putreg(Symbol);
30
static void     ralloc(Node);
31
static void     reduce(Node, int);
32
static int      reprune(Node*, int, int, Node);
33
static int      requate(Node);
34
static Node     reuse(Node, int);
35
static void     rewrite(Node);
36
static Symbol   spillee(Symbol, unsigned mask[], Node);
37
static void     spillr(Symbol, Node);
38
static int      uses(Node, Regnode);
39
 
40
int offset;
41
 
42
int maxoffset;
43
 
44
int framesize;
45
int argoffset;
46
 
47
int maxargoffset;
48
 
49
int dalign, salign;
50
int bflag = 0;  /* omit */
51
int dflag = 0;
52
 
53
int swap;
54
 
55
unsigned (*emitter)(Node, int) = emitasm;
56
static char NeedsReg[] = {
57
        0,                      /* unused */
58
        1,                      /* CNST */
59
        0, 0,                   /* ARG ASGN */
60
        1,                      /* INDIR  */
61
        0, 0, 1, 1,             /*  -  - CVF CVI */
62
        1, 0, 1, 1,             /* CVP - CVU NEG */
63
        1,                      /* CALL */
64
        1,                      /* LOAD */
65
        0,                      /* RET */
66
        1, 1, 1,                /* ADDRG ADDRF ADDRL */
67
        1, 1, 1, 1, 1,          /* ADD SUB LSH MOD RSH */
68
        1, 1, 1, 1,             /* BAND BCOM BOR BXOR */
69
        1, 1,                   /* DIV MUL */
70
        0, 0, 0, 0, 0, 0,       /* EQ GE GT LE LT NE */
71
        0, 0                   /* JUMP LABEL   */
72
};
73
Node head;
74
 
75
unsigned freemask[2];
76
unsigned usedmask[2];
77
unsigned tmask[2];
78
unsigned vmask[2];
79
Symbol mkreg(char *fmt, int n, int mask, int set) {
80
        Symbol p;
81
 
82
        NEW0(p, PERM);
83
        p->name = p->x.name = stringf(fmt, n);
84
        NEW0(p->x.regnode, PERM);
85
        p->x.regnode->number = n;
86
        p->x.regnode->mask = mask<<n;
87
        p->x.regnode->set = set;
88
        return p;
89
}
90
Symbol mkwildcard(Symbol *syms) {
91
        Symbol p;
92
 
93
        NEW0(p, PERM);
94
        p->name = p->x.name = "wildcard";
95
        p->x.wildcard = syms;
96
        return p;
97
}
98
void mkauto(Symbol p) {
99
        assert(p->sclass == AUTO);
100
        offset = roundup(offset + p->type->size, p->type->align);
101
        p->x.offset = -offset;
102
        p->x.name = stringd(-offset);
103
}
104
void blockbeg(Env *e) {
105
        e->offset = offset;
106
        e->freemask[IREG] = freemask[IREG];
107
        e->freemask[FREG] = freemask[FREG];
108
}
109
void blockend(Env *e) {
110
        if (offset > maxoffset)
111
                maxoffset = offset;
112
        offset = e->offset;
113
        freemask[IREG] = e->freemask[IREG];
114
        freemask[FREG] = e->freemask[FREG];
115
}
116
int mkactual(int align, int size) {
117
        int n = roundup(argoffset, align);
118
 
119
        argoffset = n + size;
120
        return n;
121
}
122
static void docall(Node p) {
123
        p->syms[1] = p->syms[0];
124
        p->syms[0] = intconst(argoffset);
125
        if (argoffset > maxargoffset)
126
                maxargoffset = argoffset;
127
        argoffset = 0;
128
}
129
void blkcopy(int dreg, int doff, int sreg, int soff, int size, int tmp[]) {
130
        assert(size >= 0);
131
        if (size == 0)
132
                return;
133
        else if (size <= 2)
134
                blkunroll(size, dreg, doff, sreg, soff, size, tmp);
135
        else if (size == 3) {
136
                blkunroll(2, dreg, doff,   sreg, soff,   2, tmp);
137
                blkunroll(1, dreg, doff+2, sreg, soff+2, 1, tmp);
138
        }
139
        else if (size <= 16) {
140
                blkunroll(4, dreg, doff, sreg, soff, size&~3, tmp);
141
                blkcopy(dreg, doff+(size&~3),
142
                        sreg, soff+(size&~3), size&3, tmp);
143
        }
144
        else
145
                (*IR->x.blkloop)(dreg, doff, sreg, soff, size, tmp);
146
}
147
static void blkunroll(int k, int dreg, int doff, int sreg, int soff, int size, int tmp[]) {
148
        int i;
149
 
150
        assert(IR->x.max_unaligned_load);
151
        if (k > IR->x.max_unaligned_load
152
        && (k > salign || k > dalign))
153
                k = IR->x.max_unaligned_load;
154
        for (i = 0; i+k < size; i += 2*k) {
155
                (*IR->x.blkfetch)(k, soff+i,   sreg, tmp[0]);
156
                (*IR->x.blkfetch)(k, soff+i+k, sreg, tmp[1]);
157
                (*IR->x.blkstore)(k, doff+i,   dreg, tmp[0]);
158
                (*IR->x.blkstore)(k, doff+i+k, dreg, tmp[1]);
159
        }
160
        if (i < size) {
161
                (*IR->x.blkfetch)(k, i+soff, sreg, tmp[0]);
162
                (*IR->x.blkstore)(k, i+doff, dreg, tmp[0]);
163
        }
164
}
165
void parseflags(int argc, char *argv[]) {
166
        int i;
167
 
168
        for (i = 0; i < argc; i++)
169
                if (strcmp(argv[i], "-d") == 0)
170
                        dflag = 1;
171
                else if (strcmp(argv[i], "-b") == 0)     /* omit */
172
                        bflag = 1;                      /* omit */
173
}
174
static int getrule(Node p, int nt) {
175
        int rulenum;
176
 
177
        assert(p);
178
        rulenum = (*IR->x._rule)(p->x.state, nt);
179
        if (!rulenum) {
180
                fprint(stderr, "(%x->op=%s at %w is corrupt.)\n", p, opname(p->op), &src);
181
                assert(0);
182
        }
183
        return rulenum;
184
}
185
static void reduce(Node p, int nt) {
186
        int rulenum, i;
187
        short *nts;
188
        Node kids[10];
189
 
190
        p = reuse(p, nt);
191
        rulenum = getrule(p, nt);
192
        nts = IR->x._nts[rulenum];
193
        (*IR->x._kids)(p, rulenum, kids);
194
        for (i = 0; nts[i]; i++)
195
                reduce(kids[i], nts[i]);
196
        if (IR->x._isinstruction[rulenum]) {
197
                assert(p->x.inst == 0 || p->x.inst == nt);
198
                p->x.inst = nt;
199
                if (p->syms[RX] && p->syms[RX]->temporary) {
200
                        debug(fprint(stderr, "(using %s)\n", p->syms[RX]->name));
201
                        p->syms[RX]->x.usecount++;
202
                }
203
        }
204
}
205
static Node reuse(Node p, int nt) {
206
        struct _state {
207
                short cost[1];
208
        };
209
        Symbol r = p->syms[RX];
210
 
211
        if (generic(p->op) == INDIR && p->kids[0]->op == VREG+P
212
        && r->u.t.cse && p->x.mayrecalc
213
        && ((struct _state*)r->u.t.cse->x.state)->cost[nt] == 0)
214
                return r->u.t.cse;
215
        else
216
                return p;
217
}
218
 
219
int mayrecalc(Node p) {
220
        int op;
221
 
222
        assert(p && p->syms[RX]);
223
        if (p->syms[RX]->u.t.cse == NULL)
224
                return 0;
225
        op = generic(p->syms[RX]->u.t.cse->op);
226
        if (op == CNST || op == ADDRF || op == ADDRG || op == ADDRL) {
227
                p->x.mayrecalc = 1;
228
                return 1;
229
        } else
230
                return 0;
231
}
232
static Node *prune(Node p, Node pp[]) {
233
        if (p == NULL)
234
                return pp;
235
        p->x.kids[0] = p->x.kids[1] = p->x.kids[2] = NULL;
236
        if (p->x.inst == 0)
237
                return prune(p->kids[1], prune(p->kids[0], pp));
238
        else if (p->syms[RX] && p->syms[RX]->temporary
239
        && p->syms[RX]->x.usecount < 2) {
240
                p->x.inst = 0;
241
                debug(fprint(stderr, "(clobbering %s)\n", p->syms[RX]->name));
242
                return prune(p->kids[1], prune(p->kids[0], pp));
243
        }
244
        else {
245
                prune(p->kids[1], prune(p->kids[0], &p->x.kids[0]));
246
                *pp = p;
247
                return pp + 1;
248
        }
249
}
250
 
251
#define ck(i) return (i) ? 0 : LBURG_MAX
252
 
253
int range(Node p, int lo, int hi) {
254
        Symbol s = p->syms[0];
255
 
256
        switch (specific(p->op)) {
257
        case ADDRF+P:
258
        case ADDRL+P: ck(s->x.offset >= lo && s->x.offset <= hi);
259
        case CNST+I:  ck(s->u.c.v.i  >= lo && s->u.c.v.i  <= hi);
260
        case CNST+U:  ck(s->u.c.v.u  >= lo && s->u.c.v.u  <= hi);
261
        case CNST+P:  ck(s->u.c.v.p  == 0  && lo <= 0 && hi >= 0);
262
        }
263
        return LBURG_MAX;
264
}
265
static void dumptree(Node p) {
266
        if (p->op == VREG+P && p->syms[0]) {
267
                fprint(stderr, "VREGP(%s)", p->syms[0]->name);
268
                return;
269
        } else if (generic(p->op) == LOAD) {
270
                fprint(stderr, "LOAD(");
271
                dumptree(p->kids[0]);
272
                fprint(stderr, ")");
273
                return;
274
        }
275
        fprint(stderr, "%s(", opname(p->op));
276
        switch (generic(p->op)) {
277
        case CNST: case LABEL:
278
        case ADDRG: case ADDRF: case ADDRL:
279
                if (p->syms[0])
280
                        fprint(stderr, "%s", p->syms[0]->name);
281
                break;
282
        case RET:
283
                if (p->kids[0])
284
                        dumptree(p->kids[0]);
285
                break;
286
        case CVF: case CVI: case CVP: case CVU: case JUMP:
287
        case ARG: case BCOM: case NEG: case INDIR:
288
                dumptree(p->kids[0]);
289
                break;
290
        case CALL:
291
                if (optype(p->op) != B) {
292
                        dumptree(p->kids[0]);
293
                        break;
294
                }
295
                /* else fall thru */
296
        case EQ: case NE: case GT: case GE: case LE: case LT:
297
        case ASGN: case BOR: case BAND: case BXOR: case RSH: case LSH:
298
        case ADD: case SUB:  case DIV: case MUL: case MOD:
299
                dumptree(p->kids[0]);
300
                fprint(stderr, ", ");
301
                dumptree(p->kids[1]);
302
                break;
303
        default: assert(0);
304
        }
305
        fprint(stderr, ")");
306
}
307
static void dumpcover(Node p, int nt, int in) {
308
        int rulenum, i;
309
        short *nts;
310
        Node kids[10];
311
 
312
        p = reuse(p, nt);
313
        rulenum = getrule(p, nt);
314
        nts = IR->x._nts[rulenum];
315
        fprint(stderr, "dumpcover(%x) = ", p);
316
        for (i = 0; i < in; i++)
317
                fprint(stderr, " ");
318
        dumprule(rulenum);
319
        (*IR->x._kids)(p, rulenum, kids);
320
        for (i = 0; nts[i]; i++)
321
                dumpcover(kids[i], nts[i], in+1);
322
}
323
 
324
static void dumprule(int rulenum) {
325
        assert(rulenum);
326
        fprint(stderr, "%s / %s", IR->x._string[rulenum],
327
                IR->x._templates[rulenum]);
328
        if (!IR->x._isinstruction[rulenum])
329
                fprint(stderr, "\n");
330
}
331
unsigned emitasm(Node p, int nt) {
332
        int rulenum;
333
        short *nts;
334
        char *fmt;
335
        Node kids[10];
336
 
337
        p = reuse(p, nt);
338
        rulenum = getrule(p, nt);
339
        nts = IR->x._nts[rulenum];
340
        fmt = IR->x._templates[rulenum];
341
        assert(fmt);
342
        if (IR->x._isinstruction[rulenum] && p->x.emitted)
343
                print("%s", p->syms[RX]->x.name);
344
        else if (*fmt == '#')
345
                (*IR->x.emit2)(p);
346
        else {
347
                if (*fmt == '?') {
348
                        fmt++;
349
                        assert(p->kids[0]);
350
                        if (p->syms[RX] == p->x.kids[0]->syms[RX])
351
                                while (*fmt++ != '\n')
352
                                        ;
353
                }
354
                for ((*IR->x._kids)(p, rulenum, kids); *fmt; fmt++)
355
                        if (*fmt != '%')
356
                                (void)putchar(*fmt);
357
                        else if (*++fmt == 'F')
358
                                print("%d", framesize);
359
                        else if (*fmt >= '0' && *fmt <= '9')
360
                                emitasm(kids[*fmt - '0'], nts[*fmt - '0']);
361
                        else if (*fmt >= 'a' && *fmt < 'a' + NELEMS(p->syms))
362
                                fputs(p->syms[*fmt - 'a']->x.name, stdout);
363
                        else
364
                                (void)putchar(*fmt);
365
        }
366
        return 0;
367
}
368
void emit(Node p) {
369
        for (; p; p = p->x.next) {
370
                assert(p->x.registered);
371
                if (p->x.equatable && requate(p) || moveself(p))
372
                        ;
373
                else
374
                        (*emitter)(p, p->x.inst);
375
                p->x.emitted = 1;
376
        }
377
}
378
static int moveself(Node p) {
379
        return p->x.copy
380
        && p->syms[RX]->x.name == p->x.kids[0]->syms[RX]->x.name;
381
}
382
int move(Node p) {
383
        p->x.copy = 1;
384
        return 1;
385
}
386
static int requate(Node q) {
387
        Symbol src = q->x.kids[0]->syms[RX];
388
        Symbol tmp = q->syms[RX];
389
        Node p;
390
        int n = 0;
391
 
392
        debug(fprint(stderr, "(requate(%x): tmp=%s src=%s)\n", q, tmp->x.name, src->x.name));
393
        for (p = q->x.next; p; p = p->x.next)
394
                if (p->x.copy && p->syms[RX] == src
395
                &&  p->x.kids[0]->syms[RX] == tmp)
396
                        debug(fprint(stderr, "(requate arm 0 at %x)\n", p)),
397
                        p->syms[RX] = tmp;
398
                else if (setsrc(p->syms[RX]) && !moveself(p) && !readsreg(p))
399
                        return 0;
400
                else if (p->x.spills)
401
                        return 0;
402
                else if (generic(p->op) == CALL && p->x.next)
403
                        return 0;
404
                else if (p->op == LABEL+V && p->x.next)
405
                        return 0;
406
                else if (p->syms[RX] == tmp && readsreg(p))
407
                        debug(fprint(stderr, "(requate arm 5 at %x)\n", p)),
408
                        n++;
409
                else if (p->syms[RX] == tmp)
410
                        break;
411
        debug(fprint(stderr, "(requate arm 7 at %x)\n", p));
412
        assert(n > 0);
413
        for (p = q->x.next; p; p = p->x.next)
414
                if (p->syms[RX] == tmp && readsreg(p)) {
415
                        p->syms[RX] = src;
416
                        if (--n <= 0)
417
                                break;
418
                }
419
        return 1;
420
}
421
static void prelabel(Node p) {
422
        if (p == NULL)
423
                return;
424
        prelabel(p->kids[0]);
425
        prelabel(p->kids[1]);
426
        if (NeedsReg[opindex(p->op)])
427
                setreg(p, (*IR->x.rmap)(opkind(p->op)));
428
        switch (generic(p->op)) {
429
        case ADDRF: case ADDRL:
430
                if (p->syms[0]->sclass == REGISTER)
431
                        p->op = VREG+P;
432
                break;
433
        case INDIR:
434
                if (p->kids[0]->op == VREG+P)
435
                        setreg(p, p->kids[0]->syms[0]);
436
                break;
437
        case ASGN:
438
                if (p->kids[0]->op == VREG+P)
439
                        rtarget(p, 1, p->kids[0]->syms[0]);
440
                break;
441
        case CVI: case CVU: case CVP:
442
                if (optype(p->op) != F
443
                &&  opsize(p->op) <= p->syms[0]->u.c.v.i)
444
                        p->op = LOAD + opkind(p->op);
445
                break;
446
        }
447
        (IR->x.target)(p);
448
}
449
void setreg(Node p, Symbol r) {
450
        p->syms[RX] = r;
451
}
452
void rtarget(Node p, int n, Symbol r) {
453
        Node q = p->kids[n];
454
 
455
        assert(q);
456
        assert(r);
457
        assert(r->sclass == REGISTER || !r->x.wildcard);
458
        assert(q->syms[RX]);
459
        if (r != q->syms[RX] && !q->syms[RX]->x.wildcard) {
460
                q = newnode(LOAD + opkind(q->op),
461
                        q, NULL, q->syms[0]);
462
                if (r->u.t.cse == p->kids[n])
463
                        r->u.t.cse = q;
464
                p->kids[n] = p->x.kids[n] = q;
465
                q->x.kids[0] = q->kids[0];
466
        }
467
        setreg(q, r);
468
        debug(fprint(stderr, "(targeting %x->x.kids[%d]=%x to %s)\n", p, n, p->kids[n], r->x.name));
469
}
470
static void rewrite(Node p) {
471
        assert(p->x.inst == 0);
472
        prelabel(p);
473
        debug(dumptree(p));
474
        debug(fprint(stderr, "\n"));
475
        (*IR->x._label)(p);
476
        debug(dumpcover(p, 1, 0));
477
        reduce(p, 1);
478
}
479
Node gen(Node forest) {
480
        int i;
481
        struct node sentinel;
482
        Node dummy, p;
483
 
484
        head = forest;
485
        for (p = forest; p; p = p->link) {
486
                assert(p->count == 0);
487
                if (generic(p->op) == CALL)
488
                        docall(p);
489
                else if (   generic(p->op) == ASGN
490
                && generic(p->kids[1]->op) == CALL)
491
                        docall(p->kids[1]);
492
                else if (generic(p->op) == ARG)
493
                        (*IR->x.doarg)(p);
494
                rewrite(p);
495
                p->x.listed = 1;
496
        }
497
        for (p = forest; p; p = p->link)
498
                prune(p, &dummy);
499
        relink(&sentinel, &sentinel);
500
        for (p = forest; p; p = p->link)
501
                linearize(p, &sentinel);
502
        forest = sentinel.x.next;
503
        assert(forest);
504
        sentinel.x.next->x.prev = NULL;
505
        sentinel.x.prev->x.next = NULL;
506
        for (p = forest; p; p = p->x.next)
507
                for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
508
                        assert(p->x.kids[i]->syms[RX]);
509
                        if (p->x.kids[i]->syms[RX]->temporary) {
510
                                p->x.kids[i]->x.prevuse =
511
                                        p->x.kids[i]->syms[RX]->x.lastuse;
512
                                p->x.kids[i]->syms[RX]->x.lastuse = p->x.kids[i];
513
                        }
514
                }
515
        for (p = forest; p; p = p->x.next) {
516
                ralloc(p);
517
                if (p->x.listed && NeedsReg[opindex(p->op)]
518
                && (*IR->x.rmap)(opkind(p->op))) {
519
                        assert(generic(p->op) == CALL || generic(p->op) == LOAD);
520
                        putreg(p->syms[RX]);
521
                }
522
        }
523
        return forest;
524
}
525
int notarget(Node p) {
526
        return p->syms[RX]->x.wildcard ? 0 : LBURG_MAX;
527
}
528
static void putreg(Symbol r) {
529
        assert(r && r->x.regnode);
530
        freemask[r->x.regnode->set] |= r->x.regnode->mask;
531
        debug(dumpregs("(freeing %s)\n", r->x.name, NULL));
532
}
533
static Symbol askfixedreg(Symbol s) {
534
        Regnode r = s->x.regnode;
535
        int n = r->set;
536
 
537
        if (r->mask&~freemask[n])
538
                return NULL;
539
        else {
540
                freemask[n] &= ~r->mask;
541
                usedmask[n] |=  r->mask;
542
                return s;
543
        }
544
}
545
static Symbol askreg(Symbol rs, unsigned rmask[]) {
546
        int i;
547
 
548
        if (rs->x.wildcard == NULL)
549
                return askfixedreg(rs);
550
        for (i = 31; i >= 0; i--) {
551
                Symbol r = rs->x.wildcard[i];
552
                if (r != NULL
553
                && !(r->x.regnode->mask&~rmask[r->x.regnode->set])
554
                && askfixedreg(r))
555
                        return r;
556
        }
557
        return NULL;
558
}
559
 
560
static Symbol getreg(Symbol s, unsigned mask[], Node p) {
561
        Symbol r = askreg(s, mask);
562
        if (r == NULL) {
563
                r = spillee(s, mask, p);
564
                assert(r && r->x.regnode);
565
                spill(r->x.regnode->mask, r->x.regnode->set, p);
566
                r = askreg(s, mask);
567
        }
568
        assert(r && r->x.regnode);
569
        r->x.regnode->vbl = NULL;
570
        return r;
571
}
572
int askregvar(Symbol p, Symbol regs) {
573
        Symbol r;
574
 
575
        assert(p);
576
        if (p->sclass != REGISTER)
577
                return 0;
578
        else if (!isscalar(p->type)) {
579
                p->sclass = AUTO;
580
                return 0;
581
        }
582
        else if (p->temporary) {
583
                p->x.name = "?";
584
                return 1;
585
        }
586
        else if ((r = askreg(regs, vmask)) != NULL) {
587
                p->x.regnode = r->x.regnode;
588
                p->x.regnode->vbl = p;
589
                p->x.name = r->x.name;
590
                debug(dumpregs("(allocating %s to symbol %s)\n", p->x.name, p->name));
591
                return 1;
592
        }
593
        else {
594
                p->sclass = AUTO;
595
                return 0;
596
        }
597
}
598
static void linearize(Node p, Node next) {
599
        int i;
600
 
601
        for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
602
                linearize(p->x.kids[i], next);
603
        relink(next->x.prev, p);
604
        relink(p, next);
605
        debug(fprint(stderr, "(listing %x)\n", p));
606
}
607
static void ralloc(Node p) {
608
        int i;
609
        unsigned mask[2];
610
 
611
        mask[0] = tmask[0];
612
        mask[1] = tmask[1];
613
        assert(p);
614
        debug(fprint(stderr, "(rallocing %x)\n", p));
615
        for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
616
                Node kid = p->x.kids[i];
617
                Symbol r = kid->syms[RX];
618
                assert(r && kid->x.registered);
619
                if (r->sclass != REGISTER && r->x.lastuse == kid)
620
                        putreg(r);
621
        }
622
        if (!p->x.registered && NeedsReg[opindex(p->op)]
623
        && (*IR->x.rmap)(opkind(p->op))) {
624
                Symbol sym = p->syms[RX], set = sym;
625
                assert(sym);
626
                if (sym->temporary)
627
                        set = (*IR->x.rmap)(opkind(p->op));
628
                assert(set);
629
                if (set->sclass != REGISTER) {
630
                        Symbol r;
631
                        if (*IR->x._templates[getrule(p, p->x.inst)] == '?')
632
                                for (i = 1; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
633
                                        Symbol r = p->x.kids[i]->syms[RX];
634
                                        assert(p->x.kids[i]->x.registered);
635
                                        assert(r && r->x.regnode);
636
                                        assert(sym->x.wildcard || sym != r);
637
                                        mask[r->x.regnode->set] &= ~r->x.regnode->mask;
638
                                }
639
                        r = getreg(set, mask, p);
640
                        if (sym->temporary) {
641
                                Node q;
642
                                r->x.lastuse = sym->x.lastuse;
643
                                for (q = sym->x.lastuse; q; q = q->x.prevuse) {
644
                                        q->syms[RX] = r;
645
                                        q->x.registered = 1;
646
                                        if (sym->u.t.cse && q->x.copy)
647
                                                q->x.equatable = 1;
648
                                }
649
                        } else {
650
                                p->syms[RX] = r;
651
                                r->x.lastuse = p;
652
                        }
653
                        debug(dumpregs("(allocating %s to node %x)\n", r->x.name, (char *) p));
654
                }
655
        }
656
        p->x.registered = 1;
657
        (*IR->x.clobber)(p);
658
}
659
static Symbol spillee(Symbol set, unsigned mask[], Node here) {
660
        Symbol bestreg = NULL;
661
        int bestdist = -1, i;
662
 
663
        assert(set);
664
        if (!set->x.wildcard)
665
                bestreg = set;
666
        else {
667
                for (i = 31; i >= 0; i--) {
668
                        Symbol ri = set->x.wildcard[i];
669
                        if (
670
                                ri != NULL &&
671
                                ri->x.lastuse &&
672
                                (ri->x.regnode->mask&tmask[ri->x.regnode->set]&mask[ri->x.regnode->set])
673
                        ) {
674
                                Regnode rn = ri->x.regnode;
675
                                Node q = here;
676
                                int dist = 0;
677
                                for (; q && !uses(q, rn); q = q->x.next)
678
                                        dist++;
679
                                if (q && dist > bestdist) {
680
                                        bestdist = dist;
681
                                        bestreg = ri;
682
                                }
683
                        }
684
                }
685
        }
686
        assert(bestreg); /* Must be able to spill something. Reconfigure the register allocator
687
                to ensure that we can allocate a register for all nodes without spilling
688
                the node's necessary input regs. */
689
        assert(bestreg->x.regnode->vbl == NULL); /* Can't spill register variables because
690
                the reload site might be in other blocks. Reconfigure the register allocator
691
                to ensure that this register is never allocated to a variable. */
692
        return bestreg;
693
}
694
static int uses(Node p, Regnode rn) {
695
        int i;
696
 
697
        for (i = 0; i < NELEMS(p->x.kids); i++)
698
                if (
699
                        p->x.kids[i] &&
700
                        p->x.kids[i]->x.registered &&
701
                        rn->set == p->x.kids[i]->syms[RX]->x.regnode->set &&
702
                        (rn->mask&p->x.kids[i]->syms[RX]->x.regnode->mask)
703
                )
704
                        return 1;
705
        return 0;
706
}
707
static void spillr(Symbol r, Node here) {
708
        int i;
709
        Symbol tmp;
710
        Node p = r->x.lastuse;
711
        assert(p);
712
        while (p->x.prevuse)
713
                assert(r == p->syms[RX]),
714
                p = p->x.prevuse;
715
        assert(p->x.registered && !readsreg(p));
716
        tmp = newtemp(AUTO, optype(p->op), opsize(p->op));
717
        genspill(r, p, tmp);
718
        for (p = here->x.next; p; p = p->x.next)
719
                for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
720
                        Node k = p->x.kids[i];
721
                        if (k->x.registered && k->syms[RX] == r)
722
                                genreload(p, tmp, i);
723
                }
724
        putreg(r);
725
}
726
static void genspill(Symbol r, Node last, Symbol tmp) {
727
        Node p, q;
728
        Symbol s;
729
        unsigned ty;
730
 
731
        debug(fprint(stderr, "(spilling %s to local %s)\n", r->x.name, tmp->x.name));
732
        debug(fprint(stderr, "(genspill: "));
733
        debug(dumptree(last));
734
        debug(fprint(stderr, ")\n"));
735
        ty = opkind(last->op);
736
        NEW0(s, FUNC);
737
        s->sclass = REGISTER;
738
        s->name = s->x.name = r->x.name;
739
        s->x.regnode = r->x.regnode;
740
        q = newnode(ADDRL+P + sizeop(IR->ptrmetric.size), NULL, NULL, s);
741
        q = newnode(INDIR + ty, q, NULL, NULL);
742
        p = newnode(ADDRL+P + sizeop(IR->ptrmetric.size), NULL, NULL, tmp);
743
        p = newnode(ASGN + ty, p, q, NULL);
744
        p->x.spills = 1;
745
        rewrite(p);
746
        prune(p, &q);
747
        q = last->x.next;
748
        linearize(p, q);
749
        for (p = last->x.next; p != q; p = p->x.next) {
750
                ralloc(p);
751
                assert(!p->x.listed || !NeedsReg[opindex(p->op)] || !(*IR->x.rmap)(opkind(p->op)));
752
        }
753
}
754
 
755
static void genreload(Node p, Symbol tmp, int i) {
756
        Node q;
757
        int ty;
758
 
759
        debug(fprint(stderr, "(replacing %x with a reload from %s)\n", p->x.kids[i], tmp->x.name));
760
        debug(fprint(stderr, "(genreload: "));
761
        debug(dumptree(p->x.kids[i]));
762
        debug(fprint(stderr, ")\n"));
763
        ty = opkind(p->x.kids[i]->op);
764
        q = newnode(ADDRL+P + sizeop(IR->ptrmetric.size), NULL, NULL, tmp);
765
        p->x.kids[i] = newnode(INDIR + ty, q, NULL, NULL);
766
        rewrite(p->x.kids[i]);
767
        prune(p->x.kids[i], &q);
768
        reprune(&p->kids[1], reprune(&p->kids[0], 0, i, p), i, p);
769
        prune(p, &q);
770
        linearize(p->x.kids[i], p);
771
}
772
static int reprune(Node *pp, int k, int n, Node p) {
773
        struct node x, *q = *pp;
774
 
775
        if (q == NULL || k > n)
776
                return k;
777
        else if (q->x.inst == 0)
778
                return reprune(&q->kids[1],
779
                        reprune(&q->kids[0], k, n, p), n, p);
780
        if (k == n) {
781
                debug(fprint(stderr, "(reprune changes %x from %x to %x)\n", pp, *pp, p->x.kids[n]));
782
                *pp = p->x.kids[n];
783
                x = *p;
784
                (IR->x.target)(&x);
785
        }
786
        return k + 1;
787
}
788
void spill(unsigned mask, int n, Node here) {
789
        int i;
790
        Node p;
791
 
792
        here->x.spills = 1;
793
        usedmask[n] |= mask;
794
        if (mask&~freemask[n]) {
795
 
796
                assert( /* It makes no sense for a node to clobber() its target. */
797
                        here->x.registered == 0 || /* call isn't coming through clobber() */
798
                        here->syms[RX] == NULL ||
799
                        here->syms[RX]->x.regnode == NULL ||
800
                        here->syms[RX]->x.regnode->set != n ||
801
                        (here->syms[RX]->x.regnode->mask&mask) == 0
802
                );
803
 
804
                for (p = here; p; p = p->x.next)
805
                        for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
806
                                Symbol r = p->x.kids[i]->syms[RX];
807
                                assert(r);
808
                                if (p->x.kids[i]->x.registered && r->x.regnode->set == n
809
                                && r->x.regnode->mask&mask)
810
                                        spillr(r, here);
811
                        }
812
        }
813
}
814
static void dumpregs(char *msg, char *a, char *b) {
815
        fprint(stderr, msg, a, b);
816
        fprint(stderr, "(free[0]=%x)\n", freemask[0]);
817
        fprint(stderr, "(free[1]=%x)\n", freemask[1]);
818
}
819
 
820
int getregnum(Node p) {
821
        assert(p && p->syms[RX] && p->syms[RX]->x.regnode);
822
        return p->syms[RX]->x.regnode->number;
823
}
824
 
825
 
826
unsigned regloc(Symbol p) {
827
        assert(p && p->sclass == REGISTER && p->sclass == REGISTER && p->x.regnode);
828
        return p->x.regnode->set<<8 | p->x.regnode->number;
829
}
830
 

powered by: WebSVN 2.1.0

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