123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221 |
- #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;
- }
- int
- rcmp(const void *a1, const void *a2)
- {
- Rgn *p1, *p2;
- int c1, c2;
- p1 = (Rgn*)a1;
- p2 = (Rgn*)a2;
- c1 = p2->costr;
- if(p2->costa > c1)
- c1 = p2->costa;
- c2 = p1->costr;
- if(p1->costa > c2)
- c2 = p1->costa;
- if(c1 -= c2)
- return c1;
- return p2->varno - p1->varno;
- }
- void
- regopt(Prog *p)
- {
- Reg *r, *r1, *r2;
- Prog *p1;
- int i, z;
- long val, initpc, npc;
- ulong vreg;
- Bits bit;
- Var *v;
- struct {
- long m;
- long c;
- Reg* p;
- } log5[6], *lp;
- firstr = R;
- lastr = R;
- nvar = 0;
- for(z=0; z<BITS; z++) {
- externs.b[z] = 0;
- params.b[z] = 0;
- addrs.b[z] = 0;
- }
- regbits = RtoB(0) | /* return reg */
- AtoB(6) | AtoB(7) | /* sp and sb */
- FtoB(0) | FtoB(1); /* floating return reg */
- for(i=0; i<NREG; i++) {
- if(regused[i])
- regbits |= RtoB(i);
- if(fregused[i])
- regbits |= FtoB(i);
- if(aregused[i])
- regbits |= AtoB(i);
- }
- /*
- * 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 ABRA:
- case ARTS:
- case ARTE:
- r->p1 = R;
- r1->s1 = R;
- }
- bit = mkvar(&p->from, AGOK);
- if(bany(&bit))
- switch(p->as) {
- case ALEA:
- if(!(mvbits & B_INDIR))
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- default:
- if(mvbits & B_ADDR)
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- for(z=0; z<BITS; z++)
- r->use1.b[z] |= bit.b[z];
- }
- bit = mkvar(&p->to, p->as);
- if(bany(&bit))
- switch(p->as) {
- case ABSR: /* funny */
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- goto def;
- case APEA:
- if(!(mvbits & B_INDIR))
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- def:
- case ACMPB: case ACMPW: case ACMPL:
- case AFCMPF: case AFCMPD:
- case ATSTB: case ATSTW: case ATSTL:
- case AFTSTF: case AFTSTD:
- case ABFEXTU: case ABFEXTS:
- if(mvbits & B_ADDR)
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- for(z=0; z<BITS; z++)
- r->use2.b[z] |= bit.b[z];
- break;
- default:
- diag(Z, "reg: unknown asop: %A", p->as);
- case AADDB: case AADDW: case AADDL:
- case ASUBB: case ASUBW: case ASUBL:
- case AANDB: case AANDW: case AANDL:
- case AORB: case AORW: case AORL:
- case AEORB: case AEORW: case AEORL:
- case ABFINS:
- for(z=0; z<BITS; z++)
- r->use2.b[z] |= bit.b[z];
- case ANOP:
- case AMOVB: case AMOVW: case AMOVL:
- case AFMOVEB: case AFMOVEW: case AFMOVEL:
- case ACLRB: case ACLRW: case ACLRL:
- case AFMOVEF: case AFMOVED:
- if(mvbits & B_INDIR)
- for(z=0; z<BITS; z++)
- r->use2.b[z] |= bit.b[z];
- else
- for(z=0; z<BITS; z++)
- r->set.b[z] |= bit.b[z];
- 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) {
- diag(Z, "ref not found\n%L:%P", p->lineno, p);
- continue;
- }
- if(r1 == r) {
- diag(Z, "ref to self");
- continue;
- }
- r->s2 = r1;
- r->p2link = r1->p2;
- r1->p2 = r;
- }
- }
- if(debug['R'])
- print("\n%L %D\n", firstr->prog->lineno, &firstr->prog->from);
- /*
- * pass 2.5
- * find looping structure
- */
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- changer = 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:
- changer = 0;
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- for(r = firstr; r != R; r = r->link)
- if(r->prog->as == ARTS)
- 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(changer)
- goto loop1;
- /*
- * pass 4
- * iterate propagating register/variable synchrony
- * forward until graph is complete
- */
- loop2:
- changer = 0;
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- synch(firstr, zbits);
- if(changer)
- 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]);
- 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);
- /*
- * 68040 'feature':
- * load of a denormalized fp will trap
- */
- while(bany(&bit)) {
- i = bnum(bit);
- bit.b[i/32] &= ~(1L << (i%32));
- v = var + i;
- if(v->type == D_AUTO) {
- r->set.b[i/32] |= (1L << (i%32));
- if(typefd[v->etype])
- addmove(r, i, NREG+NREG, 1);
- }
- }
- }
- }
- if(debug['R'] && debug['v'])
- print("\nprop structure:\n");
- for(r = firstr; r != R; r = r->link) {
- if(debug['R'] && debug['v'])
- print("%P\n set = %B; rah = %B; cal = %B\n",
- r->prog, r->set, r->refahead, r->calahead);
- r->act = zbits;
- }
- rgp = region;
- nregion = 0;
- for(r = firstr; r != R; r = r->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)) {
- nearln = r->prog->lineno;
- warn(Z, "set and not used: %B", bit);
- if(debug['R'])
- print("set an 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;
- changer = 0;
- changea = 0;
- if(debug['R'] && debug['v'])
- print("\n");
- paint1(r, i);
- bit.b[i/32] &= ~(1L<<(i%32));
- if(changer <= 0 && changea <= 0) {
- if(debug['R'])
- print("%L$%d.%d: %B\n",
- r->prog->lineno,
- changer, changea, blsh(i));
- continue;
- }
- rgp->costr = changer;
- rgp->costa = changea;
- 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.%d %R: %B\n",
- rgp->enter->prog->lineno,
- rgp->costr, rgp->costa,
- rgp->regno,
- bit);
- if(rgp->regno != D_NONE)
- 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
- */
- void
- addmove(Reg *r, int bn, int rn, int f)
- {
- Prog *p, *p1;
- Var *v;
- int badccr;
- badccr = 0;
- p = r->prog;
- p1 = p->link;
- if(p1)
- switch(p1->as) {
- case AMOVW:
- if(p1->from.type == D_CCR)
- p = p1;
- break;
- case ABEQ:
- case ABNE:
- case ABLE:
- case ABLS:
- case ABLT:
- case ABMI:
- case ABGE:
- case ABPL:
- case ABGT:
- case ABHI:
- case ABCC:
- case ABCS:
- p1 = prg();
- p1->link = p->link;
- p->link = p1;
- p1->lineno = p->lineno;
- p1->from.type = D_CCR;
- p1->to.type = D_TOS;
- p1->as = AMOVW;
- p = p1;
- badccr = 1;
- }
- p1 = prg();
- p1->link = p->link;
- p->link = p1;
- p1->lineno = p->lineno;
- v = var + bn;
- p1->from.sym = v->sym;
- p1->from.type = v->type;
- p1->from.offset = v->offset;
- p1->from.etype = v->etype;
- p1->to.type = rn;
- if(f) {
- p1->to = p1->from;
- p1->from = zprog.from;
- p1->from.type = rn;
- }
- p1->as = opxt[OAS][v->etype];
- if(badccr) {
- p = p1;
- p1 = prg();
- p1->link = p->link;
- p->link = p1;
- p1->lineno = p->lineno;
- p1->from.type = D_TOS;
- p1->to.type = D_CCR;
- p1->as = AMOVW;
- }
- if(debug['R'])
- print("%P\t.a%P\n", p, p1);
- }
- Bits
- mkvar(Adr *a, int as)
- {
- Var *v;
- int i, t, z;
- long o;
- Bits bit;
- Sym *s;
- mvbits = 0;
- t = a->type & D_MASK;
- switch(t) {
- default:
- if(t >= D_R0 && t < D_R0+NREG) {
- regbits |= RtoB(t-D_R0);
- if(as == ADIVUL || as == ADIVSL)
- regbits |= RtoB(t-D_R0+1);
- }
- if(t >= D_A0 && t < D_A0+NREG)
- regbits |= AtoB(t-D_A0);
- if(t >= D_F0 && t < D_F0+NREG)
- regbits |= FtoB(t-D_F0);
- goto none;
- case D_EXTERN:
- case D_STATIC:
- case D_AUTO:
- case D_PARAM:
- break;
- }
- s = a->sym;
- if(s == S)
- goto none;
- if((a->type & I_MASK) == I_ADDR)
- mvbits |= B_ADDR;
- o = a->offset;
- v = var;
- for(i=0; i<nvar; i++) {
- if(s == v->sym)
- if(t == v->type)
- if(o == v->offset)
- goto out;
- v++;
- }
- if(s)
- if(s->name[0] == '.')
- goto none;
- if(nvar >= NVAR) {
- if(debug['w'] > 1 && s)
- warn(Z, "variable not optimized: %s", s->name);
- goto none;
- }
- i = nvar;
- nvar++;
- v = &var[i];
- v->sym = s;
- v->offset = o;
- v->etype = a->etype;
- v->type = t;
- if(debug['R'])
- print("bit=%2d et=%2d %s (%d,%d,%ld)\n",
- i, a->etype, s->name,
- (int)v->sym, v->type, v->offset);
- out:
- bit = blsh(i);
- if(t == D_EXTERN || t == D_STATIC)
- for(z=0; z<BITS; z++)
- externs.b[z] |= bit.b[z];
- if(t == D_PARAM)
- for(z=0; z<BITS; z++)
- params.b[z] |= bit.b[z];
- if(a->etype != v->etype || !typechlpfd[a->etype])
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z]; /* funny punning */
- return bit;
- none:
- return zbits;
- }
- void
- prop(Reg *r, Bits ref, Bits cal)
- {
- Reg *r1, *r2;
- int z;
- for(r1 = r; r1 != R; r1 = r1->p1) {
- for(z=0; z<BITS; z++) {
- ref.b[z] |= r1->refahead.b[z];
- if(ref.b[z] != r1->refahead.b[z]) {
- r1->refahead.b[z] = ref.b[z];
- changer++;
- }
- cal.b[z] |= r1->calahead.b[z];
- if(cal.b[z] != r1->calahead.b[z]) {
- r1->calahead.b[z] = cal.b[z];
- changer++;
- }
- }
- switch(r1->prog->as) {
- case ABSR:
- for(z=0; z<BITS; z++) {
- cal.b[z] |= ref.b[z] | externs.b[z];
- ref.b[z] = 0;
- }
- break;
- case ATEXT:
- for(z=0; z<BITS; z++) {
- cal.b[z] = 0;
- ref.b[z] = 0;
- }
- break;
- case ARTS:
- for(z=0; z<BITS; z++) {
- cal.b[z] = externs.b[z];
- ref.b[z] = 0;
- }
- }
- for(z=0; z<BITS; z++) {
- ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
- r1->use1.b[z] | r1->use2.b[z];
- cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
- r1->refbehind.b[z] = ref.b[z];
- r1->calbehind.b[z] = cal.b[z];
- }
- if(r1->active)
- break;
- r1->active = 1;
- }
- for(; r != r1; r = r->p1)
- for(r2 = r->p2; r2 != R; r2 = r2->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
- */
- long
- postorder(Reg *r, Reg **rpo2r, long 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;
- }
- long
- rpolca(long *idom, long rpo1, long rpo2)
- {
- long 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(Z, "bad idom");
- rpo2 = t;
- }
- }
- return rpo1;
- }
- int
- doms(long *idom, long r, long s)
- {
- while(s > r)
- s = idom[s];
- return s == r;
- }
- int
- loophead(long *idom, Reg *r)
- {
- long 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, long 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, long nr)
- {
- Reg *r1;
- long i, d, me;
- if(nr > maxnr) {
- rpo2r = alloc(nr * sizeof(Reg*));
- idom = alloc(nr * sizeof(long));
- maxnr = nr;
- }
- d = postorder(r, rpo2r, 0);
- if(d > nr)
- fatal(Z, "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;
- if(r1->p1 != R && r1->p1->rpo < me)
- d = r1->p1->rpo;
- for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
- if(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(z=0; z<BITS; z++) {
- dif.b[z] = (dif.b[z] &
- ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
- r1->set.b[z] | r1->regdiff.b[z];
- if(dif.b[z] != r1->regdiff.b[z]) {
- r1->regdiff.b[z] = dif.b[z];
- changer++;
- }
- }
- if(r1->active)
- break;
- r1->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);
- }
- }
- ulong
- allreg(ulong b, Rgn *r)
- {
- Var *v;
- int i, j;
- v = var + r->varno;
- r->regno = D_NONE;
- switch(v->etype) {
- default:
- diag(Z, "unknown etype");
- break;
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- i = BtoR(~b);
- j = BtoA(~b);
- if(r->costa == r->costr)
- if(i > j)
- i = NREG;
- if(j < NREG && r->costa > 0)
- if(r->costa > r->costr || i >= NREG) {
- r->regno = D_A0 + j;
- return AtoB(j);
- }
- if(i < NREG && r->costr > 0) {
- r->regno = D_R0 + i;
- return RtoB(i);
- }
- break;
- case TDOUBLE:
- case TFLOAT:
- i = BtoF(~b);
- if(i < NREG) {
- r->regno = D_F0 + i;
- return FtoB(i);
- }
- break;
- }
- return 0;
- }
- void
- paint1(Reg *r, int bn)
- {
- Reg *r1;
- Prog *p;
- int z;
- ulong bb;
- int x;
- z = bn/32;
- bb = 1L<<(bn%32);
- if(r->act.b[z] & bb)
- return;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(r1->act.b[z] & bb)
- break;
- r = r1;
- }
- if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
- changer -= CLOAD * r->loop;
- changea -= CLOAD * r->loop;
- if(debug['R'] && debug['v'])
- print("%ld%P\tld %B $%d.%d\n", r->loop,
- r->prog, blsh(bn), changer, changea);
- }
- for(;;) {
- r->act.b[z] |= bb;
- p = r->prog;
- if(r->use1.b[z] & bb) {
- changer += CREF * r->loop;
- changea += CREF * r->loop;
- switch(p->as) {
- default:
- changea = -CINF;
- case AADDL:
- case ASUBL:
- case AMOVL:
- case ACMPL:
- break;
- }
- if(p->as == AMOVL) {
- x = p->to.type;
- if(x >= D_R0 && x < D_R0+NREG)
- changer += r->loop;
- if(x >= D_A0 && x < D_A0+NREG)
- changea += r->loop;
- }
- if(debug['R'] && debug['v'])
- print("%ld%P\tu1 %B $%d.%d\n", r->loop,
- p, blsh(bn), changer, changea);
- }
- if((r->use2.b[z]|r->set.b[z]) & bb) {
- changer += CREF * r->loop;
- changea += CREF * r->loop;
- switch(p->as) {
- default:
- changea = -CINF;
- break;
- case AMOVL:
- case AADDL:
- case ACMPL:
- case ASUBL:
- case ACLRL: /* can be faked */
- case ATSTL: /* can be faked */
- break;
- }
- if(p->as == AMOVL) {
- x = p->from.type;
- if(x >= D_R0 && x < D_R0+NREG)
- changer += r->loop;
- if(x >= D_A0 && x < D_A0+NREG)
- changea += r->loop;
- }
- if(debug['R'] && debug['v'])
- print("%ld%P\tu2 %B $%d.%d\n", r->loop,
- p, blsh(bn), changer, changea);
- }
- if(STORE(r) & r->regdiff.b[z] & bb) {
- changer -= CLOAD * r->loop;
- changea -= CLOAD * r->loop;
- if(debug['R'] && debug['v'])
- print("%ld%P\tst %B $%d.%d\n", r->loop,
- p, blsh(bn), changer, changea);
- }
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- paint1(r1, bn);
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- paint1(r1, bn);
- r = r->s1;
- if(r == R)
- break;
- if(r->act.b[z] & bb)
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
- }
- ulong
- paint2(Reg *r, int bn)
- {
- Reg *r1;
- int z;
- ulong bb, vreg;
- z = bn/32;
- bb = 1L << (bn%32);
- vreg = regbits;
- if(!(r->act.b[z] & bb))
- return vreg;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(!(r1->act.b[z] & bb))
- break;
- r = r1;
- }
- for(;;) {
- r->act.b[z] &= ~bb;
- vreg |= r->regu;
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- vreg |= paint2(r1, bn);
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- vreg |= paint2(r1, bn);
- r = r->s1;
- if(r == R)
- break;
- if(!(r->act.b[z] & bb))
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
- return vreg;
- }
- void
- paint3(Reg *r, int bn, ulong rb, int rn)
- {
- Reg *r1;
- Prog *p;
- int z;
- ulong bb;
- z = bn/32;
- bb = 1L << (bn%32);
- if(r->act.b[z] & bb)
- return;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(r1->act.b[z] & bb)
- break;
- r = r1;
- }
- if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
- addmove(r, bn, rn, 0);
- for(;;) {
- r->act.b[z] |= bb;
- p = r->prog;
- if(r->use1.b[z] & bb) {
- if(debug['R'])
- print("%P", p);
- addreg(&p->from, rn);
- if(debug['R'])
- print("\t.c%P\n", p);
- }
- if((r->use2.b[z]|r->set.b[z]) & bb) {
- if(debug['R'])
- print("%P", p);
- addreg(&p->to, rn);
- if(debug['R'])
- print("\t.c%P\n", p);
- }
- if(STORE(r) & r->regdiff.b[z] & bb)
- addmove(r, bn, rn, 1);
- r->regu |= rb;
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- paint3(r1, bn, rb, rn);
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- paint3(r1, bn, rb, rn);
- r = r->s1;
- if(r == R)
- break;
- if(r->act.b[z] & bb)
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
- }
- void
- addreg(Adr *a, int rn)
- {
- a->sym = 0;
- if(rn >= D_R0 && rn < D_R0+NREG)
- goto addr;
- a->type = rn | (a->type & I_INDIR);
- return;
- addr:
- a->type = rn | (a->type & I_INDIR);
- }
- /*
- * bit reg
- * 0-7 R0-R7
- * 8-15 A0-A7
- * 16-23 F0-F7
- */
- ulong
- RtoB(int r)
- {
- if(r < 0 || r >= NREG)
- return 0;
- return 1L << (r + 0);
- }
- int
- BtoR(ulong b)
- {
- b &= 0x0000ffL;
- if(b == 0)
- return NREG;
- return bitno(b) - 0;
- }
- ulong
- AtoB(int a)
- {
- if(a < 0 || a >= NREG)
- return 0;
- return 1L << (a + NREG);
- }
- int
- BtoA(ulong b)
- {
- b &= 0x00ff00L;
- if(b == 0)
- return NREG;
- return bitno(b) - NREG;
- }
- ulong
- FtoB(int f)
- {
- if(f < 0 || f >= NREG)
- return 0;
- return 1L << (f + NREG+NREG);
- }
- int
- BtoF(ulong b)
- {
- b &= 0xff0000L;
- if(b == 0)
- return NREG;
- return bitno(b) - NREG-NREG;
- }
|