00001 #include "c.h"
00002
00003
00004 #define readsreg(p) \
00005 (generic((p)->op)==INDIR && (p)->kids[0]->op==VREG+P)
00006 #define setsrc(d) ((d) && (d)->x.regnode && \
00007 (d)->x.regnode->set == src->x.regnode->set && \
00008 (d)->x.regnode->mask&src->x.regnode->mask)
00009
00010 #define relink(a, b) ((b)->x.prev = (a), (a)->x.next = (b))
00011
00012 static Symbol askfixedreg(Symbol);
00013 static Symbol askreg(Symbol, unsigned*);
00014 static void blkunroll(int, int, int, int, int, int, int[]);
00015 static void docall(Node);
00016 static void dumpcover(Node, int, int);
00017 static void dumpregs(char *, char *, char *);
00018 static void dumprule(int);
00019 static void dumptree(Node);
00020 static unsigned emitasm(Node, int);
00021 static void genreload(Node, Symbol, int);
00022 static void genspill(Symbol, Node, Symbol);
00023 static Symbol getreg(Symbol, unsigned*, Node);
00024 static int getrule(Node, int);
00025 static void linearize(Node, Node);
00026 static int moveself(Node);
00027 static void prelabel(Node);
00028 static Node* prune(Node, Node*);
00029 static void putreg(Symbol);
00030 static void ralloc(Node);
00031 static void reduce(Node, int);
00032 static int reprune(Node*, int, int, Node);
00033 static int requate(Node);
00034 static Node reuse(Node, int);
00035 static void rewrite(Node);
00036 static Symbol spillee(Symbol, unsigned mask[], Node);
00037 static void spillr(Symbol, Node);
00038 static int uses(Node, Regnode);
00039
00040 int offset;
00041
00042 int maxoffset;
00043
00044 int framesize;
00045 int argoffset;
00046
00047 int maxargoffset;
00048
00049 int dalign, salign;
00050 int bflag = 0;
00051 int dflag = 0;
00052
00053 int swap;
00054
00055 unsigned (*emitter)(Node, int) = emitasm;
00056 static char NeedsReg[] = {
00057 0,
00058 1,
00059 0, 0,
00060 1,
00061 0, 0, 1, 1,
00062 1, 0, 1, 1,
00063 1,
00064 1,
00065 0,
00066 1, 1, 1,
00067 1, 1, 1, 1, 1,
00068 1, 1, 1, 1,
00069 1, 1,
00070 0, 0, 0, 0, 0, 0,
00071 0, 0
00072 };
00073 Node head;
00074
00075 unsigned freemask[2];
00076 unsigned usedmask[2];
00077 unsigned tmask[2];
00078 unsigned vmask[2];
00079 Symbol mkreg(char *fmt, int n, int mask, int set) {
00080 Symbol p;
00081
00082 NEW0(p, PERM);
00083 p->name = p->x.name = stringf(fmt, n);
00084 NEW0(p->x.regnode, PERM);
00085 p->x.regnode->number = n;
00086 p->x.regnode->mask = mask<<n;
00087 p->x.regnode->set = set;
00088 return p;
00089 }
00090 Symbol mkwildcard(Symbol *syms) {
00091 Symbol p;
00092
00093 NEW0(p, PERM);
00094 p->name = p->x.name = "wildcard";
00095 p->x.wildcard = syms;
00096 return p;
00097 }
00098 void mkauto(Symbol p) {
00099 assert(p->sclass == AUTO);
00100 offset = roundup(offset + p->type->size, p->type->align);
00101 p->x.offset = -offset;
00102 p->x.name = stringd(-offset);
00103 }
00104 void blockbeg(Env *e) {
00105 e->offset = offset;
00106 e->freemask[IREG] = freemask[IREG];
00107 e->freemask[FREG] = freemask[FREG];
00108 }
00109 void blockend(Env *e) {
00110 if (offset > maxoffset)
00111 maxoffset = offset;
00112 offset = e->offset;
00113 freemask[IREG] = e->freemask[IREG];
00114 freemask[FREG] = e->freemask[FREG];
00115 }
00116 int mkactual(int align, int size) {
00117 int n = roundup(argoffset, align);
00118
00119 argoffset = n + size;
00120 return n;
00121 }
00122 static void docall(Node p) {
00123 p->syms[1] = p->syms[0];
00124 p->syms[0] = intconst(argoffset);
00125 if (argoffset > maxargoffset)
00126 maxargoffset = argoffset;
00127 argoffset = 0;
00128 }
00129 void blkcopy(int dreg, int doff, int sreg, int soff, int size, int tmp[]) {
00130 assert(size >= 0);
00131 if (size == 0)
00132 return;
00133 else if (size <= 2)
00134 blkunroll(size, dreg, doff, sreg, soff, size, tmp);
00135 else if (size == 3) {
00136 blkunroll(2, dreg, doff, sreg, soff, 2, tmp);
00137 blkunroll(1, dreg, doff+2, sreg, soff+2, 1, tmp);
00138 }
00139 else if (size <= 16) {
00140 blkunroll(4, dreg, doff, sreg, soff, size&~3, tmp);
00141 blkcopy(dreg, doff+(size&~3),
00142 sreg, soff+(size&~3), size&3, tmp);
00143 }
00144 else
00145 (*IR->x.blkloop)(dreg, doff, sreg, soff, size, tmp);
00146 }
00147 static void blkunroll(int k, int dreg, int doff, int sreg, int soff, int size, int tmp[]) {
00148 int i;
00149
00150 assert(IR->x.max_unaligned_load);
00151 if (k > IR->x.max_unaligned_load
00152 && (k > salign || k > dalign))
00153 k = IR->x.max_unaligned_load;
00154 for (i = 0; i+k < size; i += 2*k) {
00155 (*IR->x.blkfetch)(k, soff+i, sreg, tmp[0]);
00156 (*IR->x.blkfetch)(k, soff+i+k, sreg, tmp[1]);
00157 (*IR->x.blkstore)(k, doff+i, dreg, tmp[0]);
00158 (*IR->x.blkstore)(k, doff+i+k, dreg, tmp[1]);
00159 }
00160 if (i < size) {
00161 (*IR->x.blkfetch)(k, i+soff, sreg, tmp[0]);
00162 (*IR->x.blkstore)(k, i+doff, dreg, tmp[0]);
00163 }
00164 }
00165 void parseflags(int argc, char *argv[]) {
00166 int i;
00167
00168 for (i = 0; i < argc; i++)
00169 if (strcmp(argv[i], "-d") == 0)
00170 dflag = 1;
00171 else if (strcmp(argv[i], "-b") == 0)
00172 bflag = 1;
00173 }
00174 static int getrule(Node p, int nt) {
00175 int rulenum;
00176
00177 assert(p);
00178 rulenum = (*IR->x._rule)(p->x.state, nt);
00179 if (!rulenum) {
00180 fprint(stderr, "(%x->op=%s at %w is corrupt.)\n", p, opname(p->op), &src);
00181 assert(0);
00182 }
00183 return rulenum;
00184 }
00185 static void reduce(Node p, int nt) {
00186 int rulenum, i;
00187 short *nts;
00188 Node kids[10];
00189
00190 p = reuse(p, nt);
00191 rulenum = getrule(p, nt);
00192 nts = IR->x._nts[rulenum];
00193 (*IR->x._kids)(p, rulenum, kids);
00194 for (i = 0; nts[i]; i++)
00195 reduce(kids[i], nts[i]);
00196 if (IR->x._isinstruction[rulenum]) {
00197 assert(p->x.inst == 0 || p->x.inst == nt);
00198 p->x.inst = nt;
00199 if (p->syms[RX] && p->syms[RX]->temporary) {
00200 debug(fprint(stderr, "(using %s)\n", p->syms[RX]->name));
00201 p->syms[RX]->x.usecount++;
00202 }
00203 }
00204 }
00205 static Node reuse(Node p, int nt) {
00206 struct _state {
00207 short cost[1];
00208 };
00209 Symbol r = p->syms[RX];
00210
00211 if (generic(p->op) == INDIR && p->kids[0]->op == VREG+P
00212 && r->u.t.cse && p->x.mayrecalc
00213 && ((struct _state*)r->u.t.cse->x.state)->cost[nt] == 0)
00214 return r->u.t.cse;
00215 else
00216 return p;
00217 }
00218
00219 int mayrecalc(Node p) {
00220 int op;
00221
00222 assert(p && p->syms[RX]);
00223 if (p->syms[RX]->u.t.cse == NULL)
00224 return 0;
00225 op = generic(p->syms[RX]->u.t.cse->op);
00226 if (op == CNST || op == ADDRF || op == ADDRG || op == ADDRL) {
00227 p->x.mayrecalc = 1;
00228 return 1;
00229 } else
00230 return 0;
00231 }
00232 static Node *prune(Node p, Node pp[]) {
00233 if (p == NULL)
00234 return pp;
00235 p->x.kids[0] = p->x.kids[1] = p->x.kids[2] = NULL;
00236 if (p->x.inst == 0)
00237 return prune(p->kids[1], prune(p->kids[0], pp));
00238 else if (p->syms[RX] && p->syms[RX]->temporary
00239 && p->syms[RX]->x.usecount < 2) {
00240 p->x.inst = 0;
00241 debug(fprint(stderr, "(clobbering %s)\n", p->syms[RX]->name));
00242 return prune(p->kids[1], prune(p->kids[0], pp));
00243 }
00244 else {
00245 prune(p->kids[1], prune(p->kids[0], &p->x.kids[0]));
00246 *pp = p;
00247 return pp + 1;
00248 }
00249 }
00250
00251 #define ck(i) return (i) ? 0 : LBURG_MAX
00252
00253 int range(Node p, int lo, int hi) {
00254 Symbol s = p->syms[0];
00255
00256 switch (specific(p->op)) {
00257 case ADDRF+P:
00258 case ADDRL+P: ck(s->x.offset >= lo && s->x.offset <= hi);
00259 case CNST+I: ck(s->u.c.v.i >= lo && s->u.c.v.i <= hi);
00260 case CNST+U: ck(s->u.c.v.u >= lo && s->u.c.v.u <= hi);
00261 case CNST+P: ck(s->u.c.v.p == 0 && lo <= 0 && hi >= 0);
00262 }
00263 return LBURG_MAX;
00264 }
00265 static void dumptree(Node p) {
00266 if (p->op == VREG+P && p->syms[0]) {
00267 fprint(stderr, "VREGP(%s)", p->syms[0]->name);
00268 return;
00269 } else if (generic(p->op) == LOAD) {
00270 fprint(stderr, "LOAD(");
00271 dumptree(p->kids[0]);
00272 fprint(stderr, ")");
00273 return;
00274 }
00275 fprint(stderr, "%s(", opname(p->op));
00276 switch (generic(p->op)) {
00277 case CNST: case LABEL:
00278 case ADDRG: case ADDRF: case ADDRL:
00279 if (p->syms[0])
00280 fprint(stderr, "%s", p->syms[0]->name);
00281 break;
00282 case RET:
00283 if (p->kids[0])
00284 dumptree(p->kids[0]);
00285 break;
00286 case CVF: case CVI: case CVP: case CVU: case JUMP:
00287 case ARG: case BCOM: case NEG: case INDIR:
00288 dumptree(p->kids[0]);
00289 break;
00290 case CALL:
00291 if (optype(p->op) != B) {
00292 dumptree(p->kids[0]);
00293 break;
00294 }
00295
00296 case EQ: case NE: case GT: case GE: case LE: case LT:
00297 case ASGN: case BOR: case BAND: case BXOR: case RSH: case LSH:
00298 case ADD: case SUB: case DIV: case MUL: case MOD:
00299 dumptree(p->kids[0]);
00300 fprint(stderr, ", ");
00301 dumptree(p->kids[1]);
00302 break;
00303 default: assert(0);
00304 }
00305 fprint(stderr, ")");
00306 }
00307 static void dumpcover(Node p, int nt, int in) {
00308 int rulenum, i;
00309 short *nts;
00310 Node kids[10];
00311
00312 p = reuse(p, nt);
00313 rulenum = getrule(p, nt);
00314 nts = IR->x._nts[rulenum];
00315 fprint(stderr, "dumpcover(%x) = ", p);
00316 for (i = 0; i < in; i++)
00317 fprint(stderr, " ");
00318 dumprule(rulenum);
00319 (*IR->x._kids)(p, rulenum, kids);
00320 for (i = 0; nts[i]; i++)
00321 dumpcover(kids[i], nts[i], in+1);
00322 }
00323
00324 static void dumprule(int rulenum) {
00325 assert(rulenum);
00326 fprint(stderr, "%s / %s", IR->x._string[rulenum],
00327 IR->x._templates[rulenum]);
00328 if (!IR->x._isinstruction[rulenum])
00329 fprint(stderr, "\n");
00330 }
00331 static unsigned emitasm(Node p, int nt) {
00332 int rulenum;
00333 short *nts;
00334 char *fmt;
00335 Node kids[10];
00336
00337 p = reuse(p, nt);
00338 rulenum = getrule(p, nt);
00339 nts = IR->x._nts[rulenum];
00340 fmt = IR->x._templates[rulenum];
00341 assert(fmt);
00342 if (IR->x._isinstruction[rulenum] && p->x.emitted)
00343 print("%s", p->syms[RX]->x.name);
00344 else if (*fmt == '#')
00345 (*IR->x.emit2)(p);
00346 else {
00347 if (*fmt == '?') {
00348 fmt++;
00349 assert(p->kids[0]);
00350 if (p->syms[RX] == p->x.kids[0]->syms[RX])
00351 while (*fmt++ != '\n')
00352 ;
00353 }
00354 for ((*IR->x._kids)(p, rulenum, kids); *fmt; fmt++)
00355 if (*fmt != '%')
00356 (void)putchar(*fmt);
00357 else if (*++fmt == 'F')
00358 print("%d", framesize);
00359 else if (*fmt >= '0' && *fmt <= '9')
00360 emitasm(kids[*fmt - '0'], nts[*fmt - '0']);
00361 else if (*fmt >= 'a' && *fmt < 'a' + NELEMS(p->syms))
00362 fputs(p->syms[*fmt - 'a']->x.name, stdout);
00363 else
00364 (void)putchar(*fmt);
00365 }
00366 return 0;
00367 }
00368 void emit(Node p) {
00369 for (; p; p = p->x.next) {
00370 assert(p->x.registered);
00371 if (p->x.equatable && requate(p) || moveself(p))
00372 ;
00373 else
00374 (*emitter)(p, p->x.inst);
00375 p->x.emitted = 1;
00376 }
00377 }
00378 static int moveself(Node p) {
00379 return p->x.copy
00380 && p->syms[RX]->x.name == p->x.kids[0]->syms[RX]->x.name;
00381 }
00382 int move(Node p) {
00383 p->x.copy = 1;
00384 return 1;
00385 }
00386 static int requate(Node q) {
00387 Symbol src = q->x.kids[0]->syms[RX];
00388 Symbol tmp = q->syms[RX];
00389 Node p;
00390 int n = 0;
00391
00392 debug(fprint(stderr, "(requate(%x): tmp=%s src=%s)\n", q, tmp->x.name, src->x.name));
00393 for (p = q->x.next; p; p = p->x.next)
00394 if (p->x.copy && p->syms[RX] == src
00395 && p->x.kids[0]->syms[RX] == tmp)
00396 debug(fprint(stderr, "(requate arm 0 at %x)\n", p)),
00397 p->syms[RX] = tmp;
00398 else if (setsrc(p->syms[RX]) && !moveself(p) && !readsreg(p))
00399 return 0;
00400 else if (p->x.spills)
00401 return 0;
00402 else if (generic(p->op) == CALL && p->x.next)
00403 return 0;
00404 else if (p->op == LABEL+V && p->x.next)
00405 return 0;
00406 else if (p->syms[RX] == tmp && readsreg(p))
00407 debug(fprint(stderr, "(requate arm 5 at %x)\n", p)),
00408 n++;
00409 else if (p->syms[RX] == tmp)
00410 break;
00411 debug(fprint(stderr, "(requate arm 7 at %x)\n", p));
00412 assert(n > 0);
00413 for (p = q->x.next; p; p = p->x.next)
00414 if (p->syms[RX] == tmp && readsreg(p)) {
00415 p->syms[RX] = src;
00416 if (--n <= 0)
00417 break;
00418 }
00419 return 1;
00420 }
00421 static void prelabel(Node p) {
00422 if (p == NULL)
00423 return;
00424 prelabel(p->kids[0]);
00425 prelabel(p->kids[1]);
00426 if (NeedsReg[opindex(p->op)])
00427 setreg(p, (*IR->x.rmap)(opkind(p->op)));
00428 switch (generic(p->op)) {
00429 case ADDRF: case ADDRL:
00430 if (p->syms[0]->sclass == REGISTER)
00431 p->op = VREG+P;
00432 break;
00433 case INDIR:
00434 if (p->kids[0]->op == VREG+P)
00435 setreg(p, p->kids[0]->syms[0]);
00436 break;
00437 case ASGN:
00438 if (p->kids[0]->op == VREG+P)
00439 rtarget(p, 1, p->kids[0]->syms[0]);
00440 break;
00441 case CVI: case CVU: case CVP:
00442 if (optype(p->op) != F
00443 && opsize(p->op) <= p->syms[0]->u.c.v.i)
00444 p->op = LOAD + opkind(p->op);
00445 break;
00446 }
00447 (IR->x.target)(p);
00448 }
00449 void setreg(Node p, Symbol r) {
00450 p->syms[RX] = r;
00451 }
00452 void rtarget(Node p, int n, Symbol r) {
00453 Node q = p->kids[n];
00454
00455 assert(q);
00456 assert(r);
00457 assert(r->sclass == REGISTER || !r->x.wildcard);
00458 assert(q->syms[RX]);
00459 if (r != q->syms[RX] && !q->syms[RX]->x.wildcard) {
00460 q = newnode(LOAD + opkind(q->op),
00461 q, NULL, q->syms[0]);
00462 if (r->u.t.cse == p->kids[n])
00463 r->u.t.cse = q;
00464 p->kids[n] = p->x.kids[n] = q;
00465 q->x.kids[0] = q->kids[0];
00466 }
00467 setreg(q, r);
00468 debug(fprint(stderr, "(targeting %x->x.kids[%d]=%x to %s)\n", p, n, p->kids[n], r->x.name));
00469 }
00470 static void rewrite(Node p) {
00471 assert(p->x.inst == 0);
00472 prelabel(p);
00473 debug(dumptree(p));
00474 debug(fprint(stderr, "\n"));
00475 (*IR->x._label)(p);
00476 debug(dumpcover(p, 1, 0));
00477 reduce(p, 1);
00478 }
00479 Node gen(Node forest) {
00480 int i;
00481 struct node sentinel;
00482 Node dummy, p;
00483
00484 head = forest;
00485 for (p = forest; p; p = p->link) {
00486 assert(p->count == 0);
00487 if (generic(p->op) == CALL)
00488 docall(p);
00489 else if ( generic(p->op) == ASGN
00490 && generic(p->kids[1]->op) == CALL)
00491 docall(p->kids[1]);
00492 else if (generic(p->op) == ARG)
00493 (*IR->x.doarg)(p);
00494 rewrite(p);
00495 p->x.listed = 1;
00496 }
00497 for (p = forest; p; p = p->link)
00498 prune(p, &dummy);
00499 relink(&sentinel, &sentinel);
00500 for (p = forest; p; p = p->link)
00501 linearize(p, &sentinel);
00502 forest = sentinel.x.next;
00503 assert(forest);
00504 sentinel.x.next->x.prev = NULL;
00505 sentinel.x.prev->x.next = NULL;
00506 for (p = forest; p; p = p->x.next)
00507 for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
00508 assert(p->x.kids[i]->syms[RX]);
00509 if (p->x.kids[i]->syms[RX]->temporary) {
00510 p->x.kids[i]->x.prevuse =
00511 p->x.kids[i]->syms[RX]->x.lastuse;
00512 p->x.kids[i]->syms[RX]->x.lastuse = p->x.kids[i];
00513 }
00514 }
00515 for (p = forest; p; p = p->x.next) {
00516 ralloc(p);
00517 if (p->x.listed && NeedsReg[opindex(p->op)]
00518 && (*IR->x.rmap)(opkind(p->op))) {
00519 assert(generic(p->op) == CALL || generic(p->op) == LOAD);
00520 putreg(p->syms[RX]);
00521 }
00522 }
00523 return forest;
00524 }
00525 int notarget(Node p) {
00526 return p->syms[RX]->x.wildcard ? 0 : LBURG_MAX;
00527 }
00528 static void putreg(Symbol r) {
00529 assert(r && r->x.regnode);
00530 freemask[r->x.regnode->set] |= r->x.regnode->mask;
00531 debug(dumpregs("(freeing %s)\n", r->x.name, NULL));
00532 }
00533 static Symbol askfixedreg(Symbol s) {
00534 Regnode r = s->x.regnode;
00535 int n = r->set;
00536
00537 if (r->mask&~freemask[n])
00538 return NULL;
00539 else {
00540 freemask[n] &= ~r->mask;
00541 usedmask[n] |= r->mask;
00542 return s;
00543 }
00544 }
00545 static Symbol askreg(Symbol rs, unsigned rmask[]) {
00546 int i;
00547
00548 if (rs->x.wildcard == NULL)
00549 return askfixedreg(rs);
00550 for (i = 31; i >= 0; i--) {
00551 Symbol r = rs->x.wildcard[i];
00552 if (r != NULL
00553 && !(r->x.regnode->mask&~rmask[r->x.regnode->set])
00554 && askfixedreg(r))
00555 return r;
00556 }
00557 return NULL;
00558 }
00559
00560 static Symbol getreg(Symbol s, unsigned mask[], Node p) {
00561 Symbol r = askreg(s, mask);
00562 if (r == NULL) {
00563 r = spillee(s, mask, p);
00564 assert(r && r->x.regnode);
00565 spill(r->x.regnode->mask, r->x.regnode->set, p);
00566 r = askreg(s, mask);
00567 }
00568 assert(r && r->x.regnode);
00569 r->x.regnode->vbl = NULL;
00570 return r;
00571 }
00572 int askregvar(Symbol p, Symbol regs) {
00573 Symbol r;
00574
00575 assert(p);
00576 if (p->sclass != REGISTER)
00577 return 0;
00578 else if (!isscalar(p->type)) {
00579 p->sclass = AUTO;
00580 return 0;
00581 }
00582 else if (p->temporary) {
00583 p->x.name = "?";
00584 return 1;
00585 }
00586 else if ((r = askreg(regs, vmask)) != NULL) {
00587 p->x.regnode = r->x.regnode;
00588 p->x.regnode->vbl = p;
00589 p->x.name = r->x.name;
00590 debug(dumpregs("(allocating %s to symbol %s)\n", p->x.name, p->name));
00591 return 1;
00592 }
00593 else {
00594 p->sclass = AUTO;
00595 return 0;
00596 }
00597 }
00598 static void linearize(Node p, Node next) {
00599 int i;
00600
00601 for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
00602 linearize(p->x.kids[i], next);
00603 relink(next->x.prev, p);
00604 relink(p, next);
00605 debug(fprint(stderr, "(listing %x)\n", p));
00606 }
00607 static void ralloc(Node p) {
00608 int i;
00609 unsigned mask[2];
00610
00611 mask[0] = tmask[0];
00612 mask[1] = tmask[1];
00613 assert(p);
00614 debug(fprint(stderr, "(rallocing %x)\n", p));
00615 for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
00616 Node kid = p->x.kids[i];
00617 Symbol r = kid->syms[RX];
00618 assert(r && kid->x.registered);
00619 if (r->sclass != REGISTER && r->x.lastuse == kid)
00620 putreg(r);
00621 }
00622 if (!p->x.registered && NeedsReg[opindex(p->op)]
00623 && (*IR->x.rmap)(opkind(p->op))) {
00624 Symbol sym = p->syms[RX], set = sym;
00625 assert(sym);
00626 if (sym->temporary)
00627 set = (*IR->x.rmap)(opkind(p->op));
00628 assert(set);
00629 if (set->sclass != REGISTER) {
00630 Symbol r;
00631 if (*IR->x._templates[getrule(p, p->x.inst)] == '?')
00632 for (i = 1; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
00633 Symbol r = p->x.kids[i]->syms[RX];
00634 assert(p->x.kids[i]->x.registered);
00635 assert(r && r->x.regnode);
00636 assert(sym->x.wildcard || sym != r);
00637 mask[r->x.regnode->set] &= ~r->x.regnode->mask;
00638 }
00639 r = getreg(set, mask, p);
00640 if (sym->temporary) {
00641 Node q;
00642 r->x.lastuse = sym->x.lastuse;
00643 for (q = sym->x.lastuse; q; q = q->x.prevuse) {
00644 q->syms[RX] = r;
00645 q->x.registered = 1;
00646 if (sym->u.t.cse && q->x.copy)
00647 q->x.equatable = 1;
00648 }
00649 } else {
00650 p->syms[RX] = r;
00651 r->x.lastuse = p;
00652 }
00653 debug(dumpregs("(allocating %s to node %x)\n", r->x.name, (char *) p));
00654 }
00655 }
00656 p->x.registered = 1;
00657 (*IR->x.clobber)(p);
00658 }
00659 static Symbol spillee(Symbol set, unsigned mask[], Node here) {
00660 Symbol bestreg = NULL;
00661 int bestdist = -1, i;
00662
00663 assert(set);
00664 if (!set->x.wildcard)
00665 bestreg = set;
00666 else {
00667 for (i = 31; i >= 0; i--) {
00668 Symbol ri = set->x.wildcard[i];
00669 if (
00670 ri != NULL &&
00671 ri->x.lastuse &&
00672 (ri->x.regnode->mask&tmask[ri->x.regnode->set]&mask[ri->x.regnode->set])
00673 ) {
00674 Regnode rn = ri->x.regnode;
00675 Node q = here;
00676 int dist = 0;
00677 for (; q && !uses(q, rn); q = q->x.next)
00678 dist++;
00679 if (q && dist > bestdist) {
00680 bestdist = dist;
00681 bestreg = ri;
00682 }
00683 }
00684 }
00685 }
00686 assert(bestreg);
00687
00688
00689 assert(bestreg->x.regnode->vbl == NULL);
00690
00691
00692 return bestreg;
00693 }
00694 static int uses(Node p, Regnode rn) {
00695 int i;
00696
00697 for (i = 0; i < NELEMS(p->x.kids); i++)
00698 if (
00699 p->x.kids[i] &&
00700 p->x.kids[i]->x.registered &&
00701 rn->set == p->x.kids[i]->syms[RX]->x.regnode->set &&
00702 (rn->mask&p->x.kids[i]->syms[RX]->x.regnode->mask)
00703 )
00704 return 1;
00705 return 0;
00706 }
00707 static void spillr(Symbol r, Node here) {
00708 int i;
00709 Symbol tmp;
00710 Node p = r->x.lastuse;
00711 assert(p);
00712 while (p->x.prevuse)
00713 assert(r == p->syms[RX]),
00714 p = p->x.prevuse;
00715 assert(p->x.registered && !readsreg(p));
00716 tmp = newtemp(AUTO, optype(p->op), opsize(p->op));
00717 genspill(r, p, tmp);
00718 for (p = here->x.next; p; p = p->x.next)
00719 for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
00720 Node k = p->x.kids[i];
00721 if (k->x.registered && k->syms[RX] == r)
00722 genreload(p, tmp, i);
00723 }
00724 putreg(r);
00725 }
00726 static void genspill(Symbol r, Node last, Symbol tmp) {
00727 Node p, q;
00728 Symbol s;
00729 unsigned ty;
00730
00731 debug(fprint(stderr, "(spilling %s to local %s)\n", r->x.name, tmp->x.name));
00732 debug(fprint(stderr, "(genspill: "));
00733 debug(dumptree(last));
00734 debug(fprint(stderr, ")\n"));
00735 ty = opkind(last->op);
00736 NEW0(s, FUNC);
00737 s->sclass = REGISTER;
00738 s->name = s->x.name = r->x.name;
00739 s->x.regnode = r->x.regnode;
00740 q = newnode(ADDRL+