13e12c5d1SDavid du Colombier #include "gc.h"
23e12c5d1SDavid du Colombier
33e12c5d1SDavid du Colombier Reg*
rega(void)43e12c5d1SDavid du Colombier rega(void)
53e12c5d1SDavid du Colombier {
63e12c5d1SDavid du Colombier Reg *r;
73e12c5d1SDavid du Colombier
83e12c5d1SDavid du Colombier r = freer;
93e12c5d1SDavid du Colombier if(r == R) {
107dd7cddfSDavid du Colombier r = alloc(sizeof(*r));
113e12c5d1SDavid du Colombier } else
123e12c5d1SDavid du Colombier freer = r->link;
133e12c5d1SDavid du Colombier
143e12c5d1SDavid du Colombier *r = zreg;
153e12c5d1SDavid du Colombier return r;
163e12c5d1SDavid du Colombier }
173e12c5d1SDavid du Colombier
183e12c5d1SDavid du Colombier int
rcmp(const void * a1,const void * a2)197dd7cddfSDavid du Colombier rcmp(const void *a1, const void *a2)
203e12c5d1SDavid du Colombier {
213e12c5d1SDavid du Colombier Rgn *p1, *p2;
223e12c5d1SDavid du Colombier int c1, c2;
233e12c5d1SDavid du Colombier
247dd7cddfSDavid du Colombier p1 = (Rgn*)a1;
257dd7cddfSDavid du Colombier p2 = (Rgn*)a2;
263e12c5d1SDavid du Colombier c1 = p2->cost;
273e12c5d1SDavid du Colombier c2 = p1->cost;
283e12c5d1SDavid du Colombier if(c1 -= c2)
293e12c5d1SDavid du Colombier return c1;
303e12c5d1SDavid du Colombier return p2->varno - p1->varno;
313e12c5d1SDavid du Colombier }
323e12c5d1SDavid du Colombier
333e12c5d1SDavid du Colombier void
regopt(Prog * p)343e12c5d1SDavid du Colombier regopt(Prog *p)
353e12c5d1SDavid du Colombier {
363e12c5d1SDavid du Colombier Reg *r, *r1, *r2;
37219b2ee8SDavid du Colombier Prog *p1;
383e12c5d1SDavid du Colombier int i, z;
397dd7cddfSDavid du Colombier long initpc, val, npc;
403e12c5d1SDavid du Colombier ulong vreg;
413e12c5d1SDavid du Colombier Bits bit;
423e12c5d1SDavid du Colombier struct
433e12c5d1SDavid du Colombier {
443e12c5d1SDavid du Colombier long m;
453e12c5d1SDavid du Colombier long c;
463e12c5d1SDavid du Colombier Reg* p;
473e12c5d1SDavid du Colombier } log5[6], *lp;
483e12c5d1SDavid du Colombier
493e12c5d1SDavid du Colombier firstr = R;
503e12c5d1SDavid du Colombier lastr = R;
513e12c5d1SDavid du Colombier nvar = 0;
523e12c5d1SDavid du Colombier regbits = RtoB(D_SP) | RtoB(D_AX);
533e12c5d1SDavid du Colombier for(z=0; z<BITS; z++) {
543e12c5d1SDavid du Colombier externs.b[z] = 0;
553e12c5d1SDavid du Colombier params.b[z] = 0;
563e12c5d1SDavid du Colombier consts.b[z] = 0;
573e12c5d1SDavid du Colombier addrs.b[z] = 0;
583e12c5d1SDavid du Colombier }
593e12c5d1SDavid du Colombier
603e12c5d1SDavid du Colombier /*
613e12c5d1SDavid du Colombier * pass 1
623e12c5d1SDavid du Colombier * build aux data structure
633e12c5d1SDavid du Colombier * allocate pcs
643e12c5d1SDavid du Colombier * find use and set of variables
653e12c5d1SDavid du Colombier */
663e12c5d1SDavid du Colombier val = 5L * 5L * 5L * 5L * 5L;
673e12c5d1SDavid du Colombier lp = log5;
683e12c5d1SDavid du Colombier for(i=0; i<5; i++) {
693e12c5d1SDavid du Colombier lp->m = val;
703e12c5d1SDavid du Colombier lp->c = 0;
713e12c5d1SDavid du Colombier lp->p = R;
723e12c5d1SDavid du Colombier val /= 5L;
733e12c5d1SDavid du Colombier lp++;
743e12c5d1SDavid du Colombier }
753e12c5d1SDavid du Colombier val = 0;
763e12c5d1SDavid du Colombier for(; p != P; p = p->link) {
773e12c5d1SDavid du Colombier switch(p->as) {
783e12c5d1SDavid du Colombier case ADATA:
793e12c5d1SDavid du Colombier case AGLOBL:
803e12c5d1SDavid du Colombier case ANAME:
81375daca8SDavid du Colombier case ASIGNAME:
823e12c5d1SDavid du Colombier continue;
833e12c5d1SDavid du Colombier }
843e12c5d1SDavid du Colombier r = rega();
853e12c5d1SDavid du Colombier if(firstr == R) {
863e12c5d1SDavid du Colombier firstr = r;
873e12c5d1SDavid du Colombier lastr = r;
883e12c5d1SDavid du Colombier } else {
893e12c5d1SDavid du Colombier lastr->link = r;
903e12c5d1SDavid du Colombier r->p1 = lastr;
913e12c5d1SDavid du Colombier lastr->s1 = r;
923e12c5d1SDavid du Colombier lastr = r;
933e12c5d1SDavid du Colombier }
943e12c5d1SDavid du Colombier r->prog = p;
953e12c5d1SDavid du Colombier r->pc = val;
963e12c5d1SDavid du Colombier val++;
973e12c5d1SDavid du Colombier
983e12c5d1SDavid du Colombier lp = log5;
993e12c5d1SDavid du Colombier for(i=0; i<5; i++) {
1003e12c5d1SDavid du Colombier lp->c--;
1013e12c5d1SDavid du Colombier if(lp->c <= 0) {
1023e12c5d1SDavid du Colombier lp->c = lp->m;
1033e12c5d1SDavid du Colombier if(lp->p != R)
1043e12c5d1SDavid du Colombier lp->p->log5 = r;
1053e12c5d1SDavid du Colombier lp->p = r;
1063e12c5d1SDavid du Colombier (lp+1)->c = 0;
1073e12c5d1SDavid du Colombier break;
1083e12c5d1SDavid du Colombier }
1093e12c5d1SDavid du Colombier lp++;
1103e12c5d1SDavid du Colombier }
1113e12c5d1SDavid du Colombier
1123e12c5d1SDavid du Colombier r1 = r->p1;
1133e12c5d1SDavid du Colombier if(r1 != R)
1143e12c5d1SDavid du Colombier switch(r1->prog->as) {
1153e12c5d1SDavid du Colombier case ARET:
1163e12c5d1SDavid du Colombier case AJMP:
1173e12c5d1SDavid du Colombier case AIRETL:
1183e12c5d1SDavid du Colombier r->p1 = R;
1193e12c5d1SDavid du Colombier r1->s1 = R;
1203e12c5d1SDavid du Colombier }
1213e12c5d1SDavid du Colombier
122*d40255d8SDavid du Colombier bit = mkvar(r, &p->from, p->as==AMOVL);
1233e12c5d1SDavid du Colombier if(bany(&bit))
1243e12c5d1SDavid du Colombier switch(p->as) {
1253e12c5d1SDavid du Colombier /*
1263e12c5d1SDavid du Colombier * funny
1273e12c5d1SDavid du Colombier */
1283e12c5d1SDavid du Colombier case ALEAL:
1293e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
1303e12c5d1SDavid du Colombier addrs.b[z] |= bit.b[z];
1313e12c5d1SDavid du Colombier break;
1323e12c5d1SDavid du Colombier
1333e12c5d1SDavid du Colombier /*
1343e12c5d1SDavid du Colombier * left side read
1353e12c5d1SDavid du Colombier */
1363e12c5d1SDavid du Colombier default:
1373e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
1383e12c5d1SDavid du Colombier r->use1.b[z] |= bit.b[z];
1393e12c5d1SDavid du Colombier break;
1403e12c5d1SDavid du Colombier }
1413e12c5d1SDavid du Colombier
142*d40255d8SDavid du Colombier bit = mkvar(r, &p->to, 0);
1433e12c5d1SDavid du Colombier if(bany(&bit))
1443e12c5d1SDavid du Colombier switch(p->as) {
1453e12c5d1SDavid du Colombier default:
1463e12c5d1SDavid du Colombier diag(Z, "reg: unknown op: %A", p->as);
1473e12c5d1SDavid du Colombier break;
1483e12c5d1SDavid du Colombier
1493e12c5d1SDavid du Colombier /*
1503e12c5d1SDavid du Colombier * right side read
1513e12c5d1SDavid du Colombier */
1523e12c5d1SDavid du Colombier case ACMPB:
1533e12c5d1SDavid du Colombier case ACMPL:
1543e12c5d1SDavid du Colombier case ACMPW:
1553e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
1563e12c5d1SDavid du Colombier r->use2.b[z] |= bit.b[z];
1573e12c5d1SDavid du Colombier break;
1583e12c5d1SDavid du Colombier
1593e12c5d1SDavid du Colombier /*
1603e12c5d1SDavid du Colombier * right side write
1613e12c5d1SDavid du Colombier */
1623e12c5d1SDavid du Colombier case ANOP:
1633e12c5d1SDavid du Colombier case AMOVL:
1643e12c5d1SDavid du Colombier case AMOVB:
1653e12c5d1SDavid du Colombier case AMOVW:
166219b2ee8SDavid du Colombier case AMOVBLSX:
167219b2ee8SDavid du Colombier case AMOVBLZX:
168219b2ee8SDavid du Colombier case AMOVWLSX:
169219b2ee8SDavid du Colombier case AMOVWLZX:
1703e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
1713e12c5d1SDavid du Colombier r->set.b[z] |= bit.b[z];
1723e12c5d1SDavid du Colombier break;
1733e12c5d1SDavid du Colombier
1743e12c5d1SDavid du Colombier /*
1753e12c5d1SDavid du Colombier * right side read+write
1763e12c5d1SDavid du Colombier */
1773e12c5d1SDavid du Colombier case AADDB:
1783e12c5d1SDavid du Colombier case AADDL:
1793e12c5d1SDavid du Colombier case AADDW:
1803e12c5d1SDavid du Colombier case AANDB:
1813e12c5d1SDavid du Colombier case AANDL:
1823e12c5d1SDavid du Colombier case AANDW:
1833e12c5d1SDavid du Colombier case ASUBB:
1843e12c5d1SDavid du Colombier case ASUBL:
1853e12c5d1SDavid du Colombier case ASUBW:
1863e12c5d1SDavid du Colombier case AORB:
1873e12c5d1SDavid du Colombier case AORL:
1883e12c5d1SDavid du Colombier case AORW:
1893e12c5d1SDavid du Colombier case AXORB:
1903e12c5d1SDavid du Colombier case AXORL:
1913e12c5d1SDavid du Colombier case AXORW:
1923e12c5d1SDavid du Colombier case ASALB:
1933e12c5d1SDavid du Colombier case ASALL:
1943e12c5d1SDavid du Colombier case ASALW:
1953e12c5d1SDavid du Colombier case ASARB:
1963e12c5d1SDavid du Colombier case ASARL:
1973e12c5d1SDavid du Colombier case ASARW:
1983e12c5d1SDavid du Colombier case AROLB:
1993e12c5d1SDavid du Colombier case AROLL:
2003e12c5d1SDavid du Colombier case AROLW:
2013e12c5d1SDavid du Colombier case ARORB:
2023e12c5d1SDavid du Colombier case ARORL:
2033e12c5d1SDavid du Colombier case ARORW:
2043e12c5d1SDavid du Colombier case ASHLB:
2053e12c5d1SDavid du Colombier case ASHLL:
2063e12c5d1SDavid du Colombier case ASHLW:
2073e12c5d1SDavid du Colombier case ASHRB:
2083e12c5d1SDavid du Colombier case ASHRL:
2093e12c5d1SDavid du Colombier case ASHRW:
2109a747e4fSDavid du Colombier case AIMULL:
2119a747e4fSDavid du Colombier case AIMULW:
212da51d93aSDavid du Colombier case ANEGL:
213da51d93aSDavid du Colombier case ANOTL:
214da51d93aSDavid du Colombier case AADCL:
215da51d93aSDavid du Colombier case ASBBL:
2163e12c5d1SDavid du Colombier for(z=0; z<BITS; z++) {
2173e12c5d1SDavid du Colombier r->set.b[z] |= bit.b[z];
2183e12c5d1SDavid du Colombier r->use2.b[z] |= bit.b[z];
2193e12c5d1SDavid du Colombier }
2203e12c5d1SDavid du Colombier break;
2213e12c5d1SDavid du Colombier
2223e12c5d1SDavid du Colombier /*
2233e12c5d1SDavid du Colombier * funny
2243e12c5d1SDavid du Colombier */
2253e12c5d1SDavid du Colombier case AFMOVDP:
2263e12c5d1SDavid du Colombier case AFMOVFP:
227*d40255d8SDavid du Colombier case AFMOVLP:
228adaed953SDavid du Colombier case AFMOVVP:
229*d40255d8SDavid du Colombier case AFMOVWP:
2303e12c5d1SDavid du Colombier case ACALL:
2313e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
2323e12c5d1SDavid du Colombier addrs.b[z] |= bit.b[z];
2333e12c5d1SDavid du Colombier break;
2343e12c5d1SDavid du Colombier }
2353e12c5d1SDavid du Colombier
2363e12c5d1SDavid du Colombier switch(p->as) {
2379a747e4fSDavid du Colombier case AIMULL:
2389a747e4fSDavid du Colombier case AIMULW:
2399a747e4fSDavid du Colombier if(p->to.type != D_NONE)
2409a747e4fSDavid du Colombier break;
2419a747e4fSDavid du Colombier
2423e12c5d1SDavid du Colombier case AIDIVB:
2433e12c5d1SDavid du Colombier case AIDIVL:
2443e12c5d1SDavid du Colombier case AIDIVW:
2453e12c5d1SDavid du Colombier case AIMULB:
2463e12c5d1SDavid du Colombier case ADIVB:
2473e12c5d1SDavid du Colombier case ADIVL:
2483e12c5d1SDavid du Colombier case ADIVW:
2493e12c5d1SDavid du Colombier case AMULB:
2503e12c5d1SDavid du Colombier case AMULL:
2513e12c5d1SDavid du Colombier case AMULW:
2523e12c5d1SDavid du Colombier
2533e12c5d1SDavid du Colombier case ACWD:
2543e12c5d1SDavid du Colombier case ACDQ:
2553e12c5d1SDavid du Colombier r->regu |= RtoB(D_AX) | RtoB(D_DX);
2563e12c5d1SDavid du Colombier break;
2573e12c5d1SDavid du Colombier
2583e12c5d1SDavid du Colombier case AREP:
2593e12c5d1SDavid du Colombier case AREPN:
2603e12c5d1SDavid du Colombier case ALOOP:
2613e12c5d1SDavid du Colombier case ALOOPEQ:
2623e12c5d1SDavid du Colombier case ALOOPNE:
2633e12c5d1SDavid du Colombier r->regu |= RtoB(D_CX);
2643e12c5d1SDavid du Colombier break;
2653e12c5d1SDavid du Colombier
2663e12c5d1SDavid du Colombier case AMOVSB:
2673e12c5d1SDavid du Colombier case AMOVSL:
2683e12c5d1SDavid du Colombier case AMOVSW:
2693e12c5d1SDavid du Colombier case ACMPSB:
2703e12c5d1SDavid du Colombier case ACMPSL:
2713e12c5d1SDavid du Colombier case ACMPSW:
2723e12c5d1SDavid du Colombier r->regu |= RtoB(D_SI) | RtoB(D_DI);
2733e12c5d1SDavid du Colombier break;
2743e12c5d1SDavid du Colombier
2753e12c5d1SDavid du Colombier case ASTOSB:
2763e12c5d1SDavid du Colombier case ASTOSL:
2773e12c5d1SDavid du Colombier case ASTOSW:
2783e12c5d1SDavid du Colombier case ASCASB:
2793e12c5d1SDavid du Colombier case ASCASL:
2803e12c5d1SDavid du Colombier case ASCASW:
2813e12c5d1SDavid du Colombier r->regu |= RtoB(D_AX) | RtoB(D_DI);
2823e12c5d1SDavid du Colombier break;
2833e12c5d1SDavid du Colombier
2843e12c5d1SDavid du Colombier case AINSB:
2853e12c5d1SDavid du Colombier case AINSL:
2863e12c5d1SDavid du Colombier case AINSW:
2873e12c5d1SDavid du Colombier case AOUTSB:
2883e12c5d1SDavid du Colombier case AOUTSL:
2893e12c5d1SDavid du Colombier case AOUTSW:
2903e12c5d1SDavid du Colombier r->regu |= RtoB(D_DI) | RtoB(D_DX);
2913e12c5d1SDavid du Colombier break;
2923e12c5d1SDavid du Colombier
2933e12c5d1SDavid du Colombier case AFSTSW:
2943e12c5d1SDavid du Colombier case ASAHF:
2953e12c5d1SDavid du Colombier r->regu |= RtoB(D_AX);
2963e12c5d1SDavid du Colombier break;
2973e12c5d1SDavid du Colombier }
2983e12c5d1SDavid du Colombier }
2993e12c5d1SDavid du Colombier if(firstr == R)
3003e12c5d1SDavid du Colombier return;
3013e12c5d1SDavid du Colombier initpc = pc - val;
3027dd7cddfSDavid du Colombier npc = val;
3033e12c5d1SDavid du Colombier
3043e12c5d1SDavid du Colombier /*
3053e12c5d1SDavid du Colombier * pass 2
3063e12c5d1SDavid du Colombier * turn branch references to pointers
3073e12c5d1SDavid du Colombier * build back pointers
3083e12c5d1SDavid du Colombier */
3093e12c5d1SDavid du Colombier for(r = firstr; r != R; r = r->link) {
3103e12c5d1SDavid du Colombier p = r->prog;
3113e12c5d1SDavid du Colombier if(p->to.type == D_BRANCH) {
3123e12c5d1SDavid du Colombier val = p->to.offset - initpc;
3133e12c5d1SDavid du Colombier r1 = firstr;
3143e12c5d1SDavid du Colombier while(r1 != R) {
3153e12c5d1SDavid du Colombier r2 = r1->log5;
3163e12c5d1SDavid du Colombier if(r2 != R && val >= r2->pc) {
3173e12c5d1SDavid du Colombier r1 = r2;
3183e12c5d1SDavid du Colombier continue;
3193e12c5d1SDavid du Colombier }
3203e12c5d1SDavid du Colombier if(r1->pc == val)
3213e12c5d1SDavid du Colombier break;
3223e12c5d1SDavid du Colombier r1 = r1->link;
3233e12c5d1SDavid du Colombier }
3243e12c5d1SDavid du Colombier if(r1 == R) {
3253e12c5d1SDavid du Colombier nearln = p->lineno;
3263e12c5d1SDavid du Colombier diag(Z, "ref not found\n%P", p);
3273e12c5d1SDavid du Colombier continue;
3283e12c5d1SDavid du Colombier }
3293e12c5d1SDavid du Colombier if(r1 == r) {
3303e12c5d1SDavid du Colombier nearln = p->lineno;
3313e12c5d1SDavid du Colombier diag(Z, "ref to self\n%P", p);
3323e12c5d1SDavid du Colombier continue;
3333e12c5d1SDavid du Colombier }
3343e12c5d1SDavid du Colombier r->s2 = r1;
3353e12c5d1SDavid du Colombier r->p2link = r1->p2;
3363e12c5d1SDavid du Colombier r1->p2 = r;
3373e12c5d1SDavid du Colombier }
3383e12c5d1SDavid du Colombier }
3393e12c5d1SDavid du Colombier if(debug['R']) {
3403e12c5d1SDavid du Colombier p = firstr->prog;
3413e12c5d1SDavid du Colombier print("\n%L %D\n", p->lineno, &p->from);
3423e12c5d1SDavid du Colombier }
3433e12c5d1SDavid du Colombier
3443e12c5d1SDavid du Colombier /*
3453e12c5d1SDavid du Colombier * pass 2.5
3463e12c5d1SDavid du Colombier * find looping structure
3473e12c5d1SDavid du Colombier */
3483e12c5d1SDavid du Colombier for(r = firstr; r != R; r = r->link)
3493e12c5d1SDavid du Colombier r->active = 0;
3503e12c5d1SDavid du Colombier change = 0;
3517dd7cddfSDavid du Colombier loopit(firstr, npc);
3523e12c5d1SDavid du Colombier if(debug['R'] && debug['v']) {
3533e12c5d1SDavid du Colombier print("\nlooping structure:\n");
3543e12c5d1SDavid du Colombier for(r = firstr; r != R; r = r->link) {
3557dd7cddfSDavid du Colombier print("%ld:%P", r->loop, r->prog);
3563e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
3573e12c5d1SDavid du Colombier bit.b[z] = r->use1.b[z] |
3583e12c5d1SDavid du Colombier r->use2.b[z] |
3593e12c5d1SDavid du Colombier r->set.b[z];
3603e12c5d1SDavid du Colombier if(bany(&bit)) {
3619a747e4fSDavid du Colombier print("\t");
3623e12c5d1SDavid du Colombier if(bany(&r->use1))
3633e12c5d1SDavid du Colombier print(" u1=%B", r->use1);
3643e12c5d1SDavid du Colombier if(bany(&r->use2))
3653e12c5d1SDavid du Colombier print(" u2=%B", r->use2);
3663e12c5d1SDavid du Colombier if(bany(&r->set))
3673e12c5d1SDavid du Colombier print(" st=%B", r->set);
3683e12c5d1SDavid du Colombier }
3693e12c5d1SDavid du Colombier print("\n");
3703e12c5d1SDavid du Colombier }
3713e12c5d1SDavid du Colombier }
3723e12c5d1SDavid du Colombier
3733e12c5d1SDavid du Colombier /*
3743e12c5d1SDavid du Colombier * pass 3
3753e12c5d1SDavid du Colombier * iterate propagating usage
3763e12c5d1SDavid du Colombier * back until flow graph is complete
3773e12c5d1SDavid du Colombier */
3783e12c5d1SDavid du Colombier loop1:
3793e12c5d1SDavid du Colombier change = 0;
3803e12c5d1SDavid du Colombier for(r = firstr; r != R; r = r->link)
3813e12c5d1SDavid du Colombier r->active = 0;
3823e12c5d1SDavid du Colombier for(r = firstr; r != R; r = r->link)
3833e12c5d1SDavid du Colombier if(r->prog->as == ARET)
3843e12c5d1SDavid du Colombier prop(r, zbits, zbits);
3853e12c5d1SDavid du Colombier loop11:
3863e12c5d1SDavid du Colombier /* pick up unreachable code */
3873e12c5d1SDavid du Colombier i = 0;
3883e12c5d1SDavid du Colombier for(r = firstr; r != R; r = r1) {
3893e12c5d1SDavid du Colombier r1 = r->link;
3903e12c5d1SDavid du Colombier if(r1 && r1->active && !r->active) {
3913e12c5d1SDavid du Colombier prop(r, zbits, zbits);
3923e12c5d1SDavid du Colombier i = 1;
3933e12c5d1SDavid du Colombier }
3943e12c5d1SDavid du Colombier }
3953e12c5d1SDavid du Colombier if(i)
3963e12c5d1SDavid du Colombier goto loop11;
3973e12c5d1SDavid du Colombier if(change)
3983e12c5d1SDavid du Colombier goto loop1;
3993e12c5d1SDavid du Colombier
4003e12c5d1SDavid du Colombier
4013e12c5d1SDavid du Colombier /*
4023e12c5d1SDavid du Colombier * pass 4
4033e12c5d1SDavid du Colombier * iterate propagating register/variable synchrony
4043e12c5d1SDavid du Colombier * forward until graph is complete
4053e12c5d1SDavid du Colombier */
4063e12c5d1SDavid du Colombier loop2:
4073e12c5d1SDavid du Colombier change = 0;
4083e12c5d1SDavid du Colombier for(r = firstr; r != R; r = r->link)
4093e12c5d1SDavid du Colombier r->active = 0;
4103e12c5d1SDavid du Colombier synch(firstr, zbits);
4113e12c5d1SDavid du Colombier if(change)
4123e12c5d1SDavid du Colombier goto loop2;
4133e12c5d1SDavid du Colombier
4143e12c5d1SDavid du Colombier
4153e12c5d1SDavid du Colombier /*
4163e12c5d1SDavid du Colombier * pass 5
4173e12c5d1SDavid du Colombier * isolate regions
4183e12c5d1SDavid du Colombier * calculate costs (paint1)
4193e12c5d1SDavid du Colombier */
4203e12c5d1SDavid du Colombier r = firstr;
4213e12c5d1SDavid du Colombier if(r) {
4223e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
4233e12c5d1SDavid du Colombier bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
4243e12c5d1SDavid du Colombier ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
4253e12c5d1SDavid du Colombier if(bany(&bit)) {
4263e12c5d1SDavid du Colombier nearln = r->prog->lineno;
4273e12c5d1SDavid du Colombier warn(Z, "used and not set: %B", bit);
4283e12c5d1SDavid du Colombier if(debug['R'] && !debug['w'])
4293e12c5d1SDavid du Colombier print("used and not set: %B\n", bit);
4303e12c5d1SDavid du Colombier }
4313e12c5d1SDavid du Colombier }
4323e12c5d1SDavid du Colombier if(debug['R'] && debug['v'])
4333e12c5d1SDavid du Colombier print("\nprop structure:\n");
4343e12c5d1SDavid du Colombier for(r = firstr; r != R; r = r->link)
4353e12c5d1SDavid du Colombier r->act = zbits;
4363e12c5d1SDavid du Colombier rgp = region;
4373e12c5d1SDavid du Colombier nregion = 0;
4383e12c5d1SDavid du Colombier for(r = firstr; r != R; r = r->link) {
4393e12c5d1SDavid du Colombier if(debug['R'] && debug['v']) {
4409a747e4fSDavid du Colombier print("%P\t", r->prog);
4413e12c5d1SDavid du Colombier if(bany(&r->set))
4423e12c5d1SDavid du Colombier print("s:%B ", r->set);
4433e12c5d1SDavid du Colombier if(bany(&r->refahead))
4443e12c5d1SDavid du Colombier print("ra:%B ", r->refahead);
4453e12c5d1SDavid du Colombier if(bany(&r->calahead))
4463e12c5d1SDavid du Colombier print("ca:%B ", r->calahead);
4473e12c5d1SDavid du Colombier print("\n");
4483e12c5d1SDavid du Colombier }
4493e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
4503e12c5d1SDavid du Colombier bit.b[z] = r->set.b[z] &
4513e12c5d1SDavid du Colombier ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
4523e12c5d1SDavid du Colombier if(bany(&bit)) {
4533e12c5d1SDavid du Colombier nearln = r->prog->lineno;
4543e12c5d1SDavid du Colombier warn(Z, "set and not used: %B", bit);
4553e12c5d1SDavid du Colombier if(debug['R'])
456375daca8SDavid du Colombier print("set and not used: %B\n", bit);
4573e12c5d1SDavid du Colombier excise(r);
4583e12c5d1SDavid du Colombier }
4593e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
4603e12c5d1SDavid du Colombier bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
4613e12c5d1SDavid du Colombier while(bany(&bit)) {
4623e12c5d1SDavid du Colombier i = bnum(bit);
4633e12c5d1SDavid du Colombier rgp->enter = r;
4643e12c5d1SDavid du Colombier rgp->varno = i;
4653e12c5d1SDavid du Colombier change = 0;
4663e12c5d1SDavid du Colombier if(debug['R'] && debug['v'])
4673e12c5d1SDavid du Colombier print("\n");
4683e12c5d1SDavid du Colombier paint1(r, i);
4693e12c5d1SDavid du Colombier bit.b[i/32] &= ~(1L<<(i%32));
4703e12c5d1SDavid du Colombier if(change <= 0) {
4713e12c5d1SDavid du Colombier if(debug['R'])
4723e12c5d1SDavid du Colombier print("%L$%d: %B\n",
4733e12c5d1SDavid du Colombier r->prog->lineno, change, blsh(i));
4743e12c5d1SDavid du Colombier continue;
4753e12c5d1SDavid du Colombier }
4763e12c5d1SDavid du Colombier rgp->cost = change;
4773e12c5d1SDavid du Colombier nregion++;
4783e12c5d1SDavid du Colombier if(nregion >= NRGN) {
4793e12c5d1SDavid du Colombier warn(Z, "too many regions");
4803e12c5d1SDavid du Colombier goto brk;
4813e12c5d1SDavid du Colombier }
4823e12c5d1SDavid du Colombier rgp++;
4833e12c5d1SDavid du Colombier }
4843e12c5d1SDavid du Colombier }
4853e12c5d1SDavid du Colombier brk:
4863e12c5d1SDavid du Colombier qsort(region, nregion, sizeof(region[0]), rcmp);
4873e12c5d1SDavid du Colombier
4883e12c5d1SDavid du Colombier /*
4893e12c5d1SDavid du Colombier * pass 6
4903e12c5d1SDavid du Colombier * determine used registers (paint2)
4913e12c5d1SDavid du Colombier * replace code (paint3)
4923e12c5d1SDavid du Colombier */
4933e12c5d1SDavid du Colombier rgp = region;
4943e12c5d1SDavid du Colombier for(i=0; i<nregion; i++) {
4953e12c5d1SDavid du Colombier bit = blsh(rgp->varno);
4963e12c5d1SDavid du Colombier vreg = paint2(rgp->enter, rgp->varno);
4973e12c5d1SDavid du Colombier vreg = allreg(vreg, rgp);
4983e12c5d1SDavid du Colombier if(debug['R']) {
4993e12c5d1SDavid du Colombier print("%L$%d %R: %B\n",
5003e12c5d1SDavid du Colombier rgp->enter->prog->lineno,
5013e12c5d1SDavid du Colombier rgp->cost,
5023e12c5d1SDavid du Colombier rgp->regno,
5033e12c5d1SDavid du Colombier bit);
5043e12c5d1SDavid du Colombier }
5053e12c5d1SDavid du Colombier if(rgp->regno != 0)
5063e12c5d1SDavid du Colombier paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
5073e12c5d1SDavid du Colombier rgp++;
5083e12c5d1SDavid du Colombier }
5093e12c5d1SDavid du Colombier /*
5103e12c5d1SDavid du Colombier * pass 7
5113e12c5d1SDavid du Colombier * peep-hole on basic block
5123e12c5d1SDavid du Colombier */
5133e12c5d1SDavid du Colombier if(!debug['R'] || debug['P'])
5143e12c5d1SDavid du Colombier peep();
5153e12c5d1SDavid du Colombier
5163e12c5d1SDavid du Colombier /*
5173e12c5d1SDavid du Colombier * pass 8
5183e12c5d1SDavid du Colombier * recalculate pc
5193e12c5d1SDavid du Colombier */
5203e12c5d1SDavid du Colombier val = initpc;
5213e12c5d1SDavid du Colombier for(r = firstr; r != R; r = r1) {
5223e12c5d1SDavid du Colombier r->pc = val;
5233e12c5d1SDavid du Colombier p = r->prog;
524219b2ee8SDavid du Colombier p1 = P;
5253e12c5d1SDavid du Colombier r1 = r->link;
526219b2ee8SDavid du Colombier if(r1 != R)
527219b2ee8SDavid du Colombier p1 = r1->prog;
528219b2ee8SDavid du Colombier for(; p != p1; p = p->link) {
5293e12c5d1SDavid du Colombier switch(p->as) {
5303e12c5d1SDavid du Colombier default:
5313e12c5d1SDavid du Colombier val++;
532219b2ee8SDavid du Colombier break;
5333e12c5d1SDavid du Colombier
534219b2ee8SDavid du Colombier case ANOP:
5353e12c5d1SDavid du Colombier case ADATA:
5363e12c5d1SDavid du Colombier case AGLOBL:
5373e12c5d1SDavid du Colombier case ANAME:
538375daca8SDavid du Colombier case ASIGNAME:
539219b2ee8SDavid du Colombier break;
5403e12c5d1SDavid du Colombier }
5413e12c5d1SDavid du Colombier }
542219b2ee8SDavid du Colombier }
543219b2ee8SDavid du Colombier pc = val;
5443e12c5d1SDavid du Colombier
5453e12c5d1SDavid du Colombier /*
5463e12c5d1SDavid du Colombier * fix up branches
5473e12c5d1SDavid du Colombier */
5483e12c5d1SDavid du Colombier if(debug['R'])
5493e12c5d1SDavid du Colombier if(bany(&addrs))
5503e12c5d1SDavid du Colombier print("addrs: %B\n", addrs);
5513e12c5d1SDavid du Colombier
5523e12c5d1SDavid du Colombier r1 = 0; /* set */
5533e12c5d1SDavid du Colombier for(r = firstr; r != R; r = r->link) {
5543e12c5d1SDavid du Colombier p = r->prog;
5553e12c5d1SDavid du Colombier if(p->to.type == D_BRANCH)
5563e12c5d1SDavid du Colombier p->to.offset = r->s2->pc;
5573e12c5d1SDavid du Colombier r1 = r;
5583e12c5d1SDavid du Colombier }
559219b2ee8SDavid du Colombier
560219b2ee8SDavid du Colombier /*
561219b2ee8SDavid du Colombier * last pass
562219b2ee8SDavid du Colombier * eliminate nops
563219b2ee8SDavid du Colombier * free aux structures
564219b2ee8SDavid du Colombier */
565219b2ee8SDavid du Colombier for(p = firstr->prog; p != P; p = p->link){
566219b2ee8SDavid du Colombier while(p->link && p->link->as == ANOP)
567219b2ee8SDavid du Colombier p->link = p->link->link;
568219b2ee8SDavid du Colombier }
5693e12c5d1SDavid du Colombier if(r1 != R) {
5703e12c5d1SDavid du Colombier r1->link = freer;
5713e12c5d1SDavid du Colombier freer = firstr;
5723e12c5d1SDavid du Colombier }
5733e12c5d1SDavid du Colombier }
5743e12c5d1SDavid du Colombier
5753e12c5d1SDavid du Colombier /*
5763e12c5d1SDavid du Colombier * add mov b,rn
5773e12c5d1SDavid du Colombier * just after r
5783e12c5d1SDavid du Colombier */
5793e12c5d1SDavid du Colombier void
addmove(Reg * r,int bn,int rn,int f)5803e12c5d1SDavid du Colombier addmove(Reg *r, int bn, int rn, int f)
5813e12c5d1SDavid du Colombier {
5823e12c5d1SDavid du Colombier Prog *p, *p1;
5833e12c5d1SDavid du Colombier Adr *a;
5843e12c5d1SDavid du Colombier Var *v;
5853e12c5d1SDavid du Colombier
5867dd7cddfSDavid du Colombier p1 = alloc(sizeof(*p1));
5873e12c5d1SDavid du Colombier *p1 = zprog;
5883e12c5d1SDavid du Colombier p = r->prog;
5893e12c5d1SDavid du Colombier
5903e12c5d1SDavid du Colombier p1->link = p->link;
5913e12c5d1SDavid du Colombier p->link = p1;
5923e12c5d1SDavid du Colombier p1->lineno = p->lineno;
5933e12c5d1SDavid du Colombier
5943e12c5d1SDavid du Colombier v = var + bn;
5953e12c5d1SDavid du Colombier
5963e12c5d1SDavid du Colombier a = &p1->to;
5973e12c5d1SDavid du Colombier a->sym = v->sym;
5983e12c5d1SDavid du Colombier a->offset = v->offset;
5993e12c5d1SDavid du Colombier a->etype = v->etype;
6003e12c5d1SDavid du Colombier a->type = v->name;
6013e12c5d1SDavid du Colombier
6023e12c5d1SDavid du Colombier p1->as = AMOVL;
6033e12c5d1SDavid du Colombier if(v->etype == TCHAR || v->etype == TUCHAR)
6043e12c5d1SDavid du Colombier p1->as = AMOVB;
6053e12c5d1SDavid du Colombier if(v->etype == TSHORT || v->etype == TUSHORT)
6063e12c5d1SDavid du Colombier p1->as = AMOVW;
6073e12c5d1SDavid du Colombier
6083e12c5d1SDavid du Colombier p1->from.type = rn;
6093e12c5d1SDavid du Colombier if(!f) {
6103e12c5d1SDavid du Colombier p1->from = *a;
6113e12c5d1SDavid du Colombier *a = zprog.from;
6123e12c5d1SDavid du Colombier a->type = rn;
6133e12c5d1SDavid du Colombier if(v->etype == TUCHAR)
6143e12c5d1SDavid du Colombier p1->as = AMOVB;
6153e12c5d1SDavid du Colombier if(v->etype == TUSHORT)
6163e12c5d1SDavid du Colombier p1->as = AMOVW;
6173e12c5d1SDavid du Colombier }
6183e12c5d1SDavid du Colombier if(debug['R'])
6199a747e4fSDavid du Colombier print("%P\t.a%P\n", p, p1);
6203e12c5d1SDavid du Colombier }
6213e12c5d1SDavid du Colombier
6223e12c5d1SDavid du Colombier ulong
doregbits(int r)6233e12c5d1SDavid du Colombier doregbits(int r)
6243e12c5d1SDavid du Colombier {
6253e12c5d1SDavid du Colombier ulong b;
6263e12c5d1SDavid du Colombier
6273e12c5d1SDavid du Colombier b = 0;
6283e12c5d1SDavid du Colombier if(r >= D_INDIR)
6293e12c5d1SDavid du Colombier r -= D_INDIR;
6303e12c5d1SDavid du Colombier if(r >= D_AX && r <= D_DI)
6313e12c5d1SDavid du Colombier b |= RtoB(r);
6323e12c5d1SDavid du Colombier else
6333e12c5d1SDavid du Colombier if(r >= D_AL && r <= D_BL)
6343e12c5d1SDavid du Colombier b |= RtoB(r-D_AL+D_AX);
6353e12c5d1SDavid du Colombier else
6363e12c5d1SDavid du Colombier if(r >= D_AH && r <= D_BH)
6373e12c5d1SDavid du Colombier b |= RtoB(r-D_AH+D_AX);
6383e12c5d1SDavid du Colombier return b;
6393e12c5d1SDavid du Colombier }
6403e12c5d1SDavid du Colombier
6413e12c5d1SDavid du Colombier Bits
mkvar(Reg * r,Adr * a,int isro)642*d40255d8SDavid du Colombier mkvar(Reg *r, Adr *a, int isro)
6433e12c5d1SDavid du Colombier {
6443e12c5d1SDavid du Colombier Var *v;
6453e12c5d1SDavid du Colombier int i, t, n, et, z;
6463e12c5d1SDavid du Colombier long o;
6473e12c5d1SDavid du Colombier Bits bit;
6483e12c5d1SDavid du Colombier Sym *s;
6493e12c5d1SDavid du Colombier
6503e12c5d1SDavid du Colombier /*
6513e12c5d1SDavid du Colombier * mark registers used
6523e12c5d1SDavid du Colombier */
6533e12c5d1SDavid du Colombier t = a->type;
6543e12c5d1SDavid du Colombier r->regu |= doregbits(t);
6553e12c5d1SDavid du Colombier r->regu |= doregbits(a->index);
656*d40255d8SDavid du Colombier et = a->etype;
6573e12c5d1SDavid du Colombier
6583e12c5d1SDavid du Colombier switch(t) {
6593e12c5d1SDavid du Colombier default:
6603e12c5d1SDavid du Colombier goto none;
661*d40255d8SDavid du Colombier case D_INDIR+D_GS:
662*d40255d8SDavid du Colombier if(!isro || 1)
663*d40255d8SDavid du Colombier goto none;
664*d40255d8SDavid du Colombier n = t;
665*d40255d8SDavid du Colombier {static Sym er; a->sym = &er;}
666*d40255d8SDavid du Colombier a->sym->name = "$extreg";
667*d40255d8SDavid du Colombier break;
6683e12c5d1SDavid du Colombier case D_ADDR:
6693e12c5d1SDavid du Colombier a->type = a->index;
670*d40255d8SDavid du Colombier bit = mkvar(r, a, 0);
6713e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
6723e12c5d1SDavid du Colombier addrs.b[z] |= bit.b[z];
6733e12c5d1SDavid du Colombier a->type = t;
6743e12c5d1SDavid du Colombier goto none;
6753e12c5d1SDavid du Colombier case D_EXTERN:
6763e12c5d1SDavid du Colombier case D_STATIC:
6773e12c5d1SDavid du Colombier case D_PARAM:
6783e12c5d1SDavid du Colombier case D_AUTO:
6793e12c5d1SDavid du Colombier n = t;
6803e12c5d1SDavid du Colombier break;
6813e12c5d1SDavid du Colombier }
6823e12c5d1SDavid du Colombier s = a->sym;
6833e12c5d1SDavid du Colombier if(s == S)
6843e12c5d1SDavid du Colombier goto none;
6853e12c5d1SDavid du Colombier if(s->name[0] == '.')
6863e12c5d1SDavid du Colombier goto none;
6873e12c5d1SDavid du Colombier o = a->offset;
6883e12c5d1SDavid du Colombier v = var;
6893e12c5d1SDavid du Colombier for(i=0; i<nvar; i++) {
6903e12c5d1SDavid du Colombier if(s == v->sym)
6913e12c5d1SDavid du Colombier if(n == v->name)
6923e12c5d1SDavid du Colombier if(o == v->offset)
6933e12c5d1SDavid du Colombier goto out;
6943e12c5d1SDavid du Colombier v++;
6953e12c5d1SDavid du Colombier }
6963e12c5d1SDavid du Colombier if(nvar >= NVAR) {
6977dd7cddfSDavid du Colombier if(debug['w'] > 1 && s)
6983e12c5d1SDavid du Colombier warn(Z, "variable not optimized: %s", s->name);
6993e12c5d1SDavid du Colombier goto none;
7003e12c5d1SDavid du Colombier }
7013e12c5d1SDavid du Colombier i = nvar;
7023e12c5d1SDavid du Colombier nvar++;
7033e12c5d1SDavid du Colombier v = &var[i];
7043e12c5d1SDavid du Colombier v->sym = s;
7053e12c5d1SDavid du Colombier v->offset = o;
7063e12c5d1SDavid du Colombier v->name = n;
7073e12c5d1SDavid du Colombier v->etype = et;
7083e12c5d1SDavid du Colombier if(debug['R'])
7093e12c5d1SDavid du Colombier print("bit=%2d et=%2d %D\n", i, et, a);
7103e12c5d1SDavid du Colombier
7113e12c5d1SDavid du Colombier out:
7123e12c5d1SDavid du Colombier bit = blsh(i);
7133e12c5d1SDavid du Colombier if(n == D_EXTERN || n == D_STATIC)
7143e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
7153e12c5d1SDavid du Colombier externs.b[z] |= bit.b[z];
7163e12c5d1SDavid du Colombier if(n == D_PARAM)
7173e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
7183e12c5d1SDavid du Colombier params.b[z] |= bit.b[z];
719219b2ee8SDavid du Colombier if(v->etype != et || !typechlpfd[et]) /* funny punning */
7203e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
7213e12c5d1SDavid du Colombier addrs.b[z] |= bit.b[z];
7223e12c5d1SDavid du Colombier return bit;
7233e12c5d1SDavid du Colombier
7243e12c5d1SDavid du Colombier none:
7253e12c5d1SDavid du Colombier return zbits;
7263e12c5d1SDavid du Colombier }
7273e12c5d1SDavid du Colombier
7283e12c5d1SDavid du Colombier void
prop(Reg * r,Bits ref,Bits cal)7293e12c5d1SDavid du Colombier prop(Reg *r, Bits ref, Bits cal)
7303e12c5d1SDavid du Colombier {
7313e12c5d1SDavid du Colombier Reg *r1, *r2;
7323e12c5d1SDavid du Colombier int z;
7333e12c5d1SDavid du Colombier
7343e12c5d1SDavid du Colombier for(r1 = r; r1 != R; r1 = r1->p1) {
7353e12c5d1SDavid du Colombier for(z=0; z<BITS; z++) {
7363e12c5d1SDavid du Colombier ref.b[z] |= r1->refahead.b[z];
7373e12c5d1SDavid du Colombier if(ref.b[z] != r1->refahead.b[z]) {
7383e12c5d1SDavid du Colombier r1->refahead.b[z] = ref.b[z];
7393e12c5d1SDavid du Colombier change++;
7403e12c5d1SDavid du Colombier }
7413e12c5d1SDavid du Colombier cal.b[z] |= r1->calahead.b[z];
7423e12c5d1SDavid du Colombier if(cal.b[z] != r1->calahead.b[z]) {
7433e12c5d1SDavid du Colombier r1->calahead.b[z] = cal.b[z];
7443e12c5d1SDavid du Colombier change++;
7453e12c5d1SDavid du Colombier }
7463e12c5d1SDavid du Colombier }
7473e12c5d1SDavid du Colombier switch(r1->prog->as) {
7483e12c5d1SDavid du Colombier case ACALL:
7493e12c5d1SDavid du Colombier for(z=0; z<BITS; z++) {
7503e12c5d1SDavid du Colombier cal.b[z] |= ref.b[z] | externs.b[z];
7513e12c5d1SDavid du Colombier ref.b[z] = 0;
7523e12c5d1SDavid du Colombier }
7533e12c5d1SDavid du Colombier break;
7543e12c5d1SDavid du Colombier
7553e12c5d1SDavid du Colombier case ATEXT:
7563e12c5d1SDavid du Colombier for(z=0; z<BITS; z++) {
7573e12c5d1SDavid du Colombier cal.b[z] = 0;
7583e12c5d1SDavid du Colombier ref.b[z] = 0;
7593e12c5d1SDavid du Colombier }
7603e12c5d1SDavid du Colombier break;
7613e12c5d1SDavid du Colombier
7623e12c5d1SDavid du Colombier case ARET:
7633e12c5d1SDavid du Colombier for(z=0; z<BITS; z++) {
7643e12c5d1SDavid du Colombier cal.b[z] = externs.b[z];
7653e12c5d1SDavid du Colombier ref.b[z] = 0;
7663e12c5d1SDavid du Colombier }
7673e12c5d1SDavid du Colombier }
7683e12c5d1SDavid du Colombier for(z=0; z<BITS; z++) {
7693e12c5d1SDavid du Colombier ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
7703e12c5d1SDavid du Colombier r1->use1.b[z] | r1->use2.b[z];
7713e12c5d1SDavid du Colombier cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
7723e12c5d1SDavid du Colombier r1->refbehind.b[z] = ref.b[z];
7733e12c5d1SDavid du Colombier r1->calbehind.b[z] = cal.b[z];
7743e12c5d1SDavid du Colombier }
7753e12c5d1SDavid du Colombier if(r1->active)
7763e12c5d1SDavid du Colombier break;
7773e12c5d1SDavid du Colombier r1->active = 1;
7783e12c5d1SDavid du Colombier }
7793e12c5d1SDavid du Colombier for(; r != r1; r = r->p1)
7803e12c5d1SDavid du Colombier for(r2 = r->p2; r2 != R; r2 = r2->p2link)
7813e12c5d1SDavid du Colombier prop(r2, r->refbehind, r->calbehind);
7823e12c5d1SDavid du Colombier }
7833e12c5d1SDavid du Colombier
7847dd7cddfSDavid du Colombier /*
7857dd7cddfSDavid du Colombier * find looping structure
7867dd7cddfSDavid du Colombier *
7877dd7cddfSDavid du Colombier * 1) find reverse postordering
7887dd7cddfSDavid du Colombier * 2) find approximate dominators,
7897dd7cddfSDavid du Colombier * the actual dominators if the flow graph is reducible
7907dd7cddfSDavid du Colombier * otherwise, dominators plus some other non-dominators.
7917dd7cddfSDavid du Colombier * See Matthew S. Hecht and Jeffrey D. Ullman,
7927dd7cddfSDavid du Colombier * "Analysis of a Simple Algorithm for Global Data Flow Problems",
7937dd7cddfSDavid du Colombier * Conf. Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
7947dd7cddfSDavid du Colombier * Oct. 1-3, 1973, pp. 207-217.
7957dd7cddfSDavid du Colombier * 3) find all nodes with a predecessor dominated by the current node.
7967dd7cddfSDavid du Colombier * such a node is a loop head.
7977dd7cddfSDavid du Colombier * recursively, all preds with a greater rpo number are in the loop
7987dd7cddfSDavid du Colombier */
7997dd7cddfSDavid du Colombier long
postorder(Reg * r,Reg ** rpo2r,long n)8007dd7cddfSDavid du Colombier postorder(Reg *r, Reg **rpo2r, long n)
8013e12c5d1SDavid du Colombier {
8023e12c5d1SDavid du Colombier Reg *r1;
8033e12c5d1SDavid du Colombier
8047dd7cddfSDavid du Colombier r->rpo = 1;
8057dd7cddfSDavid du Colombier r1 = r->s1;
8067dd7cddfSDavid du Colombier if(r1 && !r1->rpo)
8077dd7cddfSDavid du Colombier n = postorder(r1, rpo2r, n);
8087dd7cddfSDavid du Colombier r1 = r->s2;
8097dd7cddfSDavid du Colombier if(r1 && !r1->rpo)
8107dd7cddfSDavid du Colombier n = postorder(r1, rpo2r, n);
8117dd7cddfSDavid du Colombier rpo2r[n] = r;
8127dd7cddfSDavid du Colombier n++;
8137dd7cddfSDavid du Colombier return n;
8143e12c5d1SDavid du Colombier }
8157dd7cddfSDavid du Colombier
8167dd7cddfSDavid du Colombier long
rpolca(long * idom,long rpo1,long rpo2)8177dd7cddfSDavid du Colombier rpolca(long *idom, long rpo1, long rpo2)
8187dd7cddfSDavid du Colombier {
8197dd7cddfSDavid du Colombier long t;
8207dd7cddfSDavid du Colombier
8217dd7cddfSDavid du Colombier if(rpo1 == -1)
8227dd7cddfSDavid du Colombier return rpo2;
8237dd7cddfSDavid du Colombier while(rpo1 != rpo2){
8247dd7cddfSDavid du Colombier if(rpo1 > rpo2){
8257dd7cddfSDavid du Colombier t = rpo2;
8267dd7cddfSDavid du Colombier rpo2 = rpo1;
8277dd7cddfSDavid du Colombier rpo1 = t;
8283e12c5d1SDavid du Colombier }
8297dd7cddfSDavid du Colombier while(rpo1 < rpo2){
8307dd7cddfSDavid du Colombier t = idom[rpo2];
8317dd7cddfSDavid du Colombier if(t >= rpo2)
832375daca8SDavid du Colombier fatal(Z, "bad idom");
8337dd7cddfSDavid du Colombier rpo2 = t;
8347dd7cddfSDavid du Colombier }
8357dd7cddfSDavid du Colombier }
8367dd7cddfSDavid du Colombier return rpo1;
8377dd7cddfSDavid du Colombier }
8387dd7cddfSDavid du Colombier
8397dd7cddfSDavid du Colombier int
doms(long * idom,long r,long s)8407dd7cddfSDavid du Colombier doms(long *idom, long r, long s)
8417dd7cddfSDavid du Colombier {
8427dd7cddfSDavid du Colombier while(s > r)
8437dd7cddfSDavid du Colombier s = idom[s];
8447dd7cddfSDavid du Colombier return s == r;
8457dd7cddfSDavid du Colombier }
8467dd7cddfSDavid du Colombier
8477dd7cddfSDavid du Colombier int
loophead(long * idom,Reg * r)8487dd7cddfSDavid du Colombier loophead(long *idom, Reg *r)
8497dd7cddfSDavid du Colombier {
8507dd7cddfSDavid du Colombier long src;
8517dd7cddfSDavid du Colombier
8527dd7cddfSDavid du Colombier src = r->rpo;
8537dd7cddfSDavid du Colombier if(r->p1 != R && doms(idom, src, r->p1->rpo))
8547dd7cddfSDavid du Colombier return 1;
8557dd7cddfSDavid du Colombier for(r = r->p2; r != R; r = r->p2link)
8567dd7cddfSDavid du Colombier if(doms(idom, src, r->rpo))
8577dd7cddfSDavid du Colombier return 1;
8587dd7cddfSDavid du Colombier return 0;
8597dd7cddfSDavid du Colombier }
8607dd7cddfSDavid du Colombier
8617dd7cddfSDavid du Colombier void
loopmark(Reg ** rpo2r,long head,Reg * r)8627dd7cddfSDavid du Colombier loopmark(Reg **rpo2r, long head, Reg *r)
8637dd7cddfSDavid du Colombier {
8647dd7cddfSDavid du Colombier if(r->rpo < head || r->active == head)
8657dd7cddfSDavid du Colombier return;
8667dd7cddfSDavid du Colombier r->active = head;
8677dd7cddfSDavid du Colombier r->loop += LOOP;
8687dd7cddfSDavid du Colombier if(r->p1 != R)
8697dd7cddfSDavid du Colombier loopmark(rpo2r, head, r->p1);
8707dd7cddfSDavid du Colombier for(r = r->p2; r != R; r = r->p2link)
8717dd7cddfSDavid du Colombier loopmark(rpo2r, head, r);
8727dd7cddfSDavid du Colombier }
8737dd7cddfSDavid du Colombier
8747dd7cddfSDavid du Colombier void
loopit(Reg * r,long nr)8757dd7cddfSDavid du Colombier loopit(Reg *r, long nr)
8767dd7cddfSDavid du Colombier {
87759cc4ca5SDavid du Colombier Reg *r1;
87859cc4ca5SDavid du Colombier long i, d, me;
8797dd7cddfSDavid du Colombier
88059cc4ca5SDavid du Colombier if(nr > maxnr) {
88159cc4ca5SDavid du Colombier rpo2r = alloc(nr * sizeof(Reg*));
88259cc4ca5SDavid du Colombier idom = alloc(nr * sizeof(long));
88359cc4ca5SDavid du Colombier maxnr = nr;
88459cc4ca5SDavid du Colombier }
88559cc4ca5SDavid du Colombier
8867dd7cddfSDavid du Colombier d = postorder(r, rpo2r, 0);
8877dd7cddfSDavid du Colombier if(d > nr)
888375daca8SDavid du Colombier fatal(Z, "too many reg nodes");
8897dd7cddfSDavid du Colombier nr = d;
8907dd7cddfSDavid du Colombier for(i = 0; i < nr / 2; i++){
8917dd7cddfSDavid du Colombier r1 = rpo2r[i];
8927dd7cddfSDavid du Colombier rpo2r[i] = rpo2r[nr - 1 - i];
8937dd7cddfSDavid du Colombier rpo2r[nr - 1 - i] = r1;
8947dd7cddfSDavid du Colombier }
8957dd7cddfSDavid du Colombier for(i = 0; i < nr; i++)
8967dd7cddfSDavid du Colombier rpo2r[i]->rpo = i;
8977dd7cddfSDavid du Colombier
8987dd7cddfSDavid du Colombier idom[0] = 0;
8997dd7cddfSDavid du Colombier for(i = 0; i < nr; i++){
9007dd7cddfSDavid du Colombier r1 = rpo2r[i];
9017dd7cddfSDavid du Colombier me = r1->rpo;
9027dd7cddfSDavid du Colombier d = -1;
9037dd7cddfSDavid du Colombier if(r1->p1 != R && r1->p1->rpo < me)
9047dd7cddfSDavid du Colombier d = r1->p1->rpo;
9057dd7cddfSDavid du Colombier for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
9067dd7cddfSDavid du Colombier if(r1->rpo < me)
9077dd7cddfSDavid du Colombier d = rpolca(idom, d, r1->rpo);
9087dd7cddfSDavid du Colombier idom[i] = d;
9097dd7cddfSDavid du Colombier }
9107dd7cddfSDavid du Colombier
9117dd7cddfSDavid du Colombier for(i = 0; i < nr; i++){
9127dd7cddfSDavid du Colombier r1 = rpo2r[i];
9137dd7cddfSDavid du Colombier r1->loop++;
9147dd7cddfSDavid du Colombier if(r1->p2 != R && loophead(idom, r1))
9157dd7cddfSDavid du Colombier loopmark(rpo2r, i, r1);
9167dd7cddfSDavid du Colombier }
9173e12c5d1SDavid du Colombier }
9183e12c5d1SDavid du Colombier
9193e12c5d1SDavid du Colombier void
synch(Reg * r,Bits dif)9203e12c5d1SDavid du Colombier synch(Reg *r, Bits dif)
9213e12c5d1SDavid du Colombier {
9223e12c5d1SDavid du Colombier Reg *r1;
9233e12c5d1SDavid du Colombier int z;
9243e12c5d1SDavid du Colombier
9253e12c5d1SDavid du Colombier for(r1 = r; r1 != R; r1 = r1->s1) {
9263e12c5d1SDavid du Colombier for(z=0; z<BITS; z++) {
9273e12c5d1SDavid du Colombier dif.b[z] = (dif.b[z] &
9283e12c5d1SDavid du Colombier ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
9293e12c5d1SDavid du Colombier r1->set.b[z] | r1->regdiff.b[z];
9303e12c5d1SDavid du Colombier if(dif.b[z] != r1->regdiff.b[z]) {
9313e12c5d1SDavid du Colombier r1->regdiff.b[z] = dif.b[z];
9323e12c5d1SDavid du Colombier change++;
9333e12c5d1SDavid du Colombier }
9343e12c5d1SDavid du Colombier }
9353e12c5d1SDavid du Colombier if(r1->active)
9363e12c5d1SDavid du Colombier break;
9373e12c5d1SDavid du Colombier r1->active = 1;
9383e12c5d1SDavid du Colombier for(z=0; z<BITS; z++)
9393e12c5d1SDavid du Colombier dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
9403e12c5d1SDavid du Colombier if(r1->s2 != R)
9413e12c5d1SDavid du Colombier synch(r1->s2, dif);
9423e12c5d1SDavid du Colombier }
9433e12c5d1SDavid du Colombier }
9443e12c5d1SDavid du Colombier
9453e12c5d1SDavid du Colombier ulong
allreg(ulong b,Rgn * r)9463e12c5d1SDavid du Colombier allreg(ulong b, Rgn *r)
9473e12c5d1SDavid du Colombier {
9483e12c5d1SDavid du Colombier Var *v;
9493e12c5d1SDavid du Colombier int i;
9503e12c5d1SDavid du Colombier
9513e12c5d1SDavid du Colombier v = var + r->varno;
9523e12c5d1SDavid du Colombier r->regno = 0;
9533e12c5d1SDavid du Colombier switch(v->etype) {
9543e12c5d1SDavid du Colombier
9553e12c5d1SDavid du Colombier default:
9563e12c5d1SDavid du Colombier diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
9573e12c5d1SDavid du Colombier break;
9583e12c5d1SDavid du Colombier
9593e12c5d1SDavid du Colombier case TCHAR:
9603e12c5d1SDavid du Colombier case TUCHAR:
9613e12c5d1SDavid du Colombier case TSHORT:
9623e12c5d1SDavid du Colombier case TUSHORT:
9637dd7cddfSDavid du Colombier case TINT:
9647dd7cddfSDavid du Colombier case TUINT:
9653e12c5d1SDavid du Colombier case TLONG:
9663e12c5d1SDavid du Colombier case TULONG:
9673e12c5d1SDavid du Colombier case TIND:
9683e12c5d1SDavid du Colombier case TARRAY:
9693e12c5d1SDavid du Colombier i = BtoR(~b);
9703e12c5d1SDavid du Colombier if(i && r->cost > 0) {
9713e12c5d1SDavid du Colombier r->regno = i;
9723e12c5d1SDavid du Colombier return RtoB(i);
9733e12c5d1SDavid du Colombier }
9743e12c5d1SDavid du Colombier break;
9753e12c5d1SDavid du Colombier
9763e12c5d1SDavid du Colombier case TDOUBLE:
9773e12c5d1SDavid du Colombier case TFLOAT:
9783e12c5d1SDavid du Colombier break;
9793e12c5d1SDavid du Colombier }
9803e12c5d1SDavid du Colombier return 0;
9813e12c5d1SDavid du Colombier }
9823e12c5d1SDavid du Colombier
9833e12c5d1SDavid du Colombier void
paint1(Reg * r,int bn)9843e12c5d1SDavid du Colombier paint1(Reg *r, int bn)
9853e12c5d1SDavid du Colombier {
9863e12c5d1SDavid du Colombier Reg *r1;
9873e12c5d1SDavid du Colombier Prog *p;
9883e12c5d1SDavid du Colombier int z;
9893e12c5d1SDavid du Colombier ulong bb;
9903e12c5d1SDavid du Colombier
9913e12c5d1SDavid du Colombier z = bn/32;
9923e12c5d1SDavid du Colombier bb = 1L<<(bn%32);
9933e12c5d1SDavid du Colombier if(r->act.b[z] & bb)
9943e12c5d1SDavid du Colombier return;
9953e12c5d1SDavid du Colombier for(;;) {
9963e12c5d1SDavid du Colombier if(!(r->refbehind.b[z] & bb))
9973e12c5d1SDavid du Colombier break;
9983e12c5d1SDavid du Colombier r1 = r->p1;
9993e12c5d1SDavid du Colombier if(r1 == R)
10003e12c5d1SDavid du Colombier break;
10013e12c5d1SDavid du Colombier if(!(r1->refahead.b[z] & bb))
10023e12c5d1SDavid du Colombier break;
10033e12c5d1SDavid du Colombier if(r1->act.b[z] & bb)
10043e12c5d1SDavid du Colombier break;
10053e12c5d1SDavid du Colombier r = r1;
10063e12c5d1SDavid du Colombier }
10073e12c5d1SDavid du Colombier
10083e12c5d1SDavid du Colombier if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
10093e12c5d1SDavid du Colombier change -= CLOAD * r->loop;
10103e12c5d1SDavid du Colombier if(debug['R'] && debug['v'])
10119a747e4fSDavid du Colombier print("%ld%P\tld %B $%d\n", r->loop,
10129a747e4fSDavid du Colombier r->prog, blsh(bn), change);
10133e12c5d1SDavid du Colombier }
10143e12c5d1SDavid du Colombier for(;;) {
10153e12c5d1SDavid du Colombier r->act.b[z] |= bb;
10163e12c5d1SDavid du Colombier p = r->prog;
10173e12c5d1SDavid du Colombier
10183e12c5d1SDavid du Colombier if(r->use1.b[z] & bb) {
10193e12c5d1SDavid du Colombier change += CREF * r->loop;
1020*d40255d8SDavid du Colombier if(p->as == AFMOVL || p->as == AFMOVW)
10213e12c5d1SDavid du Colombier if(BtoR(bb) != D_F0)
10223e12c5d1SDavid du Colombier change = -CINF;
10233e12c5d1SDavid du Colombier if(debug['R'] && debug['v'])
10249a747e4fSDavid du Colombier print("%ld%P\tu1 %B $%d\n", r->loop,
10259a747e4fSDavid du Colombier p, blsh(bn), change);
10263e12c5d1SDavid du Colombier }
10273e12c5d1SDavid du Colombier
10283e12c5d1SDavid du Colombier if((r->use2.b[z]|r->set.b[z]) & bb) {
10293e12c5d1SDavid du Colombier change += CREF * r->loop;
1030*d40255d8SDavid du Colombier if(p->as == AFMOVL || p->as == AFMOVW)
10313e12c5d1SDavid du Colombier if(BtoR(bb) != D_F0)
10323e12c5d1SDavid du Colombier change = -CINF;
10333e12c5d1SDavid du Colombier if(debug['R'] && debug['v'])
10349a747e4fSDavid du Colombier print("%ld%P\tu2 %B $%d\n", r->loop,
10359a747e4fSDavid du Colombier p, blsh(bn), change);
10363e12c5d1SDavid du Colombier }
10373e12c5d1SDavid du Colombier
10383e12c5d1SDavid du Colombier if(STORE(r) & r->regdiff.b[z] & bb) {
10393e12c5d1SDavid du Colombier change -= CLOAD * r->loop;
1040*d40255d8SDavid du Colombier if(p->as == AFMOVL || p->as == AFMOVW)
10413e12c5d1SDavid du Colombier if(BtoR(bb) != D_F0)
10423e12c5d1SDavid du Colombier change = -CINF;
10433e12c5d1SDavid du Colombier if(debug['R'] && debug['v'])
10449a747e4fSDavid du Colombier print("%ld%P\tst %B $%d\n", r->loop,
10459a747e4fSDavid du Colombier p, blsh(bn), change);
10463e12c5d1SDavid du Colombier }
10473e12c5d1SDavid du Colombier
10483e12c5d1SDavid du Colombier if(r->refbehind.b[z] & bb)
10493e12c5d1SDavid du Colombier for(r1 = r->p2; r1 != R; r1 = r1->p2link)
10503e12c5d1SDavid du Colombier if(r1->refahead.b[z] & bb)
10513e12c5d1SDavid du Colombier paint1(r1, bn);
10523e12c5d1SDavid du Colombier
10533e12c5d1SDavid du Colombier if(!(r->refahead.b[z] & bb))
10543e12c5d1SDavid du Colombier break;
10553e12c5d1SDavid du Colombier r1 = r->s2;
10563e12c5d1SDavid du Colombier if(r1 != R)
10573e12c5d1SDavid du Colombier if(r1->refbehind.b[z] & bb)
10583e12c5d1SDavid du Colombier paint1(r1, bn);
10593e12c5d1SDavid du Colombier r = r->s1;
10603e12c5d1SDavid du Colombier if(r == R)
10613e12c5d1SDavid du Colombier break;
10623e12c5d1SDavid du Colombier if(r->act.b[z] & bb)
10633e12c5d1SDavid du Colombier break;
10643e12c5d1SDavid du Colombier if(!(r->refbehind.b[z] & bb))
10653e12c5d1SDavid du Colombier break;
10663e12c5d1SDavid du Colombier }
10673e12c5d1SDavid du Colombier }
10683e12c5d1SDavid du Colombier
10693e12c5d1SDavid du Colombier ulong
regset(Reg * r,ulong bb)1070219b2ee8SDavid du Colombier regset(Reg *r, ulong bb)
1071219b2ee8SDavid du Colombier {
1072219b2ee8SDavid du Colombier ulong b, set;
1073219b2ee8SDavid du Colombier Adr v;
1074219b2ee8SDavid du Colombier int c;
1075219b2ee8SDavid du Colombier
1076219b2ee8SDavid du Colombier set = 0;
1077219b2ee8SDavid du Colombier v = zprog.from;
1078219b2ee8SDavid du Colombier while(b = bb & ~(bb-1)) {
1079219b2ee8SDavid du Colombier v.type = BtoR(b);
1080219b2ee8SDavid du Colombier c = copyu(r->prog, &v, A);
1081219b2ee8SDavid du Colombier if(c == 3)
1082219b2ee8SDavid du Colombier set |= b;
1083219b2ee8SDavid du Colombier bb &= ~b;
1084219b2ee8SDavid du Colombier }
1085219b2ee8SDavid du Colombier return set;
1086219b2ee8SDavid du Colombier }
1087219b2ee8SDavid du Colombier
1088219b2ee8SDavid du Colombier ulong
reguse(Reg * r,ulong bb)1089219b2ee8SDavid du Colombier reguse(Reg *r, ulong bb)
1090219b2ee8SDavid du Colombier {
1091219b2ee8SDavid du Colombier ulong b, set;
1092219b2ee8SDavid du Colombier Adr v;
1093219b2ee8SDavid du Colombier int c;
1094219b2ee8SDavid du Colombier
1095219b2ee8SDavid du Colombier set = 0;
1096219b2ee8SDavid du Colombier v = zprog.from;
1097219b2ee8SDavid du Colombier while(b = bb & ~(bb-1)) {
1098219b2ee8SDavid du Colombier v.type = BtoR(b);
1099219b2ee8SDavid du Colombier c = copyu(r->prog, &v, A);
1100219b2ee8SDavid du Colombier if(c == 1 || c == 2 || c == 4)
1101219b2ee8SDavid du Colombier set |= b;
1102219b2ee8SDavid du Colombier bb &= ~b;
1103219b2ee8SDavid du Colombier }
1104219b2ee8SDavid du Colombier return set;
1105219b2ee8SDavid du Colombier }
1106219b2ee8SDavid du Colombier
1107219b2ee8SDavid du Colombier ulong
paint2(Reg * r,int bn)11083e12c5d1SDavid du Colombier paint2(Reg *r, int bn)
11093e12c5d1SDavid du Colombier {
11103e12c5d1SDavid du Colombier Reg *r1;
11113e12c5d1SDavid du Colombier int z;
1112219b2ee8SDavid du Colombier ulong bb, vreg, x;
11133e12c5d1SDavid du Colombier
11143e12c5d1SDavid du Colombier z = bn/32;
11153e12c5d1SDavid du Colombier bb = 1L << (bn%32);
11163e12c5d1SDavid du Colombier vreg = regbits;
11173e12c5d1SDavid du Colombier if(!(r->act.b[z] & bb))
11183e12c5d1SDavid du Colombier return vreg;
11193e12c5d1SDavid du Colombier for(;;) {
11203e12c5d1SDavid du Colombier if(!(r->refbehind.b[z] & bb))
11213e12c5d1SDavid du Colombier break;
11223e12c5d1SDavid du Colombier r1 = r->p1;
11233e12c5d1SDavid du Colombier if(r1 == R)
11243e12c5d1SDavid du Colombier break;
11253e12c5d1SDavid du Colombier if(!(r1->refahead.b[z] & bb))
11263e12c5d1SDavid du Colombier break;
11273e12c5d1SDavid du Colombier if(!(r1->act.b[z] & bb))
11283e12c5d1SDavid du Colombier break;
11293e12c5d1SDavid du Colombier r = r1;
11303e12c5d1SDavid du Colombier }
11313e12c5d1SDavid du Colombier for(;;) {
11323e12c5d1SDavid du Colombier r->act.b[z] &= ~bb;
11333e12c5d1SDavid du Colombier
11343e12c5d1SDavid du Colombier vreg |= r->regu;
11353e12c5d1SDavid du Colombier
11363e12c5d1SDavid du Colombier if(r->refbehind.b[z] & bb)
11373e12c5d1SDavid du Colombier for(r1 = r->p2; r1 != R; r1 = r1->p2link)
11383e12c5d1SDavid du Colombier if(r1->refahead.b[z] & bb)
11393e12c5d1SDavid du Colombier vreg |= paint2(r1, bn);
11403e12c5d1SDavid du Colombier
11413e12c5d1SDavid du Colombier if(!(r->refahead.b[z] & bb))
11423e12c5d1SDavid du Colombier break;
11433e12c5d1SDavid du Colombier r1 = r->s2;
11443e12c5d1SDavid du Colombier if(r1 != R)
11453e12c5d1SDavid du Colombier if(r1->refbehind.b[z] & bb)
11463e12c5d1SDavid du Colombier vreg |= paint2(r1, bn);
11473e12c5d1SDavid du Colombier r = r->s1;
11483e12c5d1SDavid du Colombier if(r == R)
11493e12c5d1SDavid du Colombier break;
11503e12c5d1SDavid du Colombier if(!(r->act.b[z] & bb))
11513e12c5d1SDavid du Colombier break;
11523e12c5d1SDavid du Colombier if(!(r->refbehind.b[z] & bb))
11533e12c5d1SDavid du Colombier break;
11543e12c5d1SDavid du Colombier }
1155219b2ee8SDavid du Colombier
1156219b2ee8SDavid du Colombier bb = vreg;
1157219b2ee8SDavid du Colombier for(; r; r=r->s1) {
1158219b2ee8SDavid du Colombier x = r->regu & ~bb;
1159219b2ee8SDavid du Colombier if(x) {
1160219b2ee8SDavid du Colombier vreg |= reguse(r, x);
1161219b2ee8SDavid du Colombier bb |= regset(r, x);
1162219b2ee8SDavid du Colombier }
1163219b2ee8SDavid du Colombier }
11643e12c5d1SDavid du Colombier return vreg;
11653e12c5d1SDavid du Colombier }
11663e12c5d1SDavid du Colombier
11673e12c5d1SDavid du Colombier void
paint3(Reg * r,int bn,long rb,int rn)11683e12c5d1SDavid du Colombier paint3(Reg *r, int bn, long rb, int rn)
11693e12c5d1SDavid du Colombier {
11703e12c5d1SDavid du Colombier Reg *r1;
11713e12c5d1SDavid du Colombier Prog *p;
11723e12c5d1SDavid du Colombier int z;
11733e12c5d1SDavid du Colombier ulong bb;
11743e12c5d1SDavid du Colombier
11753e12c5d1SDavid du Colombier z = bn/32;
11763e12c5d1SDavid du Colombier bb = 1L << (bn%32);
11773e12c5d1SDavid du Colombier if(r->act.b[z] & bb)
11783e12c5d1SDavid du Colombier return;
11793e12c5d1SDavid du Colombier for(;;) {
11803e12c5d1SDavid du Colombier if(!(r->refbehind.b[z] & bb))
11813e12c5d1SDavid du Colombier break;
11823e12c5d1SDavid du Colombier r1 = r->p1;
11833e12c5d1SDavid du Colombier if(r1 == R)
11843e12c5d1SDavid du Colombier break;
11853e12c5d1SDavid du Colombier if(!(r1->refahead.b[z] & bb))
11863e12c5d1SDavid du Colombier break;
11873e12c5d1SDavid du Colombier if(r1->act.b[z] & bb)
11883e12c5d1SDavid du Colombier break;
11893e12c5d1SDavid du Colombier r = r1;
11903e12c5d1SDavid du Colombier }
11913e12c5d1SDavid du Colombier
11923e12c5d1SDavid du Colombier if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
11933e12c5d1SDavid du Colombier addmove(r, bn, rn, 0);
11943e12c5d1SDavid du Colombier for(;;) {
11953e12c5d1SDavid du Colombier r->act.b[z] |= bb;
11963e12c5d1SDavid du Colombier p = r->prog;
11973e12c5d1SDavid du Colombier
11983e12c5d1SDavid du Colombier if(r->use1.b[z] & bb) {
11993e12c5d1SDavid du Colombier if(debug['R'])
12003e12c5d1SDavid du Colombier print("%P", p);
12013e12c5d1SDavid du Colombier addreg(&p->from, rn);
12023e12c5d1SDavid du Colombier if(debug['R'])
12039a747e4fSDavid du Colombier print("\t.c%P\n", p);
12043e12c5d1SDavid du Colombier }
12053e12c5d1SDavid du Colombier if((r->use2.b[z]|r->set.b[z]) & bb) {
12063e12c5d1SDavid du Colombier if(debug['R'])
12073e12c5d1SDavid du Colombier print("%P", p);
12083e12c5d1SDavid du Colombier addreg(&p->to, rn);
12093e12c5d1SDavid du Colombier if(debug['R'])
12109a747e4fSDavid du Colombier print("\t.c%P\n", p);
12113e12c5d1SDavid du Colombier }
12123e12c5d1SDavid du Colombier
12133e12c5d1SDavid du Colombier if(STORE(r) & r->regdiff.b[z] & bb)
12143e12c5d1SDavid du Colombier addmove(r, bn, rn, 1);
12153e12c5d1SDavid du Colombier r->regu |= rb;
12163e12c5d1SDavid du Colombier
12173e12c5d1SDavid du Colombier if(r->refbehind.b[z] & bb)
12183e12c5d1SDavid du Colombier for(r1 = r->p2; r1 != R; r1 = r1->p2link)
12193e12c5d1SDavid du Colombier if(r1->refahead.b[z] & bb)
12203e12c5d1SDavid du Colombier paint3(r1, bn, rb, rn);
12213e12c5d1SDavid du Colombier
12223e12c5d1SDavid du Colombier if(!(r->refahead.b[z] & bb))
12233e12c5d1SDavid du Colombier break;
12243e12c5d1SDavid du Colombier r1 = r->s2;
12253e12c5d1SDavid du Colombier if(r1 != R)
12263e12c5d1SDavid du Colombier if(r1->refbehind.b[z] & bb)
12273e12c5d1SDavid du Colombier paint3(r1, bn, rb, rn);
12283e12c5d1SDavid du Colombier r = r->s1;
12293e12c5d1SDavid du Colombier if(r == R)
12303e12c5d1SDavid du Colombier break;
12313e12c5d1SDavid du Colombier if(r->act.b[z] & bb)
12323e12c5d1SDavid du Colombier break;
12333e12c5d1SDavid du Colombier if(!(r->refbehind.b[z] & bb))
12343e12c5d1SDavid du Colombier break;
12353e12c5d1SDavid du Colombier }
12363e12c5d1SDavid du Colombier }
12373e12c5d1SDavid du Colombier
12383e12c5d1SDavid du Colombier void
addreg(Adr * a,int rn)12393e12c5d1SDavid du Colombier addreg(Adr *a, int rn)
12403e12c5d1SDavid du Colombier {
12413e12c5d1SDavid du Colombier
12423e12c5d1SDavid du Colombier a->sym = 0;
12433e12c5d1SDavid du Colombier a->offset = 0;
12443e12c5d1SDavid du Colombier a->type = rn;
12453e12c5d1SDavid du Colombier }
12463e12c5d1SDavid du Colombier
12473e12c5d1SDavid du Colombier long
RtoB(int r)12483e12c5d1SDavid du Colombier RtoB(int r)
12493e12c5d1SDavid du Colombier {
12503e12c5d1SDavid du Colombier
12517dd7cddfSDavid du Colombier if(r < D_AX || r > D_DI)
12523e12c5d1SDavid du Colombier return 0;
12533e12c5d1SDavid du Colombier return 1L << (r-D_AX);
12543e12c5d1SDavid du Colombier }
12553e12c5d1SDavid du Colombier
12563e12c5d1SDavid du Colombier int
BtoR(long b)12573e12c5d1SDavid du Colombier BtoR(long b)
12583e12c5d1SDavid du Colombier {
12593e12c5d1SDavid du Colombier
12603e12c5d1SDavid du Colombier b &= 0xffL;
12613e12c5d1SDavid du Colombier if(b == 0)
12623e12c5d1SDavid du Colombier return 0;
12633e12c5d1SDavid du Colombier return bitno(b) + D_AX;
12643e12c5d1SDavid du Colombier }
1265