diff options
Diffstat (limited to 'src/cmd/5g/reg.c')
-rw-r--r-- | src/cmd/5g/reg.c | 812 |
1 files changed, 163 insertions, 649 deletions
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c index eaaaf9be3..d2a8cc488 100644 --- a/src/cmd/5g/reg.c +++ b/src/cmd/5g/reg.c @@ -36,29 +36,10 @@ #define NREGVAR 32 #define REGBITS ((uint32)0xffffffff) -#define P2R(p) (Reg*)(p->reg) void addsplits(void); - int noreturn(Prog *p); -static int first = 0; - -static void fixjmp(Prog*); - - -Reg* -rega(void) -{ - Reg *r; - - r = freer; - if(r == R) { - r = mal(sizeof(*r)); - } else - freer = r->link; - - *r = zreg; - return r; -} +static Reg* firstr; +static int first = 1; int rcmp(const void *a1, const void *a2) @@ -100,7 +81,7 @@ setoutvar(void) } void -excise(Reg *r) +excise(Flow *r) { Prog *p; @@ -177,38 +158,19 @@ regopt(Prog *firstp) { Reg *r, *r1; Prog *p; - int i, z, nr; + Graph *g; + int i, z; uint32 vreg; Bits bit; - - if(first == 0) { + ProgInfo info; + + if(first) { fmtinstall('Q', Qconv); + first = 0; } fixjmp(firstp); - - first++; - if(debug['K']) { - if(first != 13) - return; -// debug['R'] = 2; -// debug['P'] = 2; - print("optimizing %S\n", curfn->nname->sym); - } - - // count instructions - nr = 0; - for(p=firstp; p!=P; p=p->link) - nr++; - - // if too big dont bother - if(nr >= 10000) { -// print("********** %S is too big (%d)\n", curfn->nname->sym, nr); - return; - } - - firstr = R; - lastr = R; + mergetemp(firstp); /* * control flow is more complicated in generated go code @@ -241,178 +203,43 @@ regopt(Prog *firstp) * allocate pcs * find use and set of variables */ - nr = 0; - for(p=firstp; p != P; p = p->link) { - switch(p->as) { - case ADATA: - case AGLOBL: - case ANAME: - case ASIGNAME: - case ALOCALS: - case ATYPE: - continue; - } - r = rega(); - nr++; - if(firstr == R) { - firstr = r; - lastr = r; - } else { - lastr->link = r; - r->p1 = lastr; - lastr->s1 = r; - lastr = r; - } - r->prog = p; - p->regp = r; - - r1 = r->p1; - if(r1 != R) { - switch(r1->prog->as) { - case ARET: - case AB: - case ARFE: - r->p1 = R; - r1->s1 = R; - } - } + g = flowstart(firstp, sizeof(Reg)); + if(g == nil) + return; + firstr = (Reg*)g->start; + + for(r = firstr; r != R; r = (Reg*)r->f.link) { + p = r->f.prog; + proginfo(&info, p); // Avoid making variables for direct-called functions. if(p->as == ABL && p->to.type == D_EXTERN) continue; - /* - * left side always read - */ bit = mkvar(r, &p->from); - for(z=0; z<BITS; z++) - r->use1.b[z] |= bit.b[z]; - - /* - * middle always read when present - */ - if(p->reg != NREG) { + if(info.flags & LeftRead) + for(z=0; z<BITS; z++) + r->use1.b[z] |= bit.b[z]; + if(info.flags & LeftAddr) + setaddrs(bit); + + if(info.flags & RegRead) { if(p->from.type != D_FREG) r->use1.b[0] |= RtoB(p->reg); else r->use1.b[0] |= FtoB(p->reg); } - /* - * right side depends on opcode - */ - bit = mkvar(r, &p->to); - if(bany(&bit)) - switch(p->as) { - default: - yyerror("reg: unknown op: %A", p->as); - break; - - /* - * right side read - */ - case ATST: - case ATEQ: - case ACMP: - case ACMN: - case ACMPD: - case ACMPF: - rightread: - for(z=0; z<BITS; z++) - r->use2.b[z] |= bit.b[z]; - break; - - /* - * right side read or read+write, depending on middle - * ADD x, z => z += x - * ADD x, y, z => z = x + y - */ - case AADD: - case AAND: - case AEOR: - case ASUB: - case ARSB: - case AADC: - case ASBC: - case ARSC: - case AORR: - case ABIC: - case ASLL: - case ASRL: - case ASRA: - case AMUL: - case AMULU: - case ADIV: - case AMOD: - case AMODU: - case ADIVU: - if(p->reg != NREG) - goto rightread; - // fall through - - /* - * right side read+write - */ - case AADDF: - case AADDD: - case ASUBF: - case ASUBD: - case AMULF: - case AMULD: - case ADIVF: - case ADIVD: - case AMULA: - case AMULAL: - case AMULALU: - for(z=0; z<BITS; z++) { - r->use2.b[z] |= bit.b[z]; - r->set.b[z] |= bit.b[z]; - } - break; - - /* - * right side write - */ - case ANOP: - case AMOVB: - case AMOVBU: - case AMOVD: - case AMOVDF: - case AMOVDW: - case AMOVF: - case AMOVFW: - case AMOVH: - case AMOVHU: - case AMOVW: - case AMOVWD: - case AMOVWF: - case AMVN: - case AMULL: - case AMULLU: - if((p->scond & C_SCOND) != C_SCOND_NONE) + if(info.flags & (RightAddr | RightRead | RightWrite)) { + bit = mkvar(r, &p->to); + if(info.flags & RightAddr) + setaddrs(bit); + if(info.flags & RightRead) for(z=0; z<BITS; z++) r->use2.b[z] |= bit.b[z]; - for(z=0; z<BITS; z++) - r->set.b[z] |= bit.b[z]; - break; - - /* - * funny - */ - case ABL: - setaddrs(bit); - break; - } - - if(p->as == AMOVM) { - z = p->to.offset; - if(p->from.type == D_CONST) - z = p->from.offset; - for(i=0; z; i++) { - if(z&1) - regbits |= RtoB(i); - z >>= 1; - } + if(info.flags & RightWrite) + for(z=0; z<BITS; z++) + r->set.b[z] |= bit.b[z]; } } if(firstr == R) @@ -432,50 +259,16 @@ regopt(Prog *firstp) } if(debug['R'] && debug['v']) - dumpit("pass1", firstr); + dumpit("pass1", &firstr->f, 1); /* * pass 2 - * turn branch references to pointers - * build back pointers - */ - for(r=firstr; r!=R; r=r->link) { - p = r->prog; - if(p->to.type == D_BRANCH) { - if(p->to.u.branch == P) - fatal("pnil %P", p); - r1 = p->to.u.branch->regp; - if(r1 == R) - fatal("rnil %P", p); - if(r1 == r) { - //fatal("ref to self %P", p); - continue; - } - r->s2 = r1; - r->p2link = r1->p2; - r1->p2 = r; - } - } - if(debug['R']) { - p = firstr->prog; - print("\n%L %D\n", p->lineno, &p->from); - print(" addr = %Q\n", addrs); - } - - if(debug['R'] && debug['v']) - dumpit("pass2", firstr); - - /* - * pass 2.5 * find looping structure */ - for(r = firstr; r != R; r = r->link) - r->active = 0; - change = 0; - loopit(firstr, nr); + flowrpo(g); if(debug['R'] && debug['v']) - dumpit("pass2.5", firstr); + dumpit("pass2", &firstr->f, 1); /* * pass 3 @@ -484,17 +277,17 @@ regopt(Prog *firstp) */ loop1: change = 0; - for(r = firstr; r != R; r = r->link) - r->active = 0; - for(r = firstr; r != R; r = r->link) - if(r->prog->as == ARET) + for(r = firstr; r != R; r = (Reg*)r->f.link) + r->f.active = 0; + for(r = firstr; r != R; r = (Reg*)r->f.link) + if(r->f.prog->as == ARET) prop(r, zbits, zbits); loop11: /* pick up unreachable code */ i = 0; for(r = firstr; r != R; r = r1) { - r1 = r->link; - if(r1 && r1->active && !r->active) { + r1 = (Reg*)r->f.link; + if(r1 && r1->f.active && !r->f.active) { prop(r, zbits, zbits); i = 1; } @@ -505,7 +298,7 @@ loop11: goto loop1; if(debug['R'] && debug['v']) - dumpit("pass3", firstr); + dumpit("pass3", &firstr->f, 1); /* @@ -515,8 +308,8 @@ loop11: */ loop2: change = 0; - for(r = firstr; r != R; r = r->link) - r->active = 0; + for(r = firstr; r != R; r = (Reg*)r->f.link) + r->f.active = 0; synch(firstr, zbits); if(change) goto loop2; @@ -524,12 +317,12 @@ loop2: addsplits(); if(debug['R'] && debug['v']) - dumpit("pass4", firstr); + dumpit("pass4", &firstr->f, 1); if(debug['R'] > 1) { print("\nprop structure:\n"); - for(r = firstr; r != R; r = r->link) { - print("%d:%P", r->loop, r->prog); + for(r = firstr; r != R; r = (Reg*)r->f.link) { + print("%d:%P", r->f.loop, r->f.prog); for(z=0; z<BITS; z++) { bit.b[z] = r->set.b[z] | r->refahead.b[z] | r->calahead.b[z] | @@ -563,7 +356,7 @@ loop2: * pass 4.5 * move register pseudo-variables into regu. */ - for(r = firstr; r != R; r = r->link) { + for(r = firstr; r != R; r = (Reg*)r->f.link) { r->regu = (r->refbehind.b[0] | r->set.b[0]) & REGBITS; r->set.b[0] &= ~REGBITS; @@ -578,7 +371,7 @@ loop2: } if(debug['R'] && debug['v']) - dumpit("pass4.5", firstr); + dumpit("pass4.5", &firstr->f, 1); /* * pass 5 @@ -590,27 +383,27 @@ loop2: for(z=0; z<BITS; z++) bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) & ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]); - if(bany(&bit) & !r->refset) { + if(bany(&bit) & !r->f.refset) { // should never happen - all variables are preset if(debug['w']) - print("%L: used and not set: %Q\n", r->prog->lineno, bit); - r->refset = 1; + print("%L: used and not set: %Q\n", r->f.prog->lineno, bit); + r->f.refset = 1; } } - for(r = firstr; r != R; r = r->link) + for(r = firstr; r != R; r = (Reg*)r->f.link) r->act = zbits; rgp = region; nregion = 0; - for(r = firstr; r != R; r = r->link) { + for(r = firstr; r != R; r = (Reg*)r->f.link) { for(z=0; z<BITS; z++) bit.b[z] = r->set.b[z] & ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]); - if(bany(&bit) && !r->refset) { + if(bany(&bit) && !r->f.refset) { if(debug['w']) - print("%L: set and not used: %Q\n", r->prog->lineno, bit); - r->refset = 1; - excise(r); + print("%L: set and not used: %Q\n", r->f.prog->lineno, bit); + r->f.refset = 1; + excise(&r->f); } for(z=0; z<BITS; z++) bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]); @@ -626,7 +419,7 @@ loop2: if(change <= 0) { if(debug['R']) print("%L $%d: %Q\n", - r->prog->lineno, change, blsh(i)); + r->f.prog->lineno, change, blsh(i)); continue; } rgp->cost = change; @@ -643,7 +436,7 @@ brk: qsort(region, nregion, sizeof(region[0]), rcmp); if(debug['R'] && debug['v']) - dumpit("pass5", firstr); + dumpit("pass5", &firstr->f, 1); /* * pass 6 @@ -658,13 +451,13 @@ brk: if(debug['R']) { if(rgp->regno >= NREG) print("%L $%d F%d: %Q\n", - rgp->enter->prog->lineno, + rgp->enter->f.prog->lineno, rgp->cost, rgp->regno-NREG, bit); else print("%L $%d R%d: %Q\n", - rgp->enter->prog->lineno, + rgp->enter->f.prog->lineno, rgp->cost, rgp->regno, bit); @@ -675,18 +468,18 @@ brk: } if(debug['R'] && debug['v']) - dumpit("pass6", firstr); + dumpit("pass6", &firstr->f, 1); /* * pass 7 * peep-hole on basic block */ if(!debug['R'] || debug['P']) { - peep(); + peep(firstp); } if(debug['R'] && debug['v']) - dumpit("pass7", firstr); + dumpit("pass7", &firstr->f, 1); /* * last pass @@ -742,11 +535,8 @@ brk: } } } - if(lastr != R) { - lastr->link = freer; - freer = firstr; - } + flowend(g); } void @@ -756,13 +546,13 @@ addsplits(void) int z, i; Bits bit; - for(r = firstr; r != R; r = r->link) { - if(r->loop > 1) + for(r = firstr; r != R; r = (Reg*)r->f.link) { + if(r->f.loop > 1) continue; - if(r->prog->as == ABL) + if(r->f.prog->as == ABL) continue; - for(r1 = r->p2; r1 != R; r1 = r1->p2link) { - if(r1->loop <= 1) + for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link) { + if(r1->f.loop <= 1) continue; for(z=0; z<BITS; z++) bit.b[z] = r1->calbehind.b[z] & @@ -789,7 +579,7 @@ addmove(Reg *r, int bn, int rn, int f) p1 = mal(sizeof(*p1)); *p1 = zprog; - p = r->prog; + p = r->f.prog; // If there's a stack fixup coming (after BL newproc or BL deferproc), // delay the load until after the fixup. @@ -814,14 +604,14 @@ addmove(Reg *r, int bn, int rn, int f) a->type = D_CONST; if(v->addr) - fatal("addmove: shouldnt be doing this %A\n", a); + fatal("addmove: shouldn't be doing this %A\n", a); switch(v->etype) { default: print("What is this %E\n", v->etype); case TINT8: - p1->as = AMOVB; + p1->as = AMOVBS; break; case TBOOL: case TUINT8: @@ -829,7 +619,7 @@ addmove(Reg *r, int bn, int rn, int f) p1->as = AMOVBU; break; case TINT16: - p1->as = AMOVH; + p1->as = AMOVHS; break; case TUINT16: p1->as = AMOVHU; @@ -908,9 +698,6 @@ mkvar(Reg *r, Adr *a) case D_BRANCH: break; - case D_CONST: - flag = 1; - goto onereg; case D_REGREG: case D_REGREG2: @@ -921,9 +708,9 @@ mkvar(Reg *r, Adr *a) bit.b[0] |= RtoB(a->reg); return bit; + case D_CONST: case D_REG: case D_SHIFT: - onereg: if(a->reg != NREG) { bit = zbits; bit.b[0] = RtoB(a->reg); @@ -933,11 +720,11 @@ mkvar(Reg *r, Adr *a) case D_OREG: if(a->reg != NREG) { - if(a == &r->prog->from) + if(a == &r->f.prog->from) r->use1.b[0] |= RtoB(a->reg); else r->use2.b[0] |= RtoB(a->reg); - if(r->prog->scond & (C_PBIT|C_WBIT)) + if(r->f.prog->scond & (C_PBIT|C_WBIT)) r->set.b[0] |= RtoB(a->reg); } break; @@ -1040,7 +827,7 @@ prop(Reg *r, Bits ref, Bits cal) Reg *r1, *r2; int z; - for(r1 = r; r1 != R; r1 = r1->p1) { + for(r1 = r; r1 != R; r1 = (Reg*)r1->f.p1) { for(z=0; z<BITS; z++) { ref.b[z] |= r1->refahead.b[z]; if(ref.b[z] != r1->refahead.b[z]) { @@ -1053,9 +840,9 @@ prop(Reg *r, Bits ref, Bits cal) change++; } } - switch(r1->prog->as) { + switch(r1->f.prog->as) { case ABL: - if(noreturn(r1->prog)) + if(noreturn(r1->f.prog)) break; for(z=0; z<BITS; z++) { cal.b[z] |= ref.b[z] | externs.b[z]; @@ -1095,158 +882,22 @@ prop(Reg *r, Bits ref, Bits cal) r1->refbehind.b[z] = ref.b[z]; r1->calbehind.b[z] = cal.b[z]; } - if(r1->active) + if(r1->f.active) break; - r1->active = 1; + r1->f.active = 1; } - for(; r != r1; r = r->p1) - for(r2 = r->p2; r2 != R; r2 = r2->p2link) + for(; r != r1; r = (Reg*)r->f.p1) + for(r2 = (Reg*)r->f.p2; r2 != R; r2 = (Reg*)r2->f.p2link) prop(r2, r->refbehind, r->calbehind); } -/* - * find looping structure - * - * 1) find reverse postordering - * 2) find approximate dominators, - * the actual dominators if the flow graph is reducible - * otherwise, dominators plus some other non-dominators. - * See Matthew S. Hecht and Jeffrey D. Ullman, - * "Analysis of a Simple Algorithm for Global Data Flow Problems", - * Conf. Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts, - * Oct. 1-3, 1973, pp. 207-217. - * 3) find all nodes with a predecessor dominated by the current node. - * such a node is a loop head. - * recursively, all preds with a greater rpo number are in the loop - */ -int32 -postorder(Reg *r, Reg **rpo2r, int32 n) -{ - Reg *r1; - - r->rpo = 1; - r1 = r->s1; - if(r1 && !r1->rpo) - n = postorder(r1, rpo2r, n); - r1 = r->s2; - if(r1 && !r1->rpo) - n = postorder(r1, rpo2r, n); - rpo2r[n] = r; - n++; - return n; -} - -int32 -rpolca(int32 *idom, int32 rpo1, int32 rpo2) -{ - int32 t; - - if(rpo1 == -1) - return rpo2; - while(rpo1 != rpo2){ - if(rpo1 > rpo2){ - t = rpo2; - rpo2 = rpo1; - rpo1 = t; - } - while(rpo1 < rpo2){ - t = idom[rpo2]; - if(t >= rpo2) - fatal("bad idom"); - rpo2 = t; - } - } - return rpo1; -} - -int -doms(int32 *idom, int32 r, int32 s) -{ - while(s > r) - s = idom[s]; - return s == r; -} - -int -loophead(int32 *idom, Reg *r) -{ - int32 src; - - src = r->rpo; - if(r->p1 != R && doms(idom, src, r->p1->rpo)) - return 1; - for(r = r->p2; r != R; r = r->p2link) - if(doms(idom, src, r->rpo)) - return 1; - return 0; -} - -void -loopmark(Reg **rpo2r, int32 head, Reg *r) -{ - if(r->rpo < head || r->active == head) - return; - r->active = head; - r->loop += LOOP; - if(r->p1 != R) - loopmark(rpo2r, head, r->p1); - for(r = r->p2; r != R; r = r->p2link) - loopmark(rpo2r, head, r); -} - -void -loopit(Reg *r, int32 nr) -{ - Reg *r1; - int32 i, d, me; - - if(nr > maxnr) { - rpo2r = mal(nr * sizeof(Reg*)); - idom = mal(nr * sizeof(int32)); - maxnr = nr; - } - d = postorder(r, rpo2r, 0); - if(d > nr) - fatal("too many reg nodes"); - nr = d; - for(i = 0; i < nr / 2; i++){ - r1 = rpo2r[i]; - rpo2r[i] = rpo2r[nr - 1 - i]; - rpo2r[nr - 1 - i] = r1; - } - for(i = 0; i < nr; i++) - rpo2r[i]->rpo = i; - - idom[0] = 0; - for(i = 0; i < nr; i++){ - r1 = rpo2r[i]; - me = r1->rpo; - d = -1; - // rpo2r[r->rpo] == r protects against considering dead code, - // which has r->rpo == 0. - if(r1->p1 != R && rpo2r[r1->p1->rpo] == r1->p1 && r1->p1->rpo < me) - d = r1->p1->rpo; - for(r1 = r1->p2; r1 != nil; r1 = r1->p2link) - if(rpo2r[r1->rpo] == r1 && r1->rpo < me) - d = rpolca(idom, d, r1->rpo); - idom[i] = d; - } - - for(i = 0; i < nr; i++){ - r1 = rpo2r[i]; - r1->loop++; - if(r1->p2 != R && loophead(idom, r1)) - loopmark(rpo2r, i, r1); - } -} - void synch(Reg *r, Bits dif) { Reg *r1; int z; - for(r1 = r; r1 != R; r1 = r1->s1) { + for(r1 = r; r1 != R; r1 = (Reg*)r1->f.s1) { for(z=0; z<BITS; z++) { dif.b[z] = (dif.b[z] & ~(~r1->refbehind.b[z] & r1->refahead.b[z])) | @@ -1256,13 +907,13 @@ synch(Reg *r, Bits dif) change++; } } - if(r1->active) + if(r1->f.active) break; - r1->active = 1; + r1->f.active = 1; for(z=0; z<BITS; z++) dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]); - if(r1->s2 != R) - synch(r1->s2, dif); + if(r1->f.s2 != nil) + synch((Reg*)r1->f.s2, dif); } } @@ -1333,7 +984,7 @@ paint1(Reg *r, int bn) for(;;) { if(!(r->refbehind.b[z] & bb)) break; - r1 = r->p1; + r1 = (Reg*)r->f.p1; if(r1 == R) break; if(!(r1->refahead.b[z] & bb)) @@ -1344,48 +995,48 @@ paint1(Reg *r, int bn) } if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb) { - change -= CLOAD * r->loop; + change -= CLOAD * r->f.loop; if(debug['R'] > 1) - print("%d%P\td %Q $%d\n", r->loop, - r->prog, blsh(bn), change); + print("%d%P\td %Q $%d\n", r->f.loop, + r->f.prog, blsh(bn), change); } for(;;) { r->act.b[z] |= bb; - p = r->prog; + p = r->f.prog; if(r->use1.b[z] & bb) { - change += CREF * r->loop; + change += CREF * r->f.loop; if(debug['R'] > 1) - print("%d%P\tu1 %Q $%d\n", r->loop, + print("%d%P\tu1 %Q $%d\n", r->f.loop, p, blsh(bn), change); } if((r->use2.b[z]|r->set.b[z]) & bb) { - change += CREF * r->loop; + change += CREF * r->f.loop; if(debug['R'] > 1) - print("%d%P\tu2 %Q $%d\n", r->loop, + print("%d%P\tu2 %Q $%d\n", r->f.loop, p, blsh(bn), change); } if(STORE(r) & r->regdiff.b[z] & bb) { - change -= CLOAD * r->loop; + change -= CLOAD * r->f.loop; if(debug['R'] > 1) - print("%d%P\tst %Q $%d\n", r->loop, + print("%d%P\tst %Q $%d\n", r->f.loop, p, blsh(bn), change); } if(r->refbehind.b[z] & bb) - for(r1 = r->p2; r1 != R; r1 = r1->p2link) + for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link) if(r1->refahead.b[z] & bb) paint1(r1, bn); if(!(r->refahead.b[z] & bb)) break; - r1 = r->s2; + r1 = (Reg*)r->f.s2; if(r1 != R) if(r1->refbehind.b[z] & bb) paint1(r1, bn); - r = r->s1; + r = (Reg*)r->f.s1; if(r == R) break; if(r->act.b[z] & bb) @@ -1410,7 +1061,7 @@ paint2(Reg *r, int bn) for(;;) { if(!(r->refbehind.b[z] & bb)) break; - r1 = r->p1; + r1 = (Reg*)r->f.p1; if(r1 == R) break; if(!(r1->refahead.b[z] & bb)) @@ -1425,17 +1076,17 @@ paint2(Reg *r, int bn) vreg |= r->regu; if(r->refbehind.b[z] & bb) - for(r1 = r->p2; r1 != R; r1 = r1->p2link) + for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link) if(r1->refahead.b[z] & bb) vreg |= paint2(r1, bn); if(!(r->refahead.b[z] & bb)) break; - r1 = r->s2; + r1 = (Reg*)r->f.s2; if(r1 != R) if(r1->refbehind.b[z] & bb) vreg |= paint2(r1, bn); - r = r->s1; + r = (Reg*)r->f.s1; if(r == R) break; if(!(r->act.b[z] & bb)) @@ -1461,7 +1112,7 @@ paint3(Reg *r, int bn, int32 rb, int rn) for(;;) { if(!(r->refbehind.b[z] & bb)) break; - r1 = r->p1; + r1 = (Reg*)r->f.p1; if(r1 == R) break; if(!(r1->refahead.b[z] & bb)) @@ -1476,7 +1127,7 @@ paint3(Reg *r, int bn, int32 rb, int rn) for(;;) { r->act.b[z] |= bb; - p = r->prog; + p = r->f.prog; if(r->use1.b[z] & bb) { if(debug['R']) @@ -1498,17 +1149,17 @@ paint3(Reg *r, int bn, int32 rb, int rn) r->regu |= rb; if(r->refbehind.b[z] & bb) - for(r1 = r->p2; r1 != R; r1 = r1->p2link) + for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link) if(r1->refahead.b[z] & bb) paint3(r1, bn, rb, rn); if(!(r->refahead.b[z] & bb)) break; - r1 = r->s2; + r1 = (Reg*)r->f.s2; if(r1 != R) if(r1->refbehind.b[z] & bb) paint3(r1, bn, rb, rn); - r = r->s1; + r = (Reg*)r->f.s1; if(r == R) break; if(r->act.b[z] & bb) @@ -1582,91 +1233,74 @@ BtoF(int32 b) return bitno(b) - 16; } -static Sym* symlist[10]; - -int -noreturn(Prog *p) -{ - Sym *s; - int i; - - if(symlist[0] == S) { - symlist[0] = pkglookup("panicindex", runtimepkg); - symlist[1] = pkglookup("panicslice", runtimepkg); - symlist[2] = pkglookup("throwinit", runtimepkg); - symlist[3] = pkglookup("panic", runtimepkg); - symlist[4] = pkglookup("panicwrap", runtimepkg); - } - - s = p->to.sym; - if(s == S) - return 0; - for(i=0; symlist[i]!=S; i++) - if(s == symlist[i]) - return 1; - return 0; -} - void -dumpone(Reg *r) +dumpone(Flow *f, int isreg) { int z; Bits bit; + Reg *r; - print("%d:%P", r->loop, r->prog); - for(z=0; z<BITS; z++) - bit.b[z] = - r->set.b[z] | - r->use1.b[z] | - r->use2.b[z] | - r->refbehind.b[z] | - r->refahead.b[z] | - r->calbehind.b[z] | - r->calahead.b[z] | - r->regdiff.b[z] | - r->act.b[z] | - 0; - if(bany(&bit)) { - print("\t"); - if(bany(&r->set)) - print(" s:%Q", r->set); - if(bany(&r->use1)) - print(" u1:%Q", r->use1); - if(bany(&r->use2)) - print(" u2:%Q", r->use2); - if(bany(&r->refbehind)) - print(" rb:%Q ", r->refbehind); - if(bany(&r->refahead)) - print(" ra:%Q ", r->refahead); - if(bany(&r->calbehind)) - print(" cb:%Q ", r->calbehind); - if(bany(&r->calahead)) - print(" ca:%Q ", r->calahead); - if(bany(&r->regdiff)) - print(" d:%Q ", r->regdiff); - if(bany(&r->act)) - print(" a:%Q ", r->act); + print("%d:%P", f->loop, f->prog); + if(isreg) { + r = (Reg*)f; + for(z=0; z<BITS; z++) + bit.b[z] = + r->set.b[z] | + r->use1.b[z] | + r->use2.b[z] | + r->refbehind.b[z] | + r->refahead.b[z] | + r->calbehind.b[z] | + r->calahead.b[z] | + r->regdiff.b[z] | + r->act.b[z] | + 0; + if(bany(&bit)) { + print("\t"); + if(bany(&r->set)) + print(" s:%Q", r->set); + if(bany(&r->use1)) + print(" u1:%Q", r->use1); + if(bany(&r->use2)) + print(" u2:%Q", r->use2); + if(bany(&r->refbehind)) + print(" rb:%Q ", r->refbehind); + if(bany(&r->refahead)) + print(" ra:%Q ", r->refahead); + if(bany(&r->calbehind)) + print(" cb:%Q ", r->calbehind); + if(bany(&r->calahead)) + print(" ca:%Q ", r->calahead); + if(bany(&r->regdiff)) + print(" d:%Q ", r->regdiff); + if(bany(&r->act)) + print(" a:%Q ", r->act); + } } print("\n"); } void -dumpit(char *str, Reg *r0) +dumpit(char *str, Flow *r0, int isreg) { - Reg *r, *r1; + Flow *r, *r1; print("\n%s\n", str); - for(r = r0; r != R; r = r->link) { - dumpone(r); + for(r = r0; r != nil; r = r->link) { + dumpone(r, isreg); r1 = r->p2; - if(r1 != R) { + if(r1 != nil) { print(" pred:"); - for(; r1 != R; r1 = r1->p2link) + for(; r1 != nil; r1 = r1->p2link) print(" %.4ud", r1->prog->loc); + if(r->p1 != nil) + print(" (and %.4ud)", r->p1->prog->loc); + else + print(" (only)"); print("\n"); } // r1 = r->s1; -// if(r1 != R) { +// if(r1 != nil) { // print(" succ:"); // for(; r1 != R; r1 = r1->s1) // print(" %.4ud", r1->prog->loc); @@ -1674,123 +1308,3 @@ dumpit(char *str, Reg *r0) // } } } - -/* - * the code generator depends on being able to write out JMP (B) - * instructions that it can jump to now but fill in later. - * the linker will resolve them nicely, but they make the code - * longer and more difficult to follow during debugging. - * remove them. - */ - -/* what instruction does a JMP to p eventually land on? */ -static Prog* -chasejmp(Prog *p, int *jmploop) -{ - int n; - - n = 0; - while(p != P && p->as == AB && p->to.type == D_BRANCH) { - if(++n > 10) { - *jmploop = 1; - break; - } - p = p->to.u.branch; - } - return p; -} - -/* - * reuse reg pointer for mark/sweep state. - * leave reg==nil at end because alive==nil. - */ -#define alive ((void*)0) -#define dead ((void*)1) - -/* mark all code reachable from firstp as alive */ -static void -mark(Prog *firstp) -{ - Prog *p; - - for(p=firstp; p; p=p->link) { - if(p->regp != dead) - break; - p->regp = alive; - if(p->as != ABL && p->to.type == D_BRANCH && p->to.u.branch) - mark(p->to.u.branch); - if(p->as == AB || p->as == ARET || (p->as == ABL && noreturn(p))) - break; - } -} - -static void -fixjmp(Prog *firstp) -{ - int jmploop; - Prog *p, *last; - - if(debug['R'] && debug['v']) - print("\nfixjmp\n"); - - // pass 1: resolve jump to B, mark all code as dead. - jmploop = 0; - for(p=firstp; p; p=p->link) { - if(debug['R'] && debug['v']) - print("%P\n", p); - if(p->as != ABL && p->to.type == D_BRANCH && p->to.u.branch && p->to.u.branch->as == AB) { - p->to.u.branch = chasejmp(p->to.u.branch, &jmploop); - if(debug['R'] && debug['v']) - print("->%P\n", p); - } - p->regp = dead; - } - if(debug['R'] && debug['v']) - print("\n"); - - // pass 2: mark all reachable code alive - mark(firstp); - - // pass 3: delete dead code (mostly JMPs). - last = nil; - for(p=firstp; p; p=p->link) { - if(p->regp == dead) { - if(p->link == P && p->as == ARET && last && last->as != ARET) { - // This is the final ARET, and the code so far doesn't have one. - // Let it stay. - } else { - if(debug['R'] && debug['v']) - print("del %P\n", p); - continue; - } - } - if(last) - last->link = p; - last = p; - } - last->link = P; - - // pass 4: elide JMP to next instruction. - // only safe if there are no jumps to JMPs anymore. - if(!jmploop) { - last = nil; - for(p=firstp; p; p=p->link) { - if(p->as == AB && p->to.type == D_BRANCH && p->to.u.branch == p->link) { - if(debug['R'] && debug['v']) - print("del %P\n", p); - continue; - } - if(last) - last->link = p; - last = p; - } - last->link = P; - } - - if(debug['R'] && debug['v']) { - print("\n"); - for(p=firstp; p; p=p->link) - print("%P\n", p); - print("\n"); - } -} |