📄 reg.c
字号:
#include "gc.h"Reg*rega(void){ Reg *r; r = freer; if(r == R) { r = alloc(sizeof(*r)); } else freer = r->link; *r = zreg; return r;}intrcmp(const void *a1, const void *a2){ Rgn *p1, *p2; int c1, c2; p1 = (Rgn*)a1; p2 = (Rgn*)a2; c1 = p2->cost; c2 = p1->cost; if(c1 -= c2) return c1; return p2->varno - p1->varno;}voidregopt(Prog *p){ Reg *r, *r1, *r2; Prog *p1; int i, z; long initpc, val, npc; ulong vreg; Bits bit; struct { long m; long c; Reg* p; } log5[6], *lp; firstr = R; lastr = R; nvar = 0; regbits = RtoB(D_SP) | RtoB(D_AX); for(z=0; z<BITS; z++) { externs.b[z] = 0; params.b[z] = 0; consts.b[z] = 0; addrs.b[z] = 0; } /* * pass 1 * build aux data structure * allocate pcs * find use and set of variables */ val = 5L * 5L * 5L * 5L * 5L; lp = log5; for(i=0; i<5; i++) { lp->m = val; lp->c = 0; lp->p = R; val /= 5L; lp++; } val = 0; for(; p != P; p = p->link) { switch(p->as) { case ADATA: case AGLOBL: case ANAME: case ASIGNAME: continue; } r = rega(); if(firstr == R) { firstr = r; lastr = r; } else { lastr->link = r; r->p1 = lastr; lastr->s1 = r; lastr = r; } r->prog = p; r->pc = val; val++; lp = log5; for(i=0; i<5; i++) { lp->c--; if(lp->c <= 0) { lp->c = lp->m; if(lp->p != R) lp->p->log5 = r; lp->p = r; (lp+1)->c = 0; break; } lp++; } r1 = r->p1; if(r1 != R) switch(r1->prog->as) { case ARET: case AJMP: case AIRETL: r->p1 = R; r1->s1 = R; } bit = mkvar(r, &p->from); if(bany(&bit)) switch(p->as) { /* * funny */ case ALEAL: for(z=0; z<BITS; z++) addrs.b[z] |= bit.b[z]; break; /* * left side read */ default: for(z=0; z<BITS; z++) r->use1.b[z] |= bit.b[z]; break; } bit = mkvar(r, &p->to); if(bany(&bit)) switch(p->as) { default: diag(Z, "reg: unknown op: %A", p->as); break; /* * right side read */ case ACMPB: case ACMPL: case ACMPW: for(z=0; z<BITS; z++) r->use2.b[z] |= bit.b[z]; break; /* * right side write */ case ANOP: case AMOVL: case AMOVB: case AMOVW: case AMOVBLSX: case AMOVBLZX: case AMOVWLSX: case AMOVWLZX: for(z=0; z<BITS; z++) r->set.b[z] |= bit.b[z]; break; /* * right side read+write */ case AADDB: case AADDL: case AADDW: case AANDB: case AANDL: case AANDW: case ASUBB: case ASUBL: case ASUBW: case AORB: case AORL: case AORW: case AXORB: case AXORL: case AXORW: case ASALB: case ASALL: case ASALW: case ASARB: case ASARL: case ASARW: case AROLB: case AROLL: case AROLW: case ARORB: case ARORL: case ARORW: case ASHLB: case ASHLL: case ASHLW: case ASHRB: case ASHRL: case ASHRW: case AIMULL: case AIMULW: case ANEGL: case ANOTL: case AADCL: case ASBBL: for(z=0; z<BITS; z++) { r->set.b[z] |= bit.b[z]; r->use2.b[z] |= bit.b[z]; } break; /* * funny */ case AFMOVDP: case AFMOVFP: case AFMOVVP: case ACALL: for(z=0; z<BITS; z++) addrs.b[z] |= bit.b[z]; break; } switch(p->as) { case AIMULL: case AIMULW: if(p->to.type != D_NONE) break; case AIDIVB: case AIDIVL: case AIDIVW: case AIMULB: case ADIVB: case ADIVL: case ADIVW: case AMULB: case AMULL: case AMULW: case ACWD: case ACDQ: r->regu |= RtoB(D_AX) | RtoB(D_DX); break; case AREP: case AREPN: case ALOOP: case ALOOPEQ: case ALOOPNE: r->regu |= RtoB(D_CX); break; case AMOVSB: case AMOVSL: case AMOVSW: case ACMPSB: case ACMPSL: case ACMPSW: r->regu |= RtoB(D_SI) | RtoB(D_DI); break; case ASTOSB: case ASTOSL: case ASTOSW: case ASCASB: case ASCASL: case ASCASW: r->regu |= RtoB(D_AX) | RtoB(D_DI); break; case AINSB: case AINSL: case AINSW: case AOUTSB: case AOUTSL: case AOUTSW: r->regu |= RtoB(D_DI) | RtoB(D_DX); break; case AFSTSW: case ASAHF: r->regu |= RtoB(D_AX); break; } } if(firstr == R) return; initpc = pc - val; npc = val; /* * 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) { val = p->to.offset - initpc; r1 = firstr; while(r1 != R) { r2 = r1->log5; if(r2 != R && val >= r2->pc) { r1 = r2; continue; } if(r1->pc == val) break; r1 = r1->link; } if(r1 == R) { nearln = p->lineno; diag(Z, "ref not found\n%P", p); continue; } if(r1 == r) { nearln = p->lineno; diag(Z, "ref to self\n%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); } /* * pass 2.5 * find looping structure */ for(r = firstr; r != R; r = r->link) r->active = 0; change = 0; loopit(firstr, npc); if(debug['R'] && debug['v']) { print("\nlooping structure:\n"); for(r = firstr; r != R; r = r->link) { print("%ld:%P", r->loop, r->prog); for(z=0; z<BITS; z++) bit.b[z] = r->use1.b[z] | r->use2.b[z] | r->set.b[z]; if(bany(&bit)) { print("\t"); if(bany(&r->use1)) print(" u1=%B", r->use1); if(bany(&r->use2)) print(" u2=%B", r->use2); if(bany(&r->set)) print(" st=%B", r->set); } print("\n"); } } /* * pass 3 * iterate propagating usage * back until flow graph is complete */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) 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) { prop(r, zbits, zbits); i = 1; } } if(i) goto loop11; if(change) goto loop1; /* * pass 4 * iterate propagating register/variable synchrony * forward until graph is complete */loop2: change = 0; for(r = firstr; r != R; r = r->link) r->active = 0; synch(firstr, zbits); if(change) goto loop2; /* * pass 5 * isolate regions * calculate costs (paint1) */ r = firstr; if(r) { 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)) { nearln = r->prog->lineno; warn(Z, "used and not set: %B", bit); if(debug['R'] && !debug['w']) print("used and not set: %B\n", bit); } } if(debug['R'] && debug['v']) print("\nprop structure:\n"); for(r = firstr; r != R; r = r->link) r->act = zbits; rgp = region; nregion = 0; for(r = firstr; r != R; r = r->link) { if(debug['R'] && debug['v']) { print("%P\t", r->prog); if(bany(&r->set)) print("s:%B ", r->set); if(bany(&r->refahead)) print("ra:%B ", r->refahead); if(bany(&r->calahead)) print("ca:%B ", r->calahead); print("\n"); } 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)) { nearln = r->prog->lineno; warn(Z, "set and not used: %B", bit); if(debug['R']) print("set and not used: %B\n", bit); excise(r); } for(z=0; z<BITS; z++) bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]); while(bany(&bit)) { i = bnum(bit); rgp->enter = r; rgp->varno = i; change = 0; if(debug['R'] && debug['v']) print("\n"); paint1(r, i); bit.b[i/32] &= ~(1L<<(i%32)); if(change <= 0) { if(debug['R']) print("%L$%d: %B\n", r->prog->lineno, change, blsh(i)); continue; } rgp->cost = change; nregion++; if(nregion >= NRGN) { warn(Z, "too many regions"); goto brk; } rgp++; } }brk: qsort(region, nregion, sizeof(region[0]), rcmp); /* * pass 6 * determine used registers (paint2) * replace code (paint3) */ rgp = region; for(i=0; i<nregion; i++) { bit = blsh(rgp->varno); vreg = paint2(rgp->enter, rgp->varno); vreg = allreg(vreg, rgp); if(debug['R']) { print("%L$%d %R: %B\n", rgp->enter->prog->lineno, rgp->cost, rgp->regno, bit); } if(rgp->regno != 0) paint3(rgp->enter, rgp->varno, vreg, rgp->regno); rgp++; } /* * pass 7 * peep-hole on basic block */ if(!debug['R'] || debug['P']) peep(); /* * pass 8 * recalculate pc */ val = initpc; for(r = firstr; r != R; r = r1) { r->pc = val; p = r->prog; p1 = P; r1 = r->link; if(r1 != R) p1 = r1->prog; for(; p != p1; p = p->link) { switch(p->as) { default: val++; break; case ANOP: case ADATA: case AGLOBL: case ANAME: case ASIGNAME: break; } } } pc = val; /* * fix up branches */ if(debug['R']) if(bany(&addrs)) print("addrs: %B\n", addrs); r1 = 0; /* set */ for(r = firstr; r != R; r = r->link) { p = r->prog; if(p->to.type == D_BRANCH) p->to.offset = r->s2->pc; r1 = r; } /* * last pass * eliminate nops * free aux structures */ for(p = firstr->prog; p != P; p = p->link){ while(p->link && p->link->as == ANOP) p->link = p->link->link; } if(r1 != R) { r1->link = freer; freer = firstr; }}/* * add mov b,rn * just after r */voidaddmove(Reg *r, int bn, int rn, int f){ Prog *p, *p1; Adr *a; Var *v; p1 = alloc(sizeof(*p1)); *p1 = zprog; p = r->prog; p1->link = p->link; p->link = p1; p1->lineno = p->lineno; v = var + bn; a = &p1->to; a->sym = v->sym; a->offset = v->offset; a->etype = v->etype; a->type = v->name; p1->as = AMOVL; if(v->etype == TCHAR || v->etype == TUCHAR) p1->as = AMOVB; if(v->etype == TSHORT || v->etype == TUSHORT) p1->as = AMOVW; p1->from.type = rn; if(!f) { p1->from = *a; *a = zprog.from; a->type = rn; if(v->etype == TUCHAR) p1->as = AMOVB; if(v->etype == TUSHORT) p1->as = AMOVW; } if(debug['R']) print("%P\t.a%P\n", p, p1);}ulongdoregbits(int r){ ulong b; b = 0; if(r >= D_INDIR) r -= D_INDIR; if(r >= D_AX && r <= D_DI)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -