17edc7532SDavid du Colombier #include "gc.h"
27edc7532SDavid du Colombier
37edc7532SDavid du Colombier void addsplits(void);
47edc7532SDavid du Colombier
57edc7532SDavid du Colombier Reg*
rega(void)67edc7532SDavid du Colombier rega(void)
77edc7532SDavid du Colombier {
87edc7532SDavid du Colombier Reg *r;
97edc7532SDavid du Colombier
107edc7532SDavid du Colombier r = freer;
117edc7532SDavid du Colombier if(r == R) {
127edc7532SDavid du Colombier r = alloc(sizeof(*r));
137edc7532SDavid du Colombier } else
147edc7532SDavid du Colombier freer = r->link;
157edc7532SDavid du Colombier
167edc7532SDavid du Colombier *r = zreg;
177edc7532SDavid du Colombier return r;
187edc7532SDavid du Colombier }
197edc7532SDavid du Colombier
207edc7532SDavid du Colombier int
rcmp(const void * a1,const void * a2)217edc7532SDavid du Colombier rcmp(const void *a1, const void *a2)
227edc7532SDavid du Colombier {
237edc7532SDavid du Colombier Rgn *p1, *p2;
247edc7532SDavid du Colombier int c1, c2;
257edc7532SDavid du Colombier
267edc7532SDavid du Colombier p1 = (Rgn*)a1;
277edc7532SDavid du Colombier p2 = (Rgn*)a2;
287edc7532SDavid du Colombier c1 = p2->cost;
297edc7532SDavid du Colombier c2 = p1->cost;
307edc7532SDavid du Colombier if(c1 -= c2)
317edc7532SDavid du Colombier return c1;
327edc7532SDavid du Colombier return p2->varno - p1->varno;
337edc7532SDavid du Colombier }
347edc7532SDavid du Colombier
357edc7532SDavid du Colombier void
regopt(Prog * p)367edc7532SDavid du Colombier regopt(Prog *p)
377edc7532SDavid du Colombier {
387edc7532SDavid du Colombier Reg *r, *r1, *r2;
397edc7532SDavid du Colombier Prog *p1;
407edc7532SDavid du Colombier int i, z;
417edc7532SDavid du Colombier long initpc, val, npc;
427edc7532SDavid du Colombier ulong vreg;
437edc7532SDavid du Colombier Bits bit;
447edc7532SDavid du Colombier struct
457edc7532SDavid du Colombier {
467edc7532SDavid du Colombier long m;
477edc7532SDavid du Colombier long c;
487edc7532SDavid du Colombier Reg* p;
497edc7532SDavid du Colombier } log5[6], *lp;
507edc7532SDavid du Colombier
517edc7532SDavid du Colombier firstr = R;
527edc7532SDavid du Colombier lastr = R;
537edc7532SDavid du Colombier nvar = 0;
547edc7532SDavid du Colombier regbits = 0;
557edc7532SDavid du Colombier for(z=0; z<BITS; z++) {
567edc7532SDavid du Colombier externs.b[z] = 0;
577edc7532SDavid du Colombier params.b[z] = 0;
587edc7532SDavid du Colombier consts.b[z] = 0;
597edc7532SDavid du Colombier addrs.b[z] = 0;
607edc7532SDavid du Colombier }
617edc7532SDavid du Colombier
627edc7532SDavid du Colombier /*
637edc7532SDavid du Colombier * pass 1
647edc7532SDavid du Colombier * build aux data structure
657edc7532SDavid du Colombier * allocate pcs
667edc7532SDavid du Colombier * find use and set of variables
677edc7532SDavid du Colombier */
687edc7532SDavid du Colombier val = 5L * 5L * 5L * 5L * 5L;
697edc7532SDavid du Colombier lp = log5;
707edc7532SDavid du Colombier for(i=0; i<5; i++) {
717edc7532SDavid du Colombier lp->m = val;
727edc7532SDavid du Colombier lp->c = 0;
737edc7532SDavid du Colombier lp->p = R;
747edc7532SDavid du Colombier val /= 5L;
757edc7532SDavid du Colombier lp++;
767edc7532SDavid du Colombier }
777edc7532SDavid du Colombier val = 0;
787edc7532SDavid du Colombier for(; p != P; p = p->link) {
797edc7532SDavid du Colombier switch(p->as) {
807edc7532SDavid du Colombier case ADATA:
817edc7532SDavid du Colombier case AGLOBL:
827edc7532SDavid du Colombier case ANAME:
83*f8bc6aafSDavid du Colombier case ASIGNAME:
847edc7532SDavid du Colombier continue;
857edc7532SDavid du Colombier }
867edc7532SDavid du Colombier r = rega();
877edc7532SDavid du Colombier if(firstr == R) {
887edc7532SDavid du Colombier firstr = r;
897edc7532SDavid du Colombier lastr = r;
907edc7532SDavid du Colombier } else {
917edc7532SDavid du Colombier lastr->link = r;
927edc7532SDavid du Colombier r->p1 = lastr;
937edc7532SDavid du Colombier lastr->s1 = r;
947edc7532SDavid du Colombier lastr = r;
957edc7532SDavid du Colombier }
967edc7532SDavid du Colombier r->prog = p;
977edc7532SDavid du Colombier r->pc = val;
987edc7532SDavid du Colombier val++;
997edc7532SDavid du Colombier
1007edc7532SDavid du Colombier lp = log5;
1017edc7532SDavid du Colombier for(i=0; i<5; i++) {
1027edc7532SDavid du Colombier lp->c--;
1037edc7532SDavid du Colombier if(lp->c <= 0) {
1047edc7532SDavid du Colombier lp->c = lp->m;
1057edc7532SDavid du Colombier if(lp->p != R)
1067edc7532SDavid du Colombier lp->p->log5 = r;
1077edc7532SDavid du Colombier lp->p = r;
1087edc7532SDavid du Colombier (lp+1)->c = 0;
1097edc7532SDavid du Colombier break;
1107edc7532SDavid du Colombier }
1117edc7532SDavid du Colombier lp++;
1127edc7532SDavid du Colombier }
1137edc7532SDavid du Colombier
1147edc7532SDavid du Colombier r1 = r->p1;
1157edc7532SDavid du Colombier if(r1 != R)
1167edc7532SDavid du Colombier switch(r1->prog->as) {
1177edc7532SDavid du Colombier case ARET:
1187edc7532SDavid du Colombier case AJMP:
1197edc7532SDavid du Colombier case ARFE:
1207edc7532SDavid du Colombier r->p1 = R;
1217edc7532SDavid du Colombier r1->s1 = R;
1227edc7532SDavid du Colombier }
1237edc7532SDavid du Colombier
1247edc7532SDavid du Colombier /*
1257edc7532SDavid du Colombier * left side always read
1267edc7532SDavid du Colombier */
1277edc7532SDavid du Colombier bit = mkvar(&p->from, p->as==AMOVW);
1287edc7532SDavid du Colombier for(z=0; z<BITS; z++)
1297edc7532SDavid du Colombier r->use1.b[z] |= bit.b[z];
1307edc7532SDavid du Colombier
1317edc7532SDavid du Colombier /*
1327edc7532SDavid du Colombier * right side depends on opcode
1337edc7532SDavid du Colombier */
1347edc7532SDavid du Colombier bit = mkvar(&p->to, 0);
1357edc7532SDavid du Colombier if(bany(&bit))
1367edc7532SDavid du Colombier switch(p->as) {
1377edc7532SDavid du Colombier default:
1387edc7532SDavid du Colombier diag(Z, "reg: unknown asop: %A", p->as);
1397edc7532SDavid du Colombier break;
1407edc7532SDavid du Colombier
1417edc7532SDavid du Colombier /*
1427edc7532SDavid du Colombier * right side write
1437edc7532SDavid du Colombier */
1447edc7532SDavid du Colombier case ANOP:
1457edc7532SDavid du Colombier case AMOVB:
1467edc7532SDavid du Colombier case AMOVBU:
1477edc7532SDavid du Colombier case AMOVH:
1487edc7532SDavid du Colombier case AMOVHU:
1497edc7532SDavid du Colombier case AMOVW:
1507edc7532SDavid du Colombier case AMOVV:
1517edc7532SDavid du Colombier case AMOVF:
1527edc7532SDavid du Colombier case AMOVD:
1537edc7532SDavid du Colombier for(z=0; z<BITS; z++)
1547edc7532SDavid du Colombier r->set.b[z] |= bit.b[z];
1557edc7532SDavid du Colombier break;
1567edc7532SDavid du Colombier
1577edc7532SDavid du Colombier /*
1587edc7532SDavid du Colombier * funny
1597edc7532SDavid du Colombier */
1607edc7532SDavid du Colombier case AJAL:
1617edc7532SDavid du Colombier for(z=0; z<BITS; z++)
1627edc7532SDavid du Colombier addrs.b[z] |= bit.b[z];
1637edc7532SDavid du Colombier break;
1647edc7532SDavid du Colombier }
1657edc7532SDavid du Colombier }
1667edc7532SDavid du Colombier if(firstr == R)
1677edc7532SDavid du Colombier return;
1687edc7532SDavid du Colombier initpc = pc - val;
1697edc7532SDavid du Colombier npc = val;
1707edc7532SDavid du Colombier
1717edc7532SDavid du Colombier /*
1727edc7532SDavid du Colombier * pass 2
1737edc7532SDavid du Colombier * turn branch references to pointers
1747edc7532SDavid du Colombier * build back pointers
1757edc7532SDavid du Colombier */
1767edc7532SDavid du Colombier for(r = firstr; r != R; r = r->link) {
1777edc7532SDavid du Colombier p = r->prog;
1787edc7532SDavid du Colombier if(p->to.type == D_BRANCH) {
1797edc7532SDavid du Colombier val = p->to.offset - initpc;
1807edc7532SDavid du Colombier r1 = firstr;
1817edc7532SDavid du Colombier while(r1 != R) {
1827edc7532SDavid du Colombier r2 = r1->log5;
1837edc7532SDavid du Colombier if(r2 != R && val >= r2->pc) {
1847edc7532SDavid du Colombier r1 = r2;
1857edc7532SDavid du Colombier continue;
1867edc7532SDavid du Colombier }
1877edc7532SDavid du Colombier if(r1->pc == val)
1887edc7532SDavid du Colombier break;
1897edc7532SDavid du Colombier r1 = r1->link;
1907edc7532SDavid du Colombier }
1917edc7532SDavid du Colombier if(r1 == R) {
1927edc7532SDavid du Colombier nearln = p->lineno;
1937edc7532SDavid du Colombier diag(Z, "ref not found\n%P", p);
1947edc7532SDavid du Colombier continue;
1957edc7532SDavid du Colombier }
1967edc7532SDavid du Colombier if(r1 == r) {
1977edc7532SDavid du Colombier nearln = p->lineno;
1987edc7532SDavid du Colombier diag(Z, "ref to self\n%P", p);
1997edc7532SDavid du Colombier continue;
2007edc7532SDavid du Colombier }
2017edc7532SDavid du Colombier r->s2 = r1;
2027edc7532SDavid du Colombier r->p2link = r1->p2;
2037edc7532SDavid du Colombier r1->p2 = r;
2047edc7532SDavid du Colombier }
2057edc7532SDavid du Colombier }
2067edc7532SDavid du Colombier if(debug['R']) {
2077edc7532SDavid du Colombier p = firstr->prog;
2087edc7532SDavid du Colombier print("\n%L %D\n", p->lineno, &p->from);
2097edc7532SDavid du Colombier }
2107edc7532SDavid du Colombier
2117edc7532SDavid du Colombier /*
2127edc7532SDavid du Colombier * pass 2.5
2137edc7532SDavid du Colombier * find looping structure
2147edc7532SDavid du Colombier */
2157edc7532SDavid du Colombier for(r = firstr; r != R; r = r->link)
2167edc7532SDavid du Colombier r->active = 0;
2177edc7532SDavid du Colombier change = 0;
2187edc7532SDavid du Colombier loopit(firstr, npc);
2197edc7532SDavid du Colombier
2207edc7532SDavid du Colombier /*
2217edc7532SDavid du Colombier * pass 3
2227edc7532SDavid du Colombier * iterate propagating usage
2237edc7532SDavid du Colombier * back until flow graph is complete
2247edc7532SDavid du Colombier */
2257edc7532SDavid du Colombier loop1:
2267edc7532SDavid du Colombier change = 0;
2277edc7532SDavid du Colombier for(r = firstr; r != R; r = r->link)
2287edc7532SDavid du Colombier r->active = 0;
2297edc7532SDavid du Colombier for(r = firstr; r != R; r = r->link)
2307edc7532SDavid du Colombier if(r->prog->as == ARET)
2317edc7532SDavid du Colombier prop(r, zbits, zbits);
2327edc7532SDavid du Colombier loop11:
2337edc7532SDavid du Colombier /* pick up unreachable code */
2347edc7532SDavid du Colombier i = 0;
2357edc7532SDavid du Colombier for(r = firstr; r != R; r = r1) {
2367edc7532SDavid du Colombier r1 = r->link;
2377edc7532SDavid du Colombier if(r1 && r1->active && !r->active) {
2387edc7532SDavid du Colombier prop(r, zbits, zbits);
2397edc7532SDavid du Colombier i = 1;
2407edc7532SDavid du Colombier }
2417edc7532SDavid du Colombier }
2427edc7532SDavid du Colombier if(i)
2437edc7532SDavid du Colombier goto loop11;
2447edc7532SDavid du Colombier if(change)
2457edc7532SDavid du Colombier goto loop1;
2467edc7532SDavid du Colombier
2477edc7532SDavid du Colombier
2487edc7532SDavid du Colombier /*
2497edc7532SDavid du Colombier * pass 4
2507edc7532SDavid du Colombier * iterate propagating register/variable synchrony
2517edc7532SDavid du Colombier * forward until graph is complete
2527edc7532SDavid du Colombier */
2537edc7532SDavid du Colombier loop2:
2547edc7532SDavid du Colombier change = 0;
2557edc7532SDavid du Colombier for(r = firstr; r != R; r = r->link)
2567edc7532SDavid du Colombier r->active = 0;
2577edc7532SDavid du Colombier synch(firstr, zbits);
2587edc7532SDavid du Colombier if(change)
2597edc7532SDavid du Colombier goto loop2;
2607edc7532SDavid du Colombier
2617edc7532SDavid du Colombier addsplits();
2627edc7532SDavid du Colombier
2637edc7532SDavid du Colombier if(debug['R'] && debug['v']) {
2647edc7532SDavid du Colombier print("\nprop structure:\n");
2657edc7532SDavid du Colombier for(r = firstr; r != R; r = r->link) {
2667edc7532SDavid du Colombier print("%ld:%P", r->loop, r->prog);
2677edc7532SDavid du Colombier for(z=0; z<BITS; z++)
2687edc7532SDavid du Colombier bit.b[z] = r->set.b[z] |
2697edc7532SDavid du Colombier r->refahead.b[z] | r->calahead.b[z] |
2707edc7532SDavid du Colombier r->refbehind.b[z] | r->calbehind.b[z] |
2717edc7532SDavid du Colombier r->use1.b[z] | r->use2.b[z];
2727edc7532SDavid du Colombier if(bany(&bit)) {
2737edc7532SDavid du Colombier print("\t");
2747edc7532SDavid du Colombier if(bany(&r->use1))
2757edc7532SDavid du Colombier print(" u1=%B", r->use1);
2767edc7532SDavid du Colombier if(bany(&r->use2))
2777edc7532SDavid du Colombier print(" u2=%B", r->use2);
2787edc7532SDavid du Colombier if(bany(&r->set))
2797edc7532SDavid du Colombier print(" st=%B", r->set);
2807edc7532SDavid du Colombier if(bany(&r->refahead))
2817edc7532SDavid du Colombier print(" ra=%B", r->refahead);
2827edc7532SDavid du Colombier if(bany(&r->calahead))
2837edc7532SDavid du Colombier print(" ca=%B", r->calahead);
2847edc7532SDavid du Colombier if(bany(&r->refbehind))
2857edc7532SDavid du Colombier print(" rb=%B", r->refbehind);
2867edc7532SDavid du Colombier if(bany(&r->calbehind))
2877edc7532SDavid du Colombier print(" cb=%B", r->calbehind);
288*f8bc6aafSDavid du Colombier if(bany(&r->regdiff))
289*f8bc6aafSDavid du Colombier print(" rd=%B", r->regdiff);
2907edc7532SDavid du Colombier }
2917edc7532SDavid du Colombier print("\n");
2927edc7532SDavid du Colombier }
2937edc7532SDavid du Colombier }
2947edc7532SDavid du Colombier
2957edc7532SDavid du Colombier /*
2967edc7532SDavid du Colombier * pass 5
2977edc7532SDavid du Colombier * isolate regions
2987edc7532SDavid du Colombier * calculate costs (paint1)
2997edc7532SDavid du Colombier */
3007edc7532SDavid du Colombier r = firstr;
3017edc7532SDavid du Colombier if(r) {
3027edc7532SDavid du Colombier for(z=0; z<BITS; z++)
3037edc7532SDavid du Colombier bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
3047edc7532SDavid du Colombier ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
3057edc7532SDavid du Colombier if(bany(&bit)) {
3067edc7532SDavid du Colombier nearln = r->prog->lineno;
3077edc7532SDavid du Colombier warn(Z, "used and not set: %B", bit);
3087edc7532SDavid du Colombier if(debug['R'] && !debug['w'])
3097edc7532SDavid du Colombier print("used and not set: %B\n", bit);
3107edc7532SDavid du Colombier }
3117edc7532SDavid du Colombier }
3127edc7532SDavid du Colombier
3137edc7532SDavid du Colombier for(r = firstr; r != R; r = r->link)
3147edc7532SDavid du Colombier r->act = zbits;
3157edc7532SDavid du Colombier rgp = region;
3167edc7532SDavid du Colombier nregion = 0;
3177edc7532SDavid du Colombier for(r = firstr; r != R; r = r->link) {
3187edc7532SDavid du Colombier for(z=0; z<BITS; z++)
3197edc7532SDavid du Colombier bit.b[z] = r->set.b[z] &
3207edc7532SDavid du Colombier ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
3217edc7532SDavid du Colombier if(bany(&bit)) {
3227edc7532SDavid du Colombier nearln = r->prog->lineno;
3237edc7532SDavid du Colombier warn(Z, "set and not used: %B", bit);
3247edc7532SDavid du Colombier if(debug['R'])
3257edc7532SDavid du Colombier print("set and not used: %B\n", bit);
3267edc7532SDavid du Colombier excise(r);
3277edc7532SDavid du Colombier }
3287edc7532SDavid du Colombier for(z=0; z<BITS; z++)
3297edc7532SDavid du Colombier bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
3307edc7532SDavid du Colombier while(bany(&bit)) {
3317edc7532SDavid du Colombier i = bnum(bit);
3327edc7532SDavid du Colombier rgp->enter = r;
3337edc7532SDavid du Colombier rgp->varno = i;
3347edc7532SDavid du Colombier change = 0;
3357edc7532SDavid du Colombier if(debug['R'] && debug['v'])
3367edc7532SDavid du Colombier print("\n");
3377edc7532SDavid du Colombier paint1(r, i);
3387edc7532SDavid du Colombier bit.b[i/32] &= ~(1L<<(i%32));
3397edc7532SDavid du Colombier if(change <= 0) {
3407edc7532SDavid du Colombier if(debug['R'])
3417edc7532SDavid du Colombier print("%L $%d: %B\n",
3427edc7532SDavid du Colombier r->prog->lineno, change, blsh(i));
3437edc7532SDavid du Colombier continue;
3447edc7532SDavid du Colombier }
3457edc7532SDavid du Colombier rgp->cost = change;
3467edc7532SDavid du Colombier nregion++;
3477edc7532SDavid du Colombier if(nregion >= NRGN) {
3487edc7532SDavid du Colombier warn(Z, "too many regions");
3497edc7532SDavid du Colombier goto brk;
3507edc7532SDavid du Colombier }
3517edc7532SDavid du Colombier rgp++;
3527edc7532SDavid du Colombier }
3537edc7532SDavid du Colombier }
3547edc7532SDavid du Colombier brk:
3557edc7532SDavid du Colombier qsort(region, nregion, sizeof(region[0]), rcmp);
3567edc7532SDavid du Colombier
3577edc7532SDavid du Colombier /*
3587edc7532SDavid du Colombier * pass 6
3597edc7532SDavid du Colombier * determine used registers (paint2)
3607edc7532SDavid du Colombier * replace code (paint3)
3617edc7532SDavid du Colombier */
3627edc7532SDavid du Colombier rgp = region;
3637edc7532SDavid du Colombier for(i=0; i<nregion; i++) {
3647edc7532SDavid du Colombier bit = blsh(rgp->varno);
3657edc7532SDavid du Colombier vreg = paint2(rgp->enter, rgp->varno);
3667edc7532SDavid du Colombier vreg = allreg(vreg, rgp);
3677edc7532SDavid du Colombier if(debug['R']) {
3687edc7532SDavid du Colombier if(rgp->regno >= NREG)
3697edc7532SDavid du Colombier print("%L $%d F%d: %B\n",
3707edc7532SDavid du Colombier rgp->enter->prog->lineno,
3717edc7532SDavid du Colombier rgp->cost,
3727edc7532SDavid du Colombier rgp->regno-NREG,
3737edc7532SDavid du Colombier bit);
3747edc7532SDavid du Colombier else
3757edc7532SDavid du Colombier print("%L $%d R%d: %B\n",
3767edc7532SDavid du Colombier rgp->enter->prog->lineno,
3777edc7532SDavid du Colombier rgp->cost,
3787edc7532SDavid du Colombier rgp->regno,
3797edc7532SDavid du Colombier bit);
3807edc7532SDavid du Colombier }
3817edc7532SDavid du Colombier if(rgp->regno != 0)
3827edc7532SDavid du Colombier paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
3837edc7532SDavid du Colombier rgp++;
3847edc7532SDavid du Colombier }
3857edc7532SDavid du Colombier /*
3867edc7532SDavid du Colombier * pass 7
3877edc7532SDavid du Colombier * peep-hole on basic block
3887edc7532SDavid du Colombier */
3897edc7532SDavid du Colombier if(!debug['R'] || debug['P'])
3907edc7532SDavid du Colombier peep();
3917edc7532SDavid du Colombier
3927edc7532SDavid du Colombier /*
3937edc7532SDavid du Colombier * pass 8
3947edc7532SDavid du Colombier * recalculate pc
3957edc7532SDavid du Colombier */
3967edc7532SDavid du Colombier val = initpc;
3977edc7532SDavid du Colombier for(r = firstr; r != R; r = r1) {
3987edc7532SDavid du Colombier r->pc = val;
3997edc7532SDavid du Colombier p = r->prog;
4007edc7532SDavid du Colombier p1 = P;
4017edc7532SDavid du Colombier r1 = r->link;
4027edc7532SDavid du Colombier if(r1 != R)
4037edc7532SDavid du Colombier p1 = r1->prog;
4047edc7532SDavid du Colombier for(; p != p1; p = p->link) {
4057edc7532SDavid du Colombier switch(p->as) {
4067edc7532SDavid du Colombier default:
4077edc7532SDavid du Colombier val++;
4087edc7532SDavid du Colombier break;
4097edc7532SDavid du Colombier
4107edc7532SDavid du Colombier case ANOP:
4117edc7532SDavid du Colombier case ADATA:
4127edc7532SDavid du Colombier case AGLOBL:
4137edc7532SDavid du Colombier case ANAME:
414*f8bc6aafSDavid du Colombier case ASIGNAME:
4157edc7532SDavid du Colombier break;
4167edc7532SDavid du Colombier }
4177edc7532SDavid du Colombier }
4187edc7532SDavid du Colombier }
4197edc7532SDavid du Colombier pc = val;
4207edc7532SDavid du Colombier
4217edc7532SDavid du Colombier /*
4227edc7532SDavid du Colombier * fix up branches
4237edc7532SDavid du Colombier */
4247edc7532SDavid du Colombier if(debug['R'])
4257edc7532SDavid du Colombier if(bany(&addrs))
4267edc7532SDavid du Colombier print("addrs: %B\n", addrs);
4277edc7532SDavid du Colombier
4287edc7532SDavid du Colombier r1 = 0; /* set */
4297edc7532SDavid du Colombier for(r = firstr; r != R; r = r->link) {
4307edc7532SDavid du Colombier p = r->prog;
4317edc7532SDavid du Colombier if(p->to.type == D_BRANCH)
4327edc7532SDavid du Colombier p->to.offset = r->s2->pc;
4337edc7532SDavid du Colombier r1 = r;
4347edc7532SDavid du Colombier }
4357edc7532SDavid du Colombier
4367edc7532SDavid du Colombier /*
4377edc7532SDavid du Colombier * last pass
4387edc7532SDavid du Colombier * eliminate nops
4397edc7532SDavid du Colombier * free aux structures
4407edc7532SDavid du Colombier */
4417edc7532SDavid du Colombier for(p = firstr->prog; p != P; p = p->link){
4427edc7532SDavid du Colombier while(p->link && p->link->as == ANOP)
4437edc7532SDavid du Colombier p->link = p->link->link;
4447edc7532SDavid du Colombier }
4457edc7532SDavid du Colombier if(r1 != R) {
4467edc7532SDavid du Colombier r1->link = freer;
4477edc7532SDavid du Colombier freer = firstr;
4487edc7532SDavid du Colombier }
4497edc7532SDavid du Colombier }
4507edc7532SDavid du Colombier
4517edc7532SDavid du Colombier void
addsplits(void)4527edc7532SDavid du Colombier addsplits(void)
4537edc7532SDavid du Colombier {
4547edc7532SDavid du Colombier Reg *r, *r1;
4557edc7532SDavid du Colombier int z, i;
4567edc7532SDavid du Colombier Bits bit;
4577edc7532SDavid du Colombier
4587edc7532SDavid du Colombier for(r = firstr; r != R; r = r->link) {
4597edc7532SDavid du Colombier if(r->loop > 1)
4607edc7532SDavid du Colombier continue;
4617edc7532SDavid du Colombier if(r->prog->as == AJAL)
4627edc7532SDavid du Colombier continue;
4637edc7532SDavid du Colombier for(r1 = r->p2; r1 != R; r1 = r1->p2link) {
4647edc7532SDavid du Colombier if(r1->loop <= 1)
4657edc7532SDavid du Colombier continue;
4667edc7532SDavid du Colombier for(z=0; z<BITS; z++)
4677edc7532SDavid du Colombier bit.b[z] = r1->calbehind.b[z] &
4687edc7532SDavid du Colombier (r->refahead.b[z] | r->use1.b[z] | r->use2.b[z]) &
4697edc7532SDavid du Colombier ~(r->calahead.b[z] & addrs.b[z]);
4707edc7532SDavid du Colombier while(bany(&bit)) {
4717edc7532SDavid du Colombier i = bnum(bit);
4727edc7532SDavid du Colombier bit.b[i/32] &= ~(1L << (i%32));
4737edc7532SDavid du Colombier }
4747edc7532SDavid du Colombier }
4757edc7532SDavid du Colombier }
4767edc7532SDavid du Colombier }
4777edc7532SDavid du Colombier
4787edc7532SDavid du Colombier /*
4797edc7532SDavid du Colombier * add mov b,rn
4807edc7532SDavid du Colombier * just after r
4817edc7532SDavid du Colombier */
4827edc7532SDavid du Colombier void
addmove(Reg * r,int bn,int rn,int f)4837edc7532SDavid du Colombier addmove(Reg *r, int bn, int rn, int f)
4847edc7532SDavid du Colombier {
4857edc7532SDavid du Colombier Prog *p, *p1;
4867edc7532SDavid du Colombier Adr *a;
4877edc7532SDavid du Colombier Var *v;
4887edc7532SDavid du Colombier
4897edc7532SDavid du Colombier p1 = alloc(sizeof(*p1));
4907edc7532SDavid du Colombier *p1 = zprog;
4917edc7532SDavid du Colombier p = r->prog;
4927edc7532SDavid du Colombier
4937edc7532SDavid du Colombier p1->link = p->link;
4947edc7532SDavid du Colombier p->link = p1;
4957edc7532SDavid du Colombier p1->lineno = p->lineno;
4967edc7532SDavid du Colombier
4977edc7532SDavid du Colombier v = var + bn;
4987edc7532SDavid du Colombier
4997edc7532SDavid du Colombier a = &p1->to;
5007edc7532SDavid du Colombier a->sym = v->sym;
5017edc7532SDavid du Colombier a->name = v->name;
5027edc7532SDavid du Colombier a->offset = v->offset;
5037edc7532SDavid du Colombier a->etype = v->etype;
5047edc7532SDavid du Colombier a->type = D_OREG;
5057edc7532SDavid du Colombier if(a->etype == TARRAY || a->sym == S)
5067edc7532SDavid du Colombier a->type = D_CONST;
5077edc7532SDavid du Colombier
5087edc7532SDavid du Colombier p1->as = AMOVW;
5097edc7532SDavid du Colombier if(v->etype == TCHAR || v->etype == TUCHAR)
5107edc7532SDavid du Colombier p1->as = AMOVB;
5117edc7532SDavid du Colombier if(v->etype == TSHORT || v->etype == TUSHORT)
5127edc7532SDavid du Colombier p1->as = AMOVH;
5137edc7532SDavid du Colombier if(v->etype == TVLONG || v->etype == TUVLONG || v->etype == TIND)
5147edc7532SDavid du Colombier p1->as = AMOVV;
5157edc7532SDavid du Colombier if(v->etype == TFLOAT)
5167edc7532SDavid du Colombier p1->as = AMOVF;
5177edc7532SDavid du Colombier if(v->etype == TDOUBLE)
5187edc7532SDavid du Colombier p1->as = AMOVD;
5197edc7532SDavid du Colombier
5207edc7532SDavid du Colombier p1->from.type = D_REG;
5217edc7532SDavid du Colombier p1->from.reg = rn;
5227edc7532SDavid du Colombier if(rn >= NREG) {
5237edc7532SDavid du Colombier p1->from.type = D_FREG;
5247edc7532SDavid du Colombier p1->from.reg = rn-NREG;
5257edc7532SDavid du Colombier }
5267edc7532SDavid du Colombier if(!f) {
5277edc7532SDavid du Colombier p1->from = *a;
5287edc7532SDavid du Colombier *a = zprog.from;
5297edc7532SDavid du Colombier a->type = D_REG;
5307edc7532SDavid du Colombier a->reg = rn;
5317edc7532SDavid du Colombier if(rn >= NREG) {
5327edc7532SDavid du Colombier a->type = D_FREG;
5337edc7532SDavid du Colombier a->reg = rn-NREG;
5347edc7532SDavid du Colombier }
5357edc7532SDavid du Colombier if(v->etype == TUCHAR)
5367edc7532SDavid du Colombier p1->as = AMOVBU;
5377edc7532SDavid du Colombier if(v->etype == TUSHORT)
5387edc7532SDavid du Colombier p1->as = AMOVHU;
5397edc7532SDavid du Colombier }
5407edc7532SDavid du Colombier if(debug['R'])
5417edc7532SDavid du Colombier print("%P\t.a%P\n", p, p1);
5427edc7532SDavid du Colombier }
5437edc7532SDavid du Colombier
5447edc7532SDavid du Colombier Bits
mkvar(Adr * a,int docon)5457edc7532SDavid du Colombier mkvar(Adr *a, int docon)
5467edc7532SDavid du Colombier {
5477edc7532SDavid du Colombier Var *v;
5487edc7532SDavid du Colombier int i, t, n, et, z;
5497edc7532SDavid du Colombier long o;
5507edc7532SDavid du Colombier Bits bit;
5517edc7532SDavid du Colombier Sym *s;
5527edc7532SDavid du Colombier
5537edc7532SDavid du Colombier t = a->type;
5547edc7532SDavid du Colombier if(t == D_REG && a->reg != NREG)
5557edc7532SDavid du Colombier regbits |= RtoB(a->reg);
5567edc7532SDavid du Colombier if(t == D_FREG && a->reg != NREG)
5577edc7532SDavid du Colombier regbits |= FtoB(a->reg);
5587edc7532SDavid du Colombier s = a->sym;
5597edc7532SDavid du Colombier o = a->offset;
5607edc7532SDavid du Colombier et = a->etype;
5617edc7532SDavid du Colombier if(s == S) {
5627edc7532SDavid du Colombier if(t != D_CONST || !docon || a->reg != NREG)
5637edc7532SDavid du Colombier goto none;
5647edc7532SDavid du Colombier et = TLONG;
5657edc7532SDavid du Colombier }
5667edc7532SDavid du Colombier if(t == D_CONST) {
5677edc7532SDavid du Colombier if(s == S && sval(o))
5687edc7532SDavid du Colombier goto none;
5697edc7532SDavid du Colombier }
5707edc7532SDavid du Colombier
5717edc7532SDavid du Colombier n = a->name;
5727edc7532SDavid du Colombier v = var;
5737edc7532SDavid du Colombier for(i=0; i<nvar; i++) {
5747edc7532SDavid du Colombier if(s == v->sym)
5757edc7532SDavid du Colombier if(n == v->name)
5767edc7532SDavid du Colombier if(o == v->offset)
5777edc7532SDavid du Colombier goto out;
5787edc7532SDavid du Colombier v++;
5797edc7532SDavid du Colombier }
5807edc7532SDavid du Colombier if(s)
5817edc7532SDavid du Colombier if(s->name[0] == '.')
5827edc7532SDavid du Colombier goto none;
5837edc7532SDavid du Colombier if(nvar >= NVAR) {
5847edc7532SDavid du Colombier if(debug['w'] > 1 && s)
5857edc7532SDavid du Colombier warn(Z, "variable not optimized: %s", s->name);
5867edc7532SDavid du Colombier goto none;
5877edc7532SDavid du Colombier }
5887edc7532SDavid du Colombier i = nvar;
5897edc7532SDavid du Colombier nvar++;
5907edc7532SDavid du Colombier v = &var[i];
5917edc7532SDavid du Colombier v->sym = s;
5927edc7532SDavid du Colombier v->offset = o;
5937edc7532SDavid du Colombier v->etype = et;
5947edc7532SDavid du Colombier v->name = n;
5957edc7532SDavid du Colombier if(debug['R'])
5967edc7532SDavid du Colombier print("bit=%2d et=%2d %D\n", i, et, a);
5977edc7532SDavid du Colombier out:
5987edc7532SDavid du Colombier bit = blsh(i);
5997edc7532SDavid du Colombier if(n == D_EXTERN || n == D_STATIC)
6007edc7532SDavid du Colombier for(z=0; z<BITS; z++)
6017edc7532SDavid du Colombier externs.b[z] |= bit.b[z];
6027edc7532SDavid du Colombier if(n == D_PARAM)
6037edc7532SDavid du Colombier for(z=0; z<BITS; z++)
6047edc7532SDavid du Colombier params.b[z] |= bit.b[z];
605*f8bc6aafSDavid du Colombier if(v->etype != et || (!typechlpfd[et] && !typev[et])) /* funny punning */
6067edc7532SDavid du Colombier for(z=0; z<BITS; z++)
6077edc7532SDavid du Colombier addrs.b[z] |= bit.b[z];
6087edc7532SDavid du Colombier if(t == D_CONST) {
6097edc7532SDavid du Colombier if(s == S) {
6107edc7532SDavid du Colombier for(z=0; z<BITS; z++)
6117edc7532SDavid du Colombier consts.b[z] |= bit.b[z];
6127edc7532SDavid du Colombier return bit;
6137edc7532SDavid du Colombier }
6147edc7532SDavid du Colombier if(et != TARRAY)
6157edc7532SDavid du Colombier for(z=0; z<BITS; z++)
6167edc7532SDavid du Colombier addrs.b[z] |= bit.b[z];
6177edc7532SDavid du Colombier for(z=0; z<BITS; z++)
6187edc7532SDavid du Colombier params.b[z] |= bit.b[z];
6197edc7532SDavid du Colombier return bit;
6207edc7532SDavid du Colombier }
6217edc7532SDavid du Colombier if(t == D_OREG)
6227edc7532SDavid du Colombier return bit;
6237edc7532SDavid du Colombier
6247edc7532SDavid du Colombier none:
6257edc7532SDavid du Colombier return zbits;
6267edc7532SDavid du Colombier }
6277edc7532SDavid du Colombier
6287edc7532SDavid du Colombier void
prop(Reg * r,Bits ref,Bits cal)6297edc7532SDavid du Colombier prop(Reg *r, Bits ref, Bits cal)
6307edc7532SDavid du Colombier {
6317edc7532SDavid du Colombier Reg *r1, *r2;
6327edc7532SDavid du Colombier int z;
6337edc7532SDavid du Colombier
6347edc7532SDavid du Colombier for(r1 = r; r1 != R; r1 = r1->p1) {
6357edc7532SDavid du Colombier for(z=0; z<BITS; z++) {
6367edc7532SDavid du Colombier ref.b[z] |= r1->refahead.b[z];
6377edc7532SDavid du Colombier if(ref.b[z] != r1->refahead.b[z]) {
6387edc7532SDavid du Colombier r1->refahead.b[z] = ref.b[z];
6397edc7532SDavid du Colombier change++;
6407edc7532SDavid du Colombier }
6417edc7532SDavid du Colombier cal.b[z] |= r1->calahead.b[z];
6427edc7532SDavid du Colombier if(cal.b[z] != r1->calahead.b[z]) {
6437edc7532SDavid du Colombier r1->calahead.b[z] = cal.b[z];
6447edc7532SDavid du Colombier change++;
6457edc7532SDavid du Colombier }
6467edc7532SDavid du Colombier }
6477edc7532SDavid du Colombier switch(r1->prog->as) {
6487edc7532SDavid du Colombier case AJAL:
6497edc7532SDavid du Colombier for(z=0; z<BITS; z++) {
6507edc7532SDavid du Colombier cal.b[z] |= ref.b[z] | externs.b[z];
6517edc7532SDavid du Colombier ref.b[z] = 0;
6527edc7532SDavid du Colombier }
6537edc7532SDavid du Colombier break;
6547edc7532SDavid du Colombier
6557edc7532SDavid du Colombier case ATEXT:
6567edc7532SDavid du Colombier for(z=0; z<BITS; z++) {
6577edc7532SDavid du Colombier cal.b[z] = 0;
6587edc7532SDavid du Colombier ref.b[z] = 0;
6597edc7532SDavid du Colombier }
6607edc7532SDavid du Colombier break;
6617edc7532SDavid du Colombier
6627edc7532SDavid du Colombier case ARET:
6637edc7532SDavid du Colombier for(z=0; z<BITS; z++) {
6647edc7532SDavid du Colombier cal.b[z] = externs.b[z];
6657edc7532SDavid du Colombier ref.b[z] = 0;
6667edc7532SDavid du Colombier }
6677edc7532SDavid du Colombier }
6687edc7532SDavid du Colombier for(z=0; z<BITS; z++) {
6697edc7532SDavid du Colombier ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
6707edc7532SDavid du Colombier r1->use1.b[z] | r1->use2.b[z];
6717edc7532SDavid du Colombier cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
6727edc7532SDavid du Colombier r1->refbehind.b[z] = ref.b[z];
6737edc7532SDavid du Colombier r1->calbehind.b[z] = cal.b[z];
6747edc7532SDavid du Colombier }
6757edc7532SDavid du Colombier if(r1->active)
6767edc7532SDavid du Colombier break;
6777edc7532SDavid du Colombier r1->active = 1;
6787edc7532SDavid du Colombier }
6797edc7532SDavid du Colombier for(; r != r1; r = r->p1)
6807edc7532SDavid du Colombier for(r2 = r->p2; r2 != R; r2 = r2->p2link)
6817edc7532SDavid du Colombier prop(r2, r->refbehind, r->calbehind);
6827edc7532SDavid du Colombier }
6837edc7532SDavid du Colombier
6847edc7532SDavid du Colombier /*
6857edc7532SDavid du Colombier * find looping structure
6867edc7532SDavid du Colombier *
6877edc7532SDavid du Colombier * 1) find reverse postordering
6887edc7532SDavid du Colombier * 2) find approximate dominators,
6897edc7532SDavid du Colombier * the actual dominators if the flow graph is reducible
6907edc7532SDavid du Colombier * otherwise, dominators plus some other non-dominators.
6917edc7532SDavid du Colombier * See Matthew S. Hecht and Jeffrey D. Ullman,
6927edc7532SDavid du Colombier * "Analysis of a Simple Algorithm for Global Data Flow Problems",
6937edc7532SDavid du Colombier * Conf. Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
6947edc7532SDavid du Colombier * Oct. 1-3, 1973, pp. 207-217.
6957edc7532SDavid du Colombier * 3) find all nodes with a predecessor dominated by the current node.
6967edc7532SDavid du Colombier * such a node is a loop head.
6977edc7532SDavid du Colombier * recursively, all preds with a greater rpo number are in the loop
6987edc7532SDavid du Colombier */
6997edc7532SDavid du Colombier long
postorder(Reg * r,Reg ** rpo2r,long n)7007edc7532SDavid du Colombier postorder(Reg *r, Reg **rpo2r, long n)
7017edc7532SDavid du Colombier {
7027edc7532SDavid du Colombier Reg *r1;
7037edc7532SDavid du Colombier
7047edc7532SDavid du Colombier r->rpo = 1;
7057edc7532SDavid du Colombier r1 = r->s1;
7067edc7532SDavid du Colombier if(r1 && !r1->rpo)
7077edc7532SDavid du Colombier n = postorder(r1, rpo2r, n);
7087edc7532SDavid du Colombier r1 = r->s2;
7097edc7532SDavid du Colombier if(r1 && !r1->rpo)
7107edc7532SDavid du Colombier n = postorder(r1, rpo2r, n);
7117edc7532SDavid du Colombier rpo2r[n] = r;
7127edc7532SDavid du Colombier n++;
7137edc7532SDavid du Colombier return n;
7147edc7532SDavid du Colombier }
7157edc7532SDavid du Colombier
7167edc7532SDavid du Colombier long
rpolca(long * idom,long rpo1,long rpo2)7177edc7532SDavid du Colombier rpolca(long *idom, long rpo1, long rpo2)
7187edc7532SDavid du Colombier {
7197edc7532SDavid du Colombier long t;
7207edc7532SDavid du Colombier
7217edc7532SDavid du Colombier if(rpo1 == -1)
7227edc7532SDavid du Colombier return rpo2;
7237edc7532SDavid du Colombier while(rpo1 != rpo2){
7247edc7532SDavid du Colombier if(rpo1 > rpo2){
7257edc7532SDavid du Colombier t = rpo2;
7267edc7532SDavid du Colombier rpo2 = rpo1;
7277edc7532SDavid du Colombier rpo1 = t;
7287edc7532SDavid du Colombier }
7297edc7532SDavid du Colombier while(rpo1 < rpo2){
7307edc7532SDavid du Colombier t = idom[rpo2];
7317edc7532SDavid du Colombier if(t >= rpo2)
732*f8bc6aafSDavid du Colombier fatal(Z, "bad idom");
7337edc7532SDavid du Colombier rpo2 = t;
7347edc7532SDavid du Colombier }
7357edc7532SDavid du Colombier }
7367edc7532SDavid du Colombier return rpo1;
7377edc7532SDavid du Colombier }
7387edc7532SDavid du Colombier
7397edc7532SDavid du Colombier int
doms(long * idom,long r,long s)7407edc7532SDavid du Colombier doms(long *idom, long r, long s)
7417edc7532SDavid du Colombier {
7427edc7532SDavid du Colombier while(s > r)
7437edc7532SDavid du Colombier s = idom[s];
7447edc7532SDavid du Colombier return s == r;
7457edc7532SDavid du Colombier }
7467edc7532SDavid du Colombier
7477edc7532SDavid du Colombier int
loophead(long * idom,Reg * r)7487edc7532SDavid du Colombier loophead(long *idom, Reg *r)
7497edc7532SDavid du Colombier {
7507edc7532SDavid du Colombier long src;
7517edc7532SDavid du Colombier
7527edc7532SDavid du Colombier src = r->rpo;
7537edc7532SDavid du Colombier if(r->p1 != R && doms(idom, src, r->p1->rpo))
7547edc7532SDavid du Colombier return 1;
7557edc7532SDavid du Colombier for(r = r->p2; r != R; r = r->p2link)
7567edc7532SDavid du Colombier if(doms(idom, src, r->rpo))
7577edc7532SDavid du Colombier return 1;
7587edc7532SDavid du Colombier return 0;
7597edc7532SDavid du Colombier }
7607edc7532SDavid du Colombier
7617edc7532SDavid du Colombier void
loopmark(Reg ** rpo2r,long head,Reg * r)7627edc7532SDavid du Colombier loopmark(Reg **rpo2r, long head, Reg *r)
7637edc7532SDavid du Colombier {
7647edc7532SDavid du Colombier if(r->rpo < head || r->active == head)
7657edc7532SDavid du Colombier return;
7667edc7532SDavid du Colombier r->active = head;
7677edc7532SDavid du Colombier r->loop += LOOP;
7687edc7532SDavid du Colombier if(r->p1 != R)
7697edc7532SDavid du Colombier loopmark(rpo2r, head, r->p1);
7707edc7532SDavid du Colombier for(r = r->p2; r != R; r = r->p2link)
7717edc7532SDavid du Colombier loopmark(rpo2r, head, r);
7727edc7532SDavid du Colombier }
7737edc7532SDavid du Colombier
7747edc7532SDavid du Colombier void
loopit(Reg * r,long nr)7757edc7532SDavid du Colombier loopit(Reg *r, long nr)
7767edc7532SDavid du Colombier {
7777edc7532SDavid du Colombier Reg *r1;
7787edc7532SDavid du Colombier long i, d, me;
7797edc7532SDavid du Colombier
7807edc7532SDavid du Colombier if(nr > maxnr) {
7817edc7532SDavid du Colombier rpo2r = alloc(nr * sizeof(Reg*));
7827edc7532SDavid du Colombier idom = alloc(nr * sizeof(long));
7837edc7532SDavid du Colombier maxnr = nr;
7847edc7532SDavid du Colombier }
7857edc7532SDavid du Colombier
7867edc7532SDavid du Colombier d = postorder(r, rpo2r, 0);
7877edc7532SDavid du Colombier if(d > nr)
788*f8bc6aafSDavid du Colombier fatal(Z, "too many reg nodes");
7897edc7532SDavid du Colombier nr = d;
7907edc7532SDavid du Colombier for(i = 0; i < nr / 2; i++){
7917edc7532SDavid du Colombier r1 = rpo2r[i];
7927edc7532SDavid du Colombier rpo2r[i] = rpo2r[nr - 1 - i];
7937edc7532SDavid du Colombier rpo2r[nr - 1 - i] = r1;
7947edc7532SDavid du Colombier }
7957edc7532SDavid du Colombier for(i = 0; i < nr; i++)
7967edc7532SDavid du Colombier rpo2r[i]->rpo = i;
7977edc7532SDavid du Colombier
7987edc7532SDavid du Colombier idom[0] = 0;
7997edc7532SDavid du Colombier for(i = 0; i < nr; i++){
8007edc7532SDavid du Colombier r1 = rpo2r[i];
8017edc7532SDavid du Colombier me = r1->rpo;
8027edc7532SDavid du Colombier d = -1;
8037edc7532SDavid du Colombier if(r1->p1 != R && r1->p1->rpo < me)
8047edc7532SDavid du Colombier d = r1->p1->rpo;
8057edc7532SDavid du Colombier for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
8067edc7532SDavid du Colombier if(r1->rpo < me)
8077edc7532SDavid du Colombier d = rpolca(idom, d, r1->rpo);
8087edc7532SDavid du Colombier idom[i] = d;
8097edc7532SDavid du Colombier }
8107edc7532SDavid du Colombier
8117edc7532SDavid du Colombier for(i = 0; i < nr; i++){
8127edc7532SDavid du Colombier r1 = rpo2r[i];
8137edc7532SDavid du Colombier r1->loop++;
8147edc7532SDavid du Colombier if(r1->p2 != R && loophead(idom, r1))
8157edc7532SDavid du Colombier loopmark(rpo2r, i, r1);
8167edc7532SDavid du Colombier }
8177edc7532SDavid du Colombier }
8187edc7532SDavid du Colombier
8197edc7532SDavid du Colombier void
synch(Reg * r,Bits dif)8207edc7532SDavid du Colombier synch(Reg *r, Bits dif)
8217edc7532SDavid du Colombier {
8227edc7532SDavid du Colombier Reg *r1;
8237edc7532SDavid du Colombier int z;
8247edc7532SDavid du Colombier
8257edc7532SDavid du Colombier for(r1 = r; r1 != R; r1 = r1->s1) {
8267edc7532SDavid du Colombier for(z=0; z<BITS; z++) {
8277edc7532SDavid du Colombier dif.b[z] = (dif.b[z] &
8287edc7532SDavid du Colombier ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
8297edc7532SDavid du Colombier r1->set.b[z] | r1->regdiff.b[z];
8307edc7532SDavid du Colombier if(dif.b[z] != r1->regdiff.b[z]) {
8317edc7532SDavid du Colombier r1->regdiff.b[z] = dif.b[z];
8327edc7532SDavid du Colombier change++;
8337edc7532SDavid du Colombier }
8347edc7532SDavid du Colombier }
8357edc7532SDavid du Colombier if(r1->active)
8367edc7532SDavid du Colombier break;
8377edc7532SDavid du Colombier r1->active = 1;
8387edc7532SDavid du Colombier for(z=0; z<BITS; z++)
8397edc7532SDavid du Colombier dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
8407edc7532SDavid du Colombier if(r1->s2 != R)
8417edc7532SDavid du Colombier synch(r1->s2, dif);
8427edc7532SDavid du Colombier }
8437edc7532SDavid du Colombier }
8447edc7532SDavid du Colombier
8457edc7532SDavid du Colombier ulong
allreg(ulong b,Rgn * r)8467edc7532SDavid du Colombier allreg(ulong b, Rgn *r)
8477edc7532SDavid du Colombier {
8487edc7532SDavid du Colombier Var *v;
8497edc7532SDavid du Colombier int i;
8507edc7532SDavid du Colombier
8517edc7532SDavid du Colombier v = var + r->varno;
8527edc7532SDavid du Colombier r->regno = 0;
8537edc7532SDavid du Colombier switch(v->etype) {
8547edc7532SDavid du Colombier
8557edc7532SDavid du Colombier default:
8567edc7532SDavid du Colombier diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
8577edc7532SDavid du Colombier break;
8587edc7532SDavid du Colombier
8597edc7532SDavid du Colombier case TCHAR:
8607edc7532SDavid du Colombier case TUCHAR:
8617edc7532SDavid du Colombier case TSHORT:
8627edc7532SDavid du Colombier case TUSHORT:
8637edc7532SDavid du Colombier case TINT:
8647edc7532SDavid du Colombier case TUINT:
8657edc7532SDavid du Colombier case TLONG:
8667edc7532SDavid du Colombier case TULONG:
8677edc7532SDavid du Colombier case TVLONG:
8687edc7532SDavid du Colombier case TUVLONG:
8697edc7532SDavid du Colombier case TIND:
8707edc7532SDavid du Colombier case TARRAY:
8717edc7532SDavid du Colombier i = BtoR(~b);
8727edc7532SDavid du Colombier if(i && r->cost >= 0) {
8737edc7532SDavid du Colombier r->regno = i;
8747edc7532SDavid du Colombier return RtoB(i);
8757edc7532SDavid du Colombier }
8767edc7532SDavid du Colombier break;
8777edc7532SDavid du Colombier
8787edc7532SDavid du Colombier case TDOUBLE:
8797edc7532SDavid du Colombier case TFLOAT:
8807edc7532SDavid du Colombier i = BtoF(~b);
8817edc7532SDavid du Colombier if(i && r->cost >= 0) {
8827edc7532SDavid du Colombier r->regno = i+NREG;
8837edc7532SDavid du Colombier return FtoB(i);
8847edc7532SDavid du Colombier }
8857edc7532SDavid du Colombier break;
8867edc7532SDavid du Colombier }
8877edc7532SDavid du Colombier return 0;
8887edc7532SDavid du Colombier }
8897edc7532SDavid du Colombier
8907edc7532SDavid du Colombier void
paint1(Reg * r,int bn)8917edc7532SDavid du Colombier paint1(Reg *r, int bn)
8927edc7532SDavid du Colombier {
8937edc7532SDavid du Colombier Reg *r1;
8947edc7532SDavid du Colombier Prog *p;
8957edc7532SDavid du Colombier int z;
8967edc7532SDavid du Colombier ulong bb;
8977edc7532SDavid du Colombier
8987edc7532SDavid du Colombier z = bn/32;
8997edc7532SDavid du Colombier bb = 1L<<(bn%32);
9007edc7532SDavid du Colombier if(r->act.b[z] & bb)
9017edc7532SDavid du Colombier return;
9027edc7532SDavid du Colombier for(;;) {
9037edc7532SDavid du Colombier if(!(r->refbehind.b[z] & bb))
9047edc7532SDavid du Colombier break;
9057edc7532SDavid du Colombier r1 = r->p1;
9067edc7532SDavid du Colombier if(r1 == R)
9077edc7532SDavid du Colombier break;
9087edc7532SDavid du Colombier if(!(r1->refahead.b[z] & bb))
9097edc7532SDavid du Colombier break;
9107edc7532SDavid du Colombier if(r1->act.b[z] & bb)
9117edc7532SDavid du Colombier break;
9127edc7532SDavid du Colombier r = r1;
9137edc7532SDavid du Colombier }
9147edc7532SDavid du Colombier
9157edc7532SDavid du Colombier if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb) {
9167edc7532SDavid du Colombier change -= CLOAD * r->loop;
9177edc7532SDavid du Colombier if(debug['R'] && debug['v'])
9187edc7532SDavid du Colombier print("%ld%P\tld %B $%d\n", r->loop,
9197edc7532SDavid du Colombier r->prog, blsh(bn), change);
9207edc7532SDavid du Colombier }
9217edc7532SDavid du Colombier for(;;) {
9227edc7532SDavid du Colombier r->act.b[z] |= bb;
9237edc7532SDavid du Colombier p = r->prog;
9247edc7532SDavid du Colombier
9257edc7532SDavid du Colombier if(r->use1.b[z] & bb) {
9267edc7532SDavid du Colombier change += CREF * r->loop;
9277edc7532SDavid du Colombier if(debug['R'] && debug['v'])
9287edc7532SDavid du Colombier print("%ld%P\tu1 %B $%d\n", r->loop,
9297edc7532SDavid du Colombier p, blsh(bn), change);
9307edc7532SDavid du Colombier }
9317edc7532SDavid du Colombier
9327edc7532SDavid du Colombier if((r->use2.b[z]|r->set.b[z]) & bb) {
9337edc7532SDavid du Colombier change += CREF * r->loop;
9347edc7532SDavid du Colombier if(debug['R'] && debug['v'])
9357edc7532SDavid du Colombier print("%ld%P\tu2 %B $%d\n", r->loop,
9367edc7532SDavid du Colombier p, blsh(bn), change);
9377edc7532SDavid du Colombier }
9387edc7532SDavid du Colombier
9397edc7532SDavid du Colombier if(STORE(r) & r->regdiff.b[z] & bb) {
9407edc7532SDavid du Colombier change -= CLOAD * r->loop;
9417edc7532SDavid du Colombier if(debug['R'] && debug['v'])
9427edc7532SDavid du Colombier print("%ld%P\tst %B $%d\n", r->loop,
9437edc7532SDavid du Colombier p, blsh(bn), change);
9447edc7532SDavid du Colombier }
9457edc7532SDavid du Colombier
9467edc7532SDavid du Colombier if(r->refbehind.b[z] & bb)
9477edc7532SDavid du Colombier for(r1 = r->p2; r1 != R; r1 = r1->p2link)
9487edc7532SDavid du Colombier if(r1->refahead.b[z] & bb)
9497edc7532SDavid du Colombier paint1(r1, bn);
9507edc7532SDavid du Colombier
9517edc7532SDavid du Colombier if(!(r->refahead.b[z] & bb))
9527edc7532SDavid du Colombier break;
9537edc7532SDavid du Colombier r1 = r->s2;
9547edc7532SDavid du Colombier if(r1 != R)
9557edc7532SDavid du Colombier if(r1->refbehind.b[z] & bb)
9567edc7532SDavid du Colombier paint1(r1, bn);
9577edc7532SDavid du Colombier r = r->s1;
9587edc7532SDavid du Colombier if(r == R)
9597edc7532SDavid du Colombier break;
9607edc7532SDavid du Colombier if(r->act.b[z] & bb)
9617edc7532SDavid du Colombier break;
9627edc7532SDavid du Colombier if(!(r->refbehind.b[z] & bb))
9637edc7532SDavid du Colombier break;
9647edc7532SDavid du Colombier }
9657edc7532SDavid du Colombier }
9667edc7532SDavid du Colombier
9677edc7532SDavid du Colombier ulong
paint2(Reg * r,int bn)9687edc7532SDavid du Colombier paint2(Reg *r, int bn)
9697edc7532SDavid du Colombier {
9707edc7532SDavid du Colombier Reg *r1;
9717edc7532SDavid du Colombier int z;
9727edc7532SDavid du Colombier ulong bb, vreg;
9737edc7532SDavid du Colombier
9747edc7532SDavid du Colombier z = bn/32;
9757edc7532SDavid du Colombier bb = 1L << (bn%32);
9767edc7532SDavid du Colombier vreg = regbits;
9777edc7532SDavid du Colombier if(!(r->act.b[z] & bb))
9787edc7532SDavid du Colombier return vreg;
9797edc7532SDavid du Colombier for(;;) {
9807edc7532SDavid du Colombier if(!(r->refbehind.b[z] & bb))
9817edc7532SDavid du Colombier break;
9827edc7532SDavid du Colombier r1 = r->p1;
9837edc7532SDavid du Colombier if(r1 == R)
9847edc7532SDavid du Colombier break;
9857edc7532SDavid du Colombier if(!(r1->refahead.b[z] & bb))
9867edc7532SDavid du Colombier break;
9877edc7532SDavid du Colombier if(!(r1->act.b[z] & bb))
9887edc7532SDavid du Colombier break;
9897edc7532SDavid du Colombier r = r1;
9907edc7532SDavid du Colombier }
9917edc7532SDavid du Colombier for(;;) {
9927edc7532SDavid du Colombier r->act.b[z] &= ~bb;
9937edc7532SDavid du Colombier
9947edc7532SDavid du Colombier vreg |= r->regu;
9957edc7532SDavid du Colombier
9967edc7532SDavid du Colombier if(r->refbehind.b[z] & bb)
9977edc7532SDavid du Colombier for(r1 = r->p2; r1 != R; r1 = r1->p2link)
9987edc7532SDavid du Colombier if(r1->refahead.b[z] & bb)
9997edc7532SDavid du Colombier vreg |= paint2(r1, bn);
10007edc7532SDavid du Colombier
10017edc7532SDavid du Colombier if(!(r->refahead.b[z] & bb))
10027edc7532SDavid du Colombier break;
10037edc7532SDavid du Colombier r1 = r->s2;
10047edc7532SDavid du Colombier if(r1 != R)
10057edc7532SDavid du Colombier if(r1->refbehind.b[z] & bb)
10067edc7532SDavid du Colombier vreg |= paint2(r1, bn);
10077edc7532SDavid du Colombier r = r->s1;
10087edc7532SDavid du Colombier if(r == R)
10097edc7532SDavid du Colombier break;
10107edc7532SDavid du Colombier if(!(r->act.b[z] & bb))
10117edc7532SDavid du Colombier break;
10127edc7532SDavid du Colombier if(!(r->refbehind.b[z] & bb))
10137edc7532SDavid du Colombier break;
10147edc7532SDavid du Colombier }
10157edc7532SDavid du Colombier return vreg;
10167edc7532SDavid du Colombier }
10177edc7532SDavid du Colombier
10187edc7532SDavid du Colombier void
paint3(Reg * r,int bn,long rb,int rn)10197edc7532SDavid du Colombier paint3(Reg *r, int bn, long rb, int rn)
10207edc7532SDavid du Colombier {
10217edc7532SDavid du Colombier Reg *r1;
10227edc7532SDavid du Colombier Prog *p;
10237edc7532SDavid du Colombier int z;
10247edc7532SDavid du Colombier ulong bb;
10257edc7532SDavid du Colombier
10267edc7532SDavid du Colombier z = bn/32;
10277edc7532SDavid du Colombier bb = 1L << (bn%32);
10287edc7532SDavid du Colombier if(r->act.b[z] & bb)
10297edc7532SDavid du Colombier return;
10307edc7532SDavid du Colombier for(;;) {
10317edc7532SDavid du Colombier if(!(r->refbehind.b[z] & bb))
10327edc7532SDavid du Colombier break;
10337edc7532SDavid du Colombier r1 = r->p1;
10347edc7532SDavid du Colombier if(r1 == R)
10357edc7532SDavid du Colombier break;
10367edc7532SDavid du Colombier if(!(r1->refahead.b[z] & bb))
10377edc7532SDavid du Colombier break;
10387edc7532SDavid du Colombier if(r1->act.b[z] & bb)
10397edc7532SDavid du Colombier break;
10407edc7532SDavid du Colombier r = r1;
10417edc7532SDavid du Colombier }
10427edc7532SDavid du Colombier
10437edc7532SDavid du Colombier if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
10447edc7532SDavid du Colombier addmove(r, bn, rn, 0);
10457edc7532SDavid du Colombier for(;;) {
10467edc7532SDavid du Colombier r->act.b[z] |= bb;
10477edc7532SDavid du Colombier p = r->prog;
10487edc7532SDavid du Colombier
10497edc7532SDavid du Colombier if(r->use1.b[z] & bb) {
10507edc7532SDavid du Colombier if(debug['R'])
10517edc7532SDavid du Colombier print("%P", p);
10527edc7532SDavid du Colombier addreg(&p->from, rn);
10537edc7532SDavid du Colombier if(debug['R'])
10547edc7532SDavid du Colombier print("\t.c%P\n", p);
10557edc7532SDavid du Colombier }
10567edc7532SDavid du Colombier if((r->use2.b[z]|r->set.b[z]) & bb) {
10577edc7532SDavid du Colombier if(debug['R'])
10587edc7532SDavid du Colombier print("%P", p);
10597edc7532SDavid du Colombier addreg(&p->to, rn);
10607edc7532SDavid du Colombier if(debug['R'])
10617edc7532SDavid du Colombier print("\t.c%P\n", p);
10627edc7532SDavid du Colombier }
10637edc7532SDavid du Colombier
10647edc7532SDavid du Colombier if(STORE(r) & r->regdiff.b[z] & bb)
10657edc7532SDavid du Colombier addmove(r, bn, rn, 1);
10667edc7532SDavid du Colombier r->regu |= rb;
10677edc7532SDavid du Colombier
10687edc7532SDavid du Colombier if(r->refbehind.b[z] & bb)
10697edc7532SDavid du Colombier for(r1 = r->p2; r1 != R; r1 = r1->p2link)
10707edc7532SDavid du Colombier if(r1->refahead.b[z] & bb)
10717edc7532SDavid du Colombier paint3(r1, bn, rb, rn);
10727edc7532SDavid du Colombier
10737edc7532SDavid du Colombier if(!(r->refahead.b[z] & bb))
10747edc7532SDavid du Colombier break;
10757edc7532SDavid du Colombier r1 = r->s2;
10767edc7532SDavid du Colombier if(r1 != R)
10777edc7532SDavid du Colombier if(r1->refbehind.b[z] & bb)
10787edc7532SDavid du Colombier paint3(r1, bn, rb, rn);
10797edc7532SDavid du Colombier r = r->s1;
10807edc7532SDavid du Colombier if(r == R)
10817edc7532SDavid du Colombier break;
10827edc7532SDavid du Colombier if(r->act.b[z] & bb)
10837edc7532SDavid du Colombier break;
10847edc7532SDavid du Colombier if(!(r->refbehind.b[z] & bb))
10857edc7532SDavid du Colombier break;
10867edc7532SDavid du Colombier }
10877edc7532SDavid du Colombier }
10887edc7532SDavid du Colombier
10897edc7532SDavid du Colombier void
addreg(Adr * a,int rn)10907edc7532SDavid du Colombier addreg(Adr *a, int rn)
10917edc7532SDavid du Colombier {
10927edc7532SDavid du Colombier
10937edc7532SDavid du Colombier a->sym = 0;
10947edc7532SDavid du Colombier a->name = D_NONE;
10957edc7532SDavid du Colombier a->type = D_REG;
10967edc7532SDavid du Colombier a->reg = rn;
10977edc7532SDavid du Colombier if(rn >= NREG) {
10987edc7532SDavid du Colombier a->type = D_FREG;
10997edc7532SDavid du Colombier a->reg = rn-NREG;
11007edc7532SDavid du Colombier }
11017edc7532SDavid du Colombier }
11027edc7532SDavid du Colombier
11037edc7532SDavid du Colombier /*
11047edc7532SDavid du Colombier * bit reg
11057edc7532SDavid du Colombier * 0 R3
11067edc7532SDavid du Colombier * 1 R4
11077edc7532SDavid du Colombier * ... ...
11087edc7532SDavid du Colombier * 19 R22
11097edc7532SDavid du Colombier * 20 R23
11107edc7532SDavid du Colombier */
11117edc7532SDavid du Colombier long
RtoB(int r)11127edc7532SDavid du Colombier RtoB(int r)
11137edc7532SDavid du Colombier {
11147edc7532SDavid du Colombier
11157edc7532SDavid du Colombier if(r < 3 || r > 23)
11167edc7532SDavid du Colombier return 0;
11177edc7532SDavid du Colombier return 1L << (r-3);
11187edc7532SDavid du Colombier }
11197edc7532SDavid du Colombier
BtoR(long b)11207edc7532SDavid du Colombier BtoR(long b)
11217edc7532SDavid du Colombier {
11227edc7532SDavid du Colombier
11237edc7532SDavid du Colombier b &= 0x001fffffL;
11247edc7532SDavid du Colombier if(b == 0)
11257edc7532SDavid du Colombier return 0;
11267edc7532SDavid du Colombier return bitno(b) + 3;
11277edc7532SDavid du Colombier }
11287edc7532SDavid du Colombier
11297edc7532SDavid du Colombier /*
11307edc7532SDavid du Colombier * bit reg
11317edc7532SDavid du Colombier * 22 F4
11327edc7532SDavid du Colombier * 23 F6
11337edc7532SDavid du Colombier * ... ...
11347edc7532SDavid du Colombier * 31 F22
11357edc7532SDavid du Colombier */
11367edc7532SDavid du Colombier long
FtoB(int f)11377edc7532SDavid du Colombier FtoB(int f)
11387edc7532SDavid du Colombier {
11397edc7532SDavid du Colombier
11407edc7532SDavid du Colombier if(f < 4 || f > 22 || (f&1))
11417edc7532SDavid du Colombier return 0;
11427edc7532SDavid du Colombier return 1L << (f/2 + 20);
11437edc7532SDavid du Colombier }
11447edc7532SDavid du Colombier
11457edc7532SDavid du Colombier int
BtoF(long b)11467edc7532SDavid du Colombier BtoF(long b)
11477edc7532SDavid du Colombier {
11487edc7532SDavid du Colombier
11497edc7532SDavid du Colombier b &= 0xffc00000L;
11507edc7532SDavid du Colombier if(b == 0)
11517edc7532SDavid du Colombier return 0;
11527edc7532SDavid du Colombier return bitno(b)*2 - 40;
11537edc7532SDavid du Colombier }
1154