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