174a4d8c2SCharles.Forsyth #include "gc.h"
274a4d8c2SCharles.Forsyth
374a4d8c2SCharles.Forsyth Reg*
rega(void)474a4d8c2SCharles.Forsyth rega(void)
574a4d8c2SCharles.Forsyth {
674a4d8c2SCharles.Forsyth Reg *r;
774a4d8c2SCharles.Forsyth
874a4d8c2SCharles.Forsyth r = freer;
974a4d8c2SCharles.Forsyth if(r == R) {
1074a4d8c2SCharles.Forsyth r = alloc(sizeof(*r));
1174a4d8c2SCharles.Forsyth } else
1274a4d8c2SCharles.Forsyth freer = r->link;
1374a4d8c2SCharles.Forsyth
1474a4d8c2SCharles.Forsyth *r = zreg;
1574a4d8c2SCharles.Forsyth return r;
1674a4d8c2SCharles.Forsyth }
1774a4d8c2SCharles.Forsyth
1874a4d8c2SCharles.Forsyth int
rcmp(void * a1,void * a2)19*45a20ab7Sforsyth rcmp(void *a1, void *a2)
2074a4d8c2SCharles.Forsyth {
2174a4d8c2SCharles.Forsyth Rgn *p1, *p2;
2274a4d8c2SCharles.Forsyth int c1, c2;
2374a4d8c2SCharles.Forsyth
2474a4d8c2SCharles.Forsyth p1 = (Rgn*)a1;
2574a4d8c2SCharles.Forsyth p2 = (Rgn*)a2;
2674a4d8c2SCharles.Forsyth c1 = p2->cost;
2774a4d8c2SCharles.Forsyth c2 = p1->cost;
2874a4d8c2SCharles.Forsyth if(c1 -= c2)
2974a4d8c2SCharles.Forsyth return c1;
3074a4d8c2SCharles.Forsyth return p2->varno - p1->varno;
3174a4d8c2SCharles.Forsyth }
3274a4d8c2SCharles.Forsyth
3374a4d8c2SCharles.Forsyth void
regopt(Prog * p)3474a4d8c2SCharles.Forsyth regopt(Prog *p)
3574a4d8c2SCharles.Forsyth {
3674a4d8c2SCharles.Forsyth Reg *r, *r1, *r2;
3774a4d8c2SCharles.Forsyth Prog *p1;
3874a4d8c2SCharles.Forsyth int i, z;
3974a4d8c2SCharles.Forsyth long initpc, val, npc;
4074a4d8c2SCharles.Forsyth ulong vreg;
4174a4d8c2SCharles.Forsyth Bits bit;
4274a4d8c2SCharles.Forsyth struct
4374a4d8c2SCharles.Forsyth {
4474a4d8c2SCharles.Forsyth long m;
4574a4d8c2SCharles.Forsyth long c;
4674a4d8c2SCharles.Forsyth Reg* p;
4774a4d8c2SCharles.Forsyth } log5[6], *lp;
4874a4d8c2SCharles.Forsyth
4974a4d8c2SCharles.Forsyth firstr = R;
5074a4d8c2SCharles.Forsyth lastr = R;
5174a4d8c2SCharles.Forsyth nvar = 0;
5274a4d8c2SCharles.Forsyth regbits = RtoB(D_SP) | RtoB(D_AX);
5374a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
5474a4d8c2SCharles.Forsyth externs.b[z] = 0;
5574a4d8c2SCharles.Forsyth params.b[z] = 0;
5674a4d8c2SCharles.Forsyth consts.b[z] = 0;
5774a4d8c2SCharles.Forsyth addrs.b[z] = 0;
5874a4d8c2SCharles.Forsyth }
5974a4d8c2SCharles.Forsyth
6074a4d8c2SCharles.Forsyth /*
6174a4d8c2SCharles.Forsyth * pass 1
6274a4d8c2SCharles.Forsyth * build aux data structure
6374a4d8c2SCharles.Forsyth * allocate pcs
6474a4d8c2SCharles.Forsyth * find use and set of variables
6574a4d8c2SCharles.Forsyth */
6674a4d8c2SCharles.Forsyth val = 5L * 5L * 5L * 5L * 5L;
6774a4d8c2SCharles.Forsyth lp = log5;
6874a4d8c2SCharles.Forsyth for(i=0; i<5; i++) {
6974a4d8c2SCharles.Forsyth lp->m = val;
7074a4d8c2SCharles.Forsyth lp->c = 0;
7174a4d8c2SCharles.Forsyth lp->p = R;
7274a4d8c2SCharles.Forsyth val /= 5L;
7374a4d8c2SCharles.Forsyth lp++;
7474a4d8c2SCharles.Forsyth }
7574a4d8c2SCharles.Forsyth val = 0;
7674a4d8c2SCharles.Forsyth for(; p != P; p = p->link) {
7774a4d8c2SCharles.Forsyth switch(p->as) {
7874a4d8c2SCharles.Forsyth case ADATA:
7974a4d8c2SCharles.Forsyth case AGLOBL:
8074a4d8c2SCharles.Forsyth case ANAME:
8174a4d8c2SCharles.Forsyth case ASIGNAME:
8274a4d8c2SCharles.Forsyth continue;
8374a4d8c2SCharles.Forsyth }
8474a4d8c2SCharles.Forsyth r = rega();
8574a4d8c2SCharles.Forsyth if(firstr == R) {
8674a4d8c2SCharles.Forsyth firstr = r;
8774a4d8c2SCharles.Forsyth lastr = r;
8874a4d8c2SCharles.Forsyth } else {
8974a4d8c2SCharles.Forsyth lastr->link = r;
9074a4d8c2SCharles.Forsyth r->p1 = lastr;
9174a4d8c2SCharles.Forsyth lastr->s1 = r;
9274a4d8c2SCharles.Forsyth lastr = r;
9374a4d8c2SCharles.Forsyth }
9474a4d8c2SCharles.Forsyth r->prog = p;
9574a4d8c2SCharles.Forsyth r->pc = val;
9674a4d8c2SCharles.Forsyth val++;
9774a4d8c2SCharles.Forsyth
9874a4d8c2SCharles.Forsyth lp = log5;
9974a4d8c2SCharles.Forsyth for(i=0; i<5; i++) {
10074a4d8c2SCharles.Forsyth lp->c--;
10174a4d8c2SCharles.Forsyth if(lp->c <= 0) {
10274a4d8c2SCharles.Forsyth lp->c = lp->m;
10374a4d8c2SCharles.Forsyth if(lp->p != R)
10474a4d8c2SCharles.Forsyth lp->p->log5 = r;
10574a4d8c2SCharles.Forsyth lp->p = r;
10674a4d8c2SCharles.Forsyth (lp+1)->c = 0;
10774a4d8c2SCharles.Forsyth break;
10874a4d8c2SCharles.Forsyth }
10974a4d8c2SCharles.Forsyth lp++;
11074a4d8c2SCharles.Forsyth }
11174a4d8c2SCharles.Forsyth
11274a4d8c2SCharles.Forsyth r1 = r->p1;
11374a4d8c2SCharles.Forsyth if(r1 != R)
11474a4d8c2SCharles.Forsyth switch(r1->prog->as) {
11574a4d8c2SCharles.Forsyth case ARET:
11674a4d8c2SCharles.Forsyth case AJMP:
11774a4d8c2SCharles.Forsyth case AIRETL:
11874a4d8c2SCharles.Forsyth r->p1 = R;
11974a4d8c2SCharles.Forsyth r1->s1 = R;
12074a4d8c2SCharles.Forsyth }
12174a4d8c2SCharles.Forsyth
122*45a20ab7Sforsyth bit = mkvar(r, &p->from, p->as==AMOVL);
12374a4d8c2SCharles.Forsyth if(bany(&bit))
12474a4d8c2SCharles.Forsyth switch(p->as) {
12574a4d8c2SCharles.Forsyth /*
12674a4d8c2SCharles.Forsyth * funny
12774a4d8c2SCharles.Forsyth */
12874a4d8c2SCharles.Forsyth case ALEAL:
12974a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
13074a4d8c2SCharles.Forsyth addrs.b[z] |= bit.b[z];
13174a4d8c2SCharles.Forsyth break;
13274a4d8c2SCharles.Forsyth
13374a4d8c2SCharles.Forsyth /*
13474a4d8c2SCharles.Forsyth * left side read
13574a4d8c2SCharles.Forsyth */
13674a4d8c2SCharles.Forsyth default:
13774a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
13874a4d8c2SCharles.Forsyth r->use1.b[z] |= bit.b[z];
13974a4d8c2SCharles.Forsyth break;
14074a4d8c2SCharles.Forsyth }
14174a4d8c2SCharles.Forsyth
142*45a20ab7Sforsyth bit = mkvar(r, &p->to, 0);
14374a4d8c2SCharles.Forsyth if(bany(&bit))
14474a4d8c2SCharles.Forsyth switch(p->as) {
14574a4d8c2SCharles.Forsyth default:
14674a4d8c2SCharles.Forsyth diag(Z, "reg: unknown op: %A", p->as);
14774a4d8c2SCharles.Forsyth break;
14874a4d8c2SCharles.Forsyth
14974a4d8c2SCharles.Forsyth /*
15074a4d8c2SCharles.Forsyth * right side read
15174a4d8c2SCharles.Forsyth */
15274a4d8c2SCharles.Forsyth case ACMPB:
15374a4d8c2SCharles.Forsyth case ACMPL:
15474a4d8c2SCharles.Forsyth case ACMPW:
15574a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
15674a4d8c2SCharles.Forsyth r->use2.b[z] |= bit.b[z];
15774a4d8c2SCharles.Forsyth break;
15874a4d8c2SCharles.Forsyth
15974a4d8c2SCharles.Forsyth /*
16074a4d8c2SCharles.Forsyth * right side write
16174a4d8c2SCharles.Forsyth */
16274a4d8c2SCharles.Forsyth case ANOP:
16374a4d8c2SCharles.Forsyth case AMOVL:
16474a4d8c2SCharles.Forsyth case AMOVB:
16574a4d8c2SCharles.Forsyth case AMOVW:
16674a4d8c2SCharles.Forsyth case AMOVBLSX:
16774a4d8c2SCharles.Forsyth case AMOVBLZX:
16874a4d8c2SCharles.Forsyth case AMOVWLSX:
16974a4d8c2SCharles.Forsyth case AMOVWLZX:
17074a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
17174a4d8c2SCharles.Forsyth r->set.b[z] |= bit.b[z];
17274a4d8c2SCharles.Forsyth break;
17374a4d8c2SCharles.Forsyth
17474a4d8c2SCharles.Forsyth /*
17574a4d8c2SCharles.Forsyth * right side read+write
17674a4d8c2SCharles.Forsyth */
17774a4d8c2SCharles.Forsyth case AADDB:
17874a4d8c2SCharles.Forsyth case AADDL:
17974a4d8c2SCharles.Forsyth case AADDW:
18074a4d8c2SCharles.Forsyth case AANDB:
18174a4d8c2SCharles.Forsyth case AANDL:
18274a4d8c2SCharles.Forsyth case AANDW:
18374a4d8c2SCharles.Forsyth case ASUBB:
18474a4d8c2SCharles.Forsyth case ASUBL:
18574a4d8c2SCharles.Forsyth case ASUBW:
18674a4d8c2SCharles.Forsyth case AORB:
18774a4d8c2SCharles.Forsyth case AORL:
18874a4d8c2SCharles.Forsyth case AORW:
18974a4d8c2SCharles.Forsyth case AXORB:
19074a4d8c2SCharles.Forsyth case AXORL:
19174a4d8c2SCharles.Forsyth case AXORW:
19274a4d8c2SCharles.Forsyth case ASALB:
19374a4d8c2SCharles.Forsyth case ASALL:
19474a4d8c2SCharles.Forsyth case ASALW:
19574a4d8c2SCharles.Forsyth case ASARB:
19674a4d8c2SCharles.Forsyth case ASARL:
19774a4d8c2SCharles.Forsyth case ASARW:
19874a4d8c2SCharles.Forsyth case AROLB:
19974a4d8c2SCharles.Forsyth case AROLL:
20074a4d8c2SCharles.Forsyth case AROLW:
20174a4d8c2SCharles.Forsyth case ARORB:
20274a4d8c2SCharles.Forsyth case ARORL:
20374a4d8c2SCharles.Forsyth case ARORW:
20474a4d8c2SCharles.Forsyth case ASHLB:
20574a4d8c2SCharles.Forsyth case ASHLL:
20674a4d8c2SCharles.Forsyth case ASHLW:
20774a4d8c2SCharles.Forsyth case ASHRB:
20874a4d8c2SCharles.Forsyth case ASHRL:
20974a4d8c2SCharles.Forsyth case ASHRW:
21074a4d8c2SCharles.Forsyth case AIMULL:
21174a4d8c2SCharles.Forsyth case AIMULW:
21274a4d8c2SCharles.Forsyth case ANEGL:
21374a4d8c2SCharles.Forsyth case ANOTL:
21474a4d8c2SCharles.Forsyth case AADCL:
21574a4d8c2SCharles.Forsyth case ASBBL:
21674a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
21774a4d8c2SCharles.Forsyth r->set.b[z] |= bit.b[z];
21874a4d8c2SCharles.Forsyth r->use2.b[z] |= bit.b[z];
21974a4d8c2SCharles.Forsyth }
22074a4d8c2SCharles.Forsyth break;
22174a4d8c2SCharles.Forsyth
22274a4d8c2SCharles.Forsyth /*
22374a4d8c2SCharles.Forsyth * funny
22474a4d8c2SCharles.Forsyth */
22574a4d8c2SCharles.Forsyth case AFMOVDP:
22674a4d8c2SCharles.Forsyth case AFMOVFP:
2274d1cf526Sforsyth case AFMOVLP:
22874a4d8c2SCharles.Forsyth case AFMOVVP:
2294d1cf526Sforsyth case AFMOVWP:
23074a4d8c2SCharles.Forsyth case ACALL:
23174a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
23274a4d8c2SCharles.Forsyth addrs.b[z] |= bit.b[z];
23374a4d8c2SCharles.Forsyth break;
23474a4d8c2SCharles.Forsyth }
23574a4d8c2SCharles.Forsyth
23674a4d8c2SCharles.Forsyth switch(p->as) {
23774a4d8c2SCharles.Forsyth case AIMULL:
23874a4d8c2SCharles.Forsyth case AIMULW:
23974a4d8c2SCharles.Forsyth if(p->to.type != D_NONE)
24074a4d8c2SCharles.Forsyth break;
24174a4d8c2SCharles.Forsyth
24274a4d8c2SCharles.Forsyth case AIDIVB:
24374a4d8c2SCharles.Forsyth case AIDIVL:
24474a4d8c2SCharles.Forsyth case AIDIVW:
24574a4d8c2SCharles.Forsyth case AIMULB:
24674a4d8c2SCharles.Forsyth case ADIVB:
24774a4d8c2SCharles.Forsyth case ADIVL:
24874a4d8c2SCharles.Forsyth case ADIVW:
24974a4d8c2SCharles.Forsyth case AMULB:
25074a4d8c2SCharles.Forsyth case AMULL:
25174a4d8c2SCharles.Forsyth case AMULW:
25274a4d8c2SCharles.Forsyth
25374a4d8c2SCharles.Forsyth case ACWD:
25474a4d8c2SCharles.Forsyth case ACDQ:
25574a4d8c2SCharles.Forsyth r->regu |= RtoB(D_AX) | RtoB(D_DX);
25674a4d8c2SCharles.Forsyth break;
25774a4d8c2SCharles.Forsyth
25874a4d8c2SCharles.Forsyth case AREP:
25974a4d8c2SCharles.Forsyth case AREPN:
26074a4d8c2SCharles.Forsyth case ALOOP:
26174a4d8c2SCharles.Forsyth case ALOOPEQ:
26274a4d8c2SCharles.Forsyth case ALOOPNE:
26374a4d8c2SCharles.Forsyth r->regu |= RtoB(D_CX);
26474a4d8c2SCharles.Forsyth break;
26574a4d8c2SCharles.Forsyth
26674a4d8c2SCharles.Forsyth case AMOVSB:
26774a4d8c2SCharles.Forsyth case AMOVSL:
26874a4d8c2SCharles.Forsyth case AMOVSW:
26974a4d8c2SCharles.Forsyth case ACMPSB:
27074a4d8c2SCharles.Forsyth case ACMPSL:
27174a4d8c2SCharles.Forsyth case ACMPSW:
27274a4d8c2SCharles.Forsyth r->regu |= RtoB(D_SI) | RtoB(D_DI);
27374a4d8c2SCharles.Forsyth break;
27474a4d8c2SCharles.Forsyth
27574a4d8c2SCharles.Forsyth case ASTOSB:
27674a4d8c2SCharles.Forsyth case ASTOSL:
27774a4d8c2SCharles.Forsyth case ASTOSW:
27874a4d8c2SCharles.Forsyth case ASCASB:
27974a4d8c2SCharles.Forsyth case ASCASL:
28074a4d8c2SCharles.Forsyth case ASCASW:
28174a4d8c2SCharles.Forsyth r->regu |= RtoB(D_AX) | RtoB(D_DI);
28274a4d8c2SCharles.Forsyth break;
28374a4d8c2SCharles.Forsyth
28474a4d8c2SCharles.Forsyth case AINSB:
28574a4d8c2SCharles.Forsyth case AINSL:
28674a4d8c2SCharles.Forsyth case AINSW:
28774a4d8c2SCharles.Forsyth case AOUTSB:
28874a4d8c2SCharles.Forsyth case AOUTSL:
28974a4d8c2SCharles.Forsyth case AOUTSW:
29074a4d8c2SCharles.Forsyth r->regu |= RtoB(D_DI) | RtoB(D_DX);
29174a4d8c2SCharles.Forsyth break;
29274a4d8c2SCharles.Forsyth
29374a4d8c2SCharles.Forsyth case AFSTSW:
29474a4d8c2SCharles.Forsyth case ASAHF:
29574a4d8c2SCharles.Forsyth r->regu |= RtoB(D_AX);
29674a4d8c2SCharles.Forsyth break;
29774a4d8c2SCharles.Forsyth }
29874a4d8c2SCharles.Forsyth }
29974a4d8c2SCharles.Forsyth if(firstr == R)
30074a4d8c2SCharles.Forsyth return;
30174a4d8c2SCharles.Forsyth initpc = pc - val;
30274a4d8c2SCharles.Forsyth npc = val;
30374a4d8c2SCharles.Forsyth
30474a4d8c2SCharles.Forsyth /*
30574a4d8c2SCharles.Forsyth * pass 2
30674a4d8c2SCharles.Forsyth * turn branch references to pointers
30774a4d8c2SCharles.Forsyth * build back pointers
30874a4d8c2SCharles.Forsyth */
30974a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link) {
31074a4d8c2SCharles.Forsyth p = r->prog;
31174a4d8c2SCharles.Forsyth if(p->to.type == D_BRANCH) {
31274a4d8c2SCharles.Forsyth val = p->to.offset - initpc;
31374a4d8c2SCharles.Forsyth r1 = firstr;
31474a4d8c2SCharles.Forsyth while(r1 != R) {
31574a4d8c2SCharles.Forsyth r2 = r1->log5;
31674a4d8c2SCharles.Forsyth if(r2 != R && val >= r2->pc) {
31774a4d8c2SCharles.Forsyth r1 = r2;
31874a4d8c2SCharles.Forsyth continue;
31974a4d8c2SCharles.Forsyth }
32074a4d8c2SCharles.Forsyth if(r1->pc == val)
32174a4d8c2SCharles.Forsyth break;
32274a4d8c2SCharles.Forsyth r1 = r1->link;
32374a4d8c2SCharles.Forsyth }
32474a4d8c2SCharles.Forsyth if(r1 == R) {
32574a4d8c2SCharles.Forsyth nearln = p->lineno;
32674a4d8c2SCharles.Forsyth diag(Z, "ref not found\n%P", p);
32774a4d8c2SCharles.Forsyth continue;
32874a4d8c2SCharles.Forsyth }
32974a4d8c2SCharles.Forsyth if(r1 == r) {
33074a4d8c2SCharles.Forsyth nearln = p->lineno;
33174a4d8c2SCharles.Forsyth diag(Z, "ref to self\n%P", p);
33274a4d8c2SCharles.Forsyth continue;
33374a4d8c2SCharles.Forsyth }
33474a4d8c2SCharles.Forsyth r->s2 = r1;
33574a4d8c2SCharles.Forsyth r->p2link = r1->p2;
33674a4d8c2SCharles.Forsyth r1->p2 = r;
33774a4d8c2SCharles.Forsyth }
33874a4d8c2SCharles.Forsyth }
33974a4d8c2SCharles.Forsyth if(debug['R']) {
34074a4d8c2SCharles.Forsyth p = firstr->prog;
34174a4d8c2SCharles.Forsyth print("\n%L %D\n", p->lineno, &p->from);
34274a4d8c2SCharles.Forsyth }
34374a4d8c2SCharles.Forsyth
34474a4d8c2SCharles.Forsyth /*
34574a4d8c2SCharles.Forsyth * pass 2.5
34674a4d8c2SCharles.Forsyth * find looping structure
34774a4d8c2SCharles.Forsyth */
34874a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link)
34974a4d8c2SCharles.Forsyth r->active = 0;
35074a4d8c2SCharles.Forsyth change = 0;
35174a4d8c2SCharles.Forsyth loopit(firstr, npc);
35274a4d8c2SCharles.Forsyth if(debug['R'] && debug['v']) {
35374a4d8c2SCharles.Forsyth print("\nlooping structure:\n");
35474a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link) {
35574a4d8c2SCharles.Forsyth print("%ld:%P", r->loop, r->prog);
35674a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
35774a4d8c2SCharles.Forsyth bit.b[z] = r->use1.b[z] |
35874a4d8c2SCharles.Forsyth r->use2.b[z] |
35974a4d8c2SCharles.Forsyth r->set.b[z];
36074a4d8c2SCharles.Forsyth if(bany(&bit)) {
36174a4d8c2SCharles.Forsyth print("\t");
36274a4d8c2SCharles.Forsyth if(bany(&r->use1))
36374a4d8c2SCharles.Forsyth print(" u1=%B", r->use1);
36474a4d8c2SCharles.Forsyth if(bany(&r->use2))
36574a4d8c2SCharles.Forsyth print(" u2=%B", r->use2);
36674a4d8c2SCharles.Forsyth if(bany(&r->set))
36774a4d8c2SCharles.Forsyth print(" st=%B", r->set);
36874a4d8c2SCharles.Forsyth }
36974a4d8c2SCharles.Forsyth print("\n");
37074a4d8c2SCharles.Forsyth }
37174a4d8c2SCharles.Forsyth }
37274a4d8c2SCharles.Forsyth
37374a4d8c2SCharles.Forsyth /*
37474a4d8c2SCharles.Forsyth * pass 3
37574a4d8c2SCharles.Forsyth * iterate propagating usage
37674a4d8c2SCharles.Forsyth * back until flow graph is complete
37774a4d8c2SCharles.Forsyth */
37874a4d8c2SCharles.Forsyth loop1:
37974a4d8c2SCharles.Forsyth change = 0;
38074a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link)
38174a4d8c2SCharles.Forsyth r->active = 0;
38274a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link)
38374a4d8c2SCharles.Forsyth if(r->prog->as == ARET)
38474a4d8c2SCharles.Forsyth prop(r, zbits, zbits);
38574a4d8c2SCharles.Forsyth loop11:
38674a4d8c2SCharles.Forsyth /* pick up unreachable code */
38774a4d8c2SCharles.Forsyth i = 0;
38874a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r1) {
38974a4d8c2SCharles.Forsyth r1 = r->link;
39074a4d8c2SCharles.Forsyth if(r1 && r1->active && !r->active) {
39174a4d8c2SCharles.Forsyth prop(r, zbits, zbits);
39274a4d8c2SCharles.Forsyth i = 1;
39374a4d8c2SCharles.Forsyth }
39474a4d8c2SCharles.Forsyth }
39574a4d8c2SCharles.Forsyth if(i)
39674a4d8c2SCharles.Forsyth goto loop11;
39774a4d8c2SCharles.Forsyth if(change)
39874a4d8c2SCharles.Forsyth goto loop1;
39974a4d8c2SCharles.Forsyth
40074a4d8c2SCharles.Forsyth
40174a4d8c2SCharles.Forsyth /*
40274a4d8c2SCharles.Forsyth * pass 4
40374a4d8c2SCharles.Forsyth * iterate propagating register/variable synchrony
40474a4d8c2SCharles.Forsyth * forward until graph is complete
40574a4d8c2SCharles.Forsyth */
40674a4d8c2SCharles.Forsyth loop2:
40774a4d8c2SCharles.Forsyth change = 0;
40874a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link)
40974a4d8c2SCharles.Forsyth r->active = 0;
41074a4d8c2SCharles.Forsyth synch(firstr, zbits);
41174a4d8c2SCharles.Forsyth if(change)
41274a4d8c2SCharles.Forsyth goto loop2;
41374a4d8c2SCharles.Forsyth
41474a4d8c2SCharles.Forsyth
41574a4d8c2SCharles.Forsyth /*
41674a4d8c2SCharles.Forsyth * pass 5
41774a4d8c2SCharles.Forsyth * isolate regions
41874a4d8c2SCharles.Forsyth * calculate costs (paint1)
41974a4d8c2SCharles.Forsyth */
42074a4d8c2SCharles.Forsyth r = firstr;
42174a4d8c2SCharles.Forsyth if(r) {
42274a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
42374a4d8c2SCharles.Forsyth bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
42474a4d8c2SCharles.Forsyth ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
42574a4d8c2SCharles.Forsyth if(bany(&bit)) {
42674a4d8c2SCharles.Forsyth nearln = r->prog->lineno;
42774a4d8c2SCharles.Forsyth warn(Z, "used and not set: %B", bit);
42874a4d8c2SCharles.Forsyth if(debug['R'] && !debug['w'])
42974a4d8c2SCharles.Forsyth print("used and not set: %B\n", bit);
43074a4d8c2SCharles.Forsyth }
43174a4d8c2SCharles.Forsyth }
43274a4d8c2SCharles.Forsyth if(debug['R'] && debug['v'])
43374a4d8c2SCharles.Forsyth print("\nprop structure:\n");
43474a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link)
43574a4d8c2SCharles.Forsyth r->act = zbits;
43674a4d8c2SCharles.Forsyth rgp = region;
43774a4d8c2SCharles.Forsyth nregion = 0;
43874a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link) {
43974a4d8c2SCharles.Forsyth if(debug['R'] && debug['v']) {
44074a4d8c2SCharles.Forsyth print("%P\t", r->prog);
44174a4d8c2SCharles.Forsyth if(bany(&r->set))
44274a4d8c2SCharles.Forsyth print("s:%B ", r->set);
44374a4d8c2SCharles.Forsyth if(bany(&r->refahead))
44474a4d8c2SCharles.Forsyth print("ra:%B ", r->refahead);
44574a4d8c2SCharles.Forsyth if(bany(&r->calahead))
44674a4d8c2SCharles.Forsyth print("ca:%B ", r->calahead);
44774a4d8c2SCharles.Forsyth print("\n");
44874a4d8c2SCharles.Forsyth }
44974a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
45074a4d8c2SCharles.Forsyth bit.b[z] = r->set.b[z] &
45174a4d8c2SCharles.Forsyth ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
45274a4d8c2SCharles.Forsyth if(bany(&bit)) {
45374a4d8c2SCharles.Forsyth nearln = r->prog->lineno;
45474a4d8c2SCharles.Forsyth warn(Z, "set and not used: %B", bit);
45574a4d8c2SCharles.Forsyth if(debug['R'])
45674a4d8c2SCharles.Forsyth print("set and not used: %B\n", bit);
45774a4d8c2SCharles.Forsyth excise(r);
45874a4d8c2SCharles.Forsyth }
45974a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
46074a4d8c2SCharles.Forsyth bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
46174a4d8c2SCharles.Forsyth while(bany(&bit)) {
46274a4d8c2SCharles.Forsyth i = bnum(bit);
46374a4d8c2SCharles.Forsyth rgp->enter = r;
46474a4d8c2SCharles.Forsyth rgp->varno = i;
46574a4d8c2SCharles.Forsyth change = 0;
46674a4d8c2SCharles.Forsyth if(debug['R'] && debug['v'])
46774a4d8c2SCharles.Forsyth print("\n");
46874a4d8c2SCharles.Forsyth paint1(r, i);
46974a4d8c2SCharles.Forsyth bit.b[i/32] &= ~(1L<<(i%32));
47074a4d8c2SCharles.Forsyth if(change <= 0) {
47174a4d8c2SCharles.Forsyth if(debug['R'])
47274a4d8c2SCharles.Forsyth print("%L$%d: %B\n",
47374a4d8c2SCharles.Forsyth r->prog->lineno, change, blsh(i));
47474a4d8c2SCharles.Forsyth continue;
47574a4d8c2SCharles.Forsyth }
47674a4d8c2SCharles.Forsyth rgp->cost = change;
47774a4d8c2SCharles.Forsyth nregion++;
47874a4d8c2SCharles.Forsyth if(nregion >= NRGN) {
47974a4d8c2SCharles.Forsyth warn(Z, "too many regions");
48074a4d8c2SCharles.Forsyth goto brk;
48174a4d8c2SCharles.Forsyth }
48274a4d8c2SCharles.Forsyth rgp++;
48374a4d8c2SCharles.Forsyth }
48474a4d8c2SCharles.Forsyth }
48574a4d8c2SCharles.Forsyth brk:
48674a4d8c2SCharles.Forsyth qsort(region, nregion, sizeof(region[0]), rcmp);
48774a4d8c2SCharles.Forsyth
48874a4d8c2SCharles.Forsyth /*
48974a4d8c2SCharles.Forsyth * pass 6
49074a4d8c2SCharles.Forsyth * determine used registers (paint2)
49174a4d8c2SCharles.Forsyth * replace code (paint3)
49274a4d8c2SCharles.Forsyth */
49374a4d8c2SCharles.Forsyth rgp = region;
49474a4d8c2SCharles.Forsyth for(i=0; i<nregion; i++) {
49574a4d8c2SCharles.Forsyth bit = blsh(rgp->varno);
49674a4d8c2SCharles.Forsyth vreg = paint2(rgp->enter, rgp->varno);
49774a4d8c2SCharles.Forsyth vreg = allreg(vreg, rgp);
49874a4d8c2SCharles.Forsyth if(debug['R']) {
49974a4d8c2SCharles.Forsyth print("%L$%d %R: %B\n",
50074a4d8c2SCharles.Forsyth rgp->enter->prog->lineno,
50174a4d8c2SCharles.Forsyth rgp->cost,
50274a4d8c2SCharles.Forsyth rgp->regno,
50374a4d8c2SCharles.Forsyth bit);
50474a4d8c2SCharles.Forsyth }
50574a4d8c2SCharles.Forsyth if(rgp->regno != 0)
50674a4d8c2SCharles.Forsyth paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
50774a4d8c2SCharles.Forsyth rgp++;
50874a4d8c2SCharles.Forsyth }
50974a4d8c2SCharles.Forsyth /*
51074a4d8c2SCharles.Forsyth * pass 7
51174a4d8c2SCharles.Forsyth * peep-hole on basic block
51274a4d8c2SCharles.Forsyth */
51374a4d8c2SCharles.Forsyth if(!debug['R'] || debug['P'])
51474a4d8c2SCharles.Forsyth peep();
51574a4d8c2SCharles.Forsyth
51674a4d8c2SCharles.Forsyth /*
51774a4d8c2SCharles.Forsyth * pass 8
51874a4d8c2SCharles.Forsyth * recalculate pc
51974a4d8c2SCharles.Forsyth */
52074a4d8c2SCharles.Forsyth val = initpc;
52174a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r1) {
52274a4d8c2SCharles.Forsyth r->pc = val;
52374a4d8c2SCharles.Forsyth p = r->prog;
52474a4d8c2SCharles.Forsyth p1 = P;
52574a4d8c2SCharles.Forsyth r1 = r->link;
52674a4d8c2SCharles.Forsyth if(r1 != R)
52774a4d8c2SCharles.Forsyth p1 = r1->prog;
52874a4d8c2SCharles.Forsyth for(; p != p1; p = p->link) {
52974a4d8c2SCharles.Forsyth switch(p->as) {
53074a4d8c2SCharles.Forsyth default:
53174a4d8c2SCharles.Forsyth val++;
53274a4d8c2SCharles.Forsyth break;
53374a4d8c2SCharles.Forsyth
53474a4d8c2SCharles.Forsyth case ANOP:
53574a4d8c2SCharles.Forsyth case ADATA:
53674a4d8c2SCharles.Forsyth case AGLOBL:
53774a4d8c2SCharles.Forsyth case ANAME:
53874a4d8c2SCharles.Forsyth case ASIGNAME:
53974a4d8c2SCharles.Forsyth break;
54074a4d8c2SCharles.Forsyth }
54174a4d8c2SCharles.Forsyth }
54274a4d8c2SCharles.Forsyth }
54374a4d8c2SCharles.Forsyth pc = val;
54474a4d8c2SCharles.Forsyth
54574a4d8c2SCharles.Forsyth /*
54674a4d8c2SCharles.Forsyth * fix up branches
54774a4d8c2SCharles.Forsyth */
54874a4d8c2SCharles.Forsyth if(debug['R'])
54974a4d8c2SCharles.Forsyth if(bany(&addrs))
55074a4d8c2SCharles.Forsyth print("addrs: %B\n", addrs);
55174a4d8c2SCharles.Forsyth
55274a4d8c2SCharles.Forsyth r1 = 0; /* set */
55374a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link) {
55474a4d8c2SCharles.Forsyth p = r->prog;
55574a4d8c2SCharles.Forsyth if(p->to.type == D_BRANCH)
55674a4d8c2SCharles.Forsyth p->to.offset = r->s2->pc;
55774a4d8c2SCharles.Forsyth r1 = r;
55874a4d8c2SCharles.Forsyth }
55974a4d8c2SCharles.Forsyth
56074a4d8c2SCharles.Forsyth /*
56174a4d8c2SCharles.Forsyth * last pass
56274a4d8c2SCharles.Forsyth * eliminate nops
56374a4d8c2SCharles.Forsyth * free aux structures
56474a4d8c2SCharles.Forsyth */
56574a4d8c2SCharles.Forsyth for(p = firstr->prog; p != P; p = p->link){
56674a4d8c2SCharles.Forsyth while(p->link && p->link->as == ANOP)
56774a4d8c2SCharles.Forsyth p->link = p->link->link;
56874a4d8c2SCharles.Forsyth }
56974a4d8c2SCharles.Forsyth if(r1 != R) {
57074a4d8c2SCharles.Forsyth r1->link = freer;
57174a4d8c2SCharles.Forsyth freer = firstr;
57274a4d8c2SCharles.Forsyth }
57374a4d8c2SCharles.Forsyth }
57474a4d8c2SCharles.Forsyth
57574a4d8c2SCharles.Forsyth /*
57674a4d8c2SCharles.Forsyth * add mov b,rn
57774a4d8c2SCharles.Forsyth * just after r
57874a4d8c2SCharles.Forsyth */
57974a4d8c2SCharles.Forsyth void
addmove(Reg * r,int bn,int rn,int f)58074a4d8c2SCharles.Forsyth addmove(Reg *r, int bn, int rn, int f)
58174a4d8c2SCharles.Forsyth {
58274a4d8c2SCharles.Forsyth Prog *p, *p1;
58374a4d8c2SCharles.Forsyth Adr *a;
58474a4d8c2SCharles.Forsyth Var *v;
58574a4d8c2SCharles.Forsyth
58674a4d8c2SCharles.Forsyth p1 = alloc(sizeof(*p1));
58774a4d8c2SCharles.Forsyth *p1 = zprog;
58874a4d8c2SCharles.Forsyth p = r->prog;
58974a4d8c2SCharles.Forsyth
59074a4d8c2SCharles.Forsyth p1->link = p->link;
59174a4d8c2SCharles.Forsyth p->link = p1;
59274a4d8c2SCharles.Forsyth p1->lineno = p->lineno;
59374a4d8c2SCharles.Forsyth
59474a4d8c2SCharles.Forsyth v = var + bn;
59574a4d8c2SCharles.Forsyth
59674a4d8c2SCharles.Forsyth a = &p1->to;
59774a4d8c2SCharles.Forsyth a->sym = v->sym;
59874a4d8c2SCharles.Forsyth a->offset = v->offset;
59974a4d8c2SCharles.Forsyth a->etype = v->etype;
60074a4d8c2SCharles.Forsyth a->type = v->name;
60174a4d8c2SCharles.Forsyth
60274a4d8c2SCharles.Forsyth p1->as = AMOVL;
60374a4d8c2SCharles.Forsyth if(v->etype == TCHAR || v->etype == TUCHAR)
60474a4d8c2SCharles.Forsyth p1->as = AMOVB;
60574a4d8c2SCharles.Forsyth if(v->etype == TSHORT || v->etype == TUSHORT)
60674a4d8c2SCharles.Forsyth p1->as = AMOVW;
60774a4d8c2SCharles.Forsyth
60874a4d8c2SCharles.Forsyth p1->from.type = rn;
60974a4d8c2SCharles.Forsyth if(!f) {
61074a4d8c2SCharles.Forsyth p1->from = *a;
61174a4d8c2SCharles.Forsyth *a = zprog.from;
61274a4d8c2SCharles.Forsyth a->type = rn;
61374a4d8c2SCharles.Forsyth if(v->etype == TUCHAR)
61474a4d8c2SCharles.Forsyth p1->as = AMOVB;
61574a4d8c2SCharles.Forsyth if(v->etype == TUSHORT)
61674a4d8c2SCharles.Forsyth p1->as = AMOVW;
61774a4d8c2SCharles.Forsyth }
61874a4d8c2SCharles.Forsyth if(debug['R'])
61974a4d8c2SCharles.Forsyth print("%P\t.a%P\n", p, p1);
62074a4d8c2SCharles.Forsyth }
62174a4d8c2SCharles.Forsyth
62274a4d8c2SCharles.Forsyth ulong
doregbits(int r)62374a4d8c2SCharles.Forsyth doregbits(int r)
62474a4d8c2SCharles.Forsyth {
62574a4d8c2SCharles.Forsyth ulong b;
62674a4d8c2SCharles.Forsyth
62774a4d8c2SCharles.Forsyth b = 0;
62874a4d8c2SCharles.Forsyth if(r >= D_INDIR)
62974a4d8c2SCharles.Forsyth r -= D_INDIR;
63074a4d8c2SCharles.Forsyth if(r >= D_AX && r <= D_DI)
63174a4d8c2SCharles.Forsyth b |= RtoB(r);
63274a4d8c2SCharles.Forsyth else
63374a4d8c2SCharles.Forsyth if(r >= D_AL && r <= D_BL)
63474a4d8c2SCharles.Forsyth b |= RtoB(r-D_AL+D_AX);
63574a4d8c2SCharles.Forsyth else
63674a4d8c2SCharles.Forsyth if(r >= D_AH && r <= D_BH)
63774a4d8c2SCharles.Forsyth b |= RtoB(r-D_AH+D_AX);
63874a4d8c2SCharles.Forsyth return b;
63974a4d8c2SCharles.Forsyth }
64074a4d8c2SCharles.Forsyth
64174a4d8c2SCharles.Forsyth Bits
mkvar(Reg * r,Adr * a,int isro)642*45a20ab7Sforsyth mkvar(Reg *r, Adr *a, int isro)
64374a4d8c2SCharles.Forsyth {
64474a4d8c2SCharles.Forsyth Var *v;
64574a4d8c2SCharles.Forsyth int i, t, n, et, z;
64674a4d8c2SCharles.Forsyth long o;
64774a4d8c2SCharles.Forsyth Bits bit;
64874a4d8c2SCharles.Forsyth Sym *s;
64974a4d8c2SCharles.Forsyth
65074a4d8c2SCharles.Forsyth /*
65174a4d8c2SCharles.Forsyth * mark registers used
65274a4d8c2SCharles.Forsyth */
65374a4d8c2SCharles.Forsyth t = a->type;
65474a4d8c2SCharles.Forsyth r->regu |= doregbits(t);
65574a4d8c2SCharles.Forsyth r->regu |= doregbits(a->index);
656*45a20ab7Sforsyth et = a->etype;
65774a4d8c2SCharles.Forsyth
65874a4d8c2SCharles.Forsyth switch(t) {
65974a4d8c2SCharles.Forsyth default:
66074a4d8c2SCharles.Forsyth goto none;
661*45a20ab7Sforsyth case D_INDIR+D_GS:
662*45a20ab7Sforsyth if(!isro || 1)
663*45a20ab7Sforsyth goto none;
664*45a20ab7Sforsyth n = t;
665*45a20ab7Sforsyth {static Sym er; a->sym = &er;}
666*45a20ab7Sforsyth a->sym->name = "$extreg";
667*45a20ab7Sforsyth break;
66874a4d8c2SCharles.Forsyth case D_ADDR:
66974a4d8c2SCharles.Forsyth a->type = a->index;
670*45a20ab7Sforsyth bit = mkvar(r, a, 0);
67174a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
67274a4d8c2SCharles.Forsyth addrs.b[z] |= bit.b[z];
67374a4d8c2SCharles.Forsyth a->type = t;
67474a4d8c2SCharles.Forsyth goto none;
67574a4d8c2SCharles.Forsyth case D_EXTERN:
67674a4d8c2SCharles.Forsyth case D_STATIC:
67774a4d8c2SCharles.Forsyth case D_PARAM:
67874a4d8c2SCharles.Forsyth case D_AUTO:
67974a4d8c2SCharles.Forsyth n = t;
68074a4d8c2SCharles.Forsyth break;
68174a4d8c2SCharles.Forsyth }
68274a4d8c2SCharles.Forsyth s = a->sym;
68374a4d8c2SCharles.Forsyth if(s == S)
68474a4d8c2SCharles.Forsyth goto none;
68574a4d8c2SCharles.Forsyth if(s->name[0] == '.')
68674a4d8c2SCharles.Forsyth goto none;
68774a4d8c2SCharles.Forsyth o = a->offset;
68874a4d8c2SCharles.Forsyth v = var;
68974a4d8c2SCharles.Forsyth for(i=0; i<nvar; i++) {
69074a4d8c2SCharles.Forsyth if(s == v->sym)
69174a4d8c2SCharles.Forsyth if(n == v->name)
69274a4d8c2SCharles.Forsyth if(o == v->offset)
69374a4d8c2SCharles.Forsyth goto out;
69474a4d8c2SCharles.Forsyth v++;
69574a4d8c2SCharles.Forsyth }
69674a4d8c2SCharles.Forsyth if(nvar >= NVAR) {
69774a4d8c2SCharles.Forsyth if(debug['w'] > 1 && s)
69874a4d8c2SCharles.Forsyth warn(Z, "variable not optimized: %s", s->name);
69974a4d8c2SCharles.Forsyth goto none;
70074a4d8c2SCharles.Forsyth }
70174a4d8c2SCharles.Forsyth i = nvar;
70274a4d8c2SCharles.Forsyth nvar++;
70374a4d8c2SCharles.Forsyth v = &var[i];
70474a4d8c2SCharles.Forsyth v->sym = s;
70574a4d8c2SCharles.Forsyth v->offset = o;
70674a4d8c2SCharles.Forsyth v->name = n;
70774a4d8c2SCharles.Forsyth v->etype = et;
70874a4d8c2SCharles.Forsyth if(debug['R'])
70974a4d8c2SCharles.Forsyth print("bit=%2d et=%2d %D\n", i, et, a);
71074a4d8c2SCharles.Forsyth
71174a4d8c2SCharles.Forsyth out:
71274a4d8c2SCharles.Forsyth bit = blsh(i);
71374a4d8c2SCharles.Forsyth if(n == D_EXTERN || n == D_STATIC)
71474a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
71574a4d8c2SCharles.Forsyth externs.b[z] |= bit.b[z];
71674a4d8c2SCharles.Forsyth if(n == D_PARAM)
71774a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
71874a4d8c2SCharles.Forsyth params.b[z] |= bit.b[z];
71974a4d8c2SCharles.Forsyth if(v->etype != et || !typechlpfd[et]) /* funny punning */
72074a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
72174a4d8c2SCharles.Forsyth addrs.b[z] |= bit.b[z];
72274a4d8c2SCharles.Forsyth return bit;
72374a4d8c2SCharles.Forsyth
72474a4d8c2SCharles.Forsyth none:
72574a4d8c2SCharles.Forsyth return zbits;
72674a4d8c2SCharles.Forsyth }
72774a4d8c2SCharles.Forsyth
72874a4d8c2SCharles.Forsyth void
prop(Reg * r,Bits ref,Bits cal)72974a4d8c2SCharles.Forsyth prop(Reg *r, Bits ref, Bits cal)
73074a4d8c2SCharles.Forsyth {
73174a4d8c2SCharles.Forsyth Reg *r1, *r2;
73274a4d8c2SCharles.Forsyth int z;
73374a4d8c2SCharles.Forsyth
73474a4d8c2SCharles.Forsyth for(r1 = r; r1 != R; r1 = r1->p1) {
73574a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
73674a4d8c2SCharles.Forsyth ref.b[z] |= r1->refahead.b[z];
73774a4d8c2SCharles.Forsyth if(ref.b[z] != r1->refahead.b[z]) {
73874a4d8c2SCharles.Forsyth r1->refahead.b[z] = ref.b[z];
73974a4d8c2SCharles.Forsyth change++;
74074a4d8c2SCharles.Forsyth }
74174a4d8c2SCharles.Forsyth cal.b[z] |= r1->calahead.b[z];
74274a4d8c2SCharles.Forsyth if(cal.b[z] != r1->calahead.b[z]) {
74374a4d8c2SCharles.Forsyth r1->calahead.b[z] = cal.b[z];
74474a4d8c2SCharles.Forsyth change++;
74574a4d8c2SCharles.Forsyth }
74674a4d8c2SCharles.Forsyth }
74774a4d8c2SCharles.Forsyth switch(r1->prog->as) {
74874a4d8c2SCharles.Forsyth case ACALL:
74974a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
75074a4d8c2SCharles.Forsyth cal.b[z] |= ref.b[z] | externs.b[z];
75174a4d8c2SCharles.Forsyth ref.b[z] = 0;
75274a4d8c2SCharles.Forsyth }
75374a4d8c2SCharles.Forsyth break;
75474a4d8c2SCharles.Forsyth
75574a4d8c2SCharles.Forsyth case ATEXT:
75674a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
75774a4d8c2SCharles.Forsyth cal.b[z] = 0;
75874a4d8c2SCharles.Forsyth ref.b[z] = 0;
75974a4d8c2SCharles.Forsyth }
76074a4d8c2SCharles.Forsyth break;
76174a4d8c2SCharles.Forsyth
76274a4d8c2SCharles.Forsyth case ARET:
76374a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
76474a4d8c2SCharles.Forsyth cal.b[z] = externs.b[z];
76574a4d8c2SCharles.Forsyth ref.b[z] = 0;
76674a4d8c2SCharles.Forsyth }
76774a4d8c2SCharles.Forsyth }
76874a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
76974a4d8c2SCharles.Forsyth ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
77074a4d8c2SCharles.Forsyth r1->use1.b[z] | r1->use2.b[z];
77174a4d8c2SCharles.Forsyth cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
77274a4d8c2SCharles.Forsyth r1->refbehind.b[z] = ref.b[z];
77374a4d8c2SCharles.Forsyth r1->calbehind.b[z] = cal.b[z];
77474a4d8c2SCharles.Forsyth }
77574a4d8c2SCharles.Forsyth if(r1->active)
77674a4d8c2SCharles.Forsyth break;
77774a4d8c2SCharles.Forsyth r1->active = 1;
77874a4d8c2SCharles.Forsyth }
77974a4d8c2SCharles.Forsyth for(; r != r1; r = r->p1)
78074a4d8c2SCharles.Forsyth for(r2 = r->p2; r2 != R; r2 = r2->p2link)
78174a4d8c2SCharles.Forsyth prop(r2, r->refbehind, r->calbehind);
78274a4d8c2SCharles.Forsyth }
78374a4d8c2SCharles.Forsyth
78474a4d8c2SCharles.Forsyth /*
78574a4d8c2SCharles.Forsyth * find looping structure
78674a4d8c2SCharles.Forsyth *
78774a4d8c2SCharles.Forsyth * 1) find reverse postordering
78874a4d8c2SCharles.Forsyth * 2) find approximate dominators,
78974a4d8c2SCharles.Forsyth * the actual dominators if the flow graph is reducible
79074a4d8c2SCharles.Forsyth * otherwise, dominators plus some other non-dominators.
79174a4d8c2SCharles.Forsyth * See Matthew S. Hecht and Jeffrey D. Ullman,
79274a4d8c2SCharles.Forsyth * "Analysis of a Simple Algorithm for Global Data Flow Problems",
79374a4d8c2SCharles.Forsyth * Conf. Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
79474a4d8c2SCharles.Forsyth * Oct. 1-3, 1973, pp. 207-217.
79574a4d8c2SCharles.Forsyth * 3) find all nodes with a predecessor dominated by the current node.
79674a4d8c2SCharles.Forsyth * such a node is a loop head.
79774a4d8c2SCharles.Forsyth * recursively, all preds with a greater rpo number are in the loop
79874a4d8c2SCharles.Forsyth */
79974a4d8c2SCharles.Forsyth long
postorder(Reg * r,Reg ** rpo2r,long n)80074a4d8c2SCharles.Forsyth postorder(Reg *r, Reg **rpo2r, long n)
80174a4d8c2SCharles.Forsyth {
80274a4d8c2SCharles.Forsyth Reg *r1;
80374a4d8c2SCharles.Forsyth
80474a4d8c2SCharles.Forsyth r->rpo = 1;
80574a4d8c2SCharles.Forsyth r1 = r->s1;
80674a4d8c2SCharles.Forsyth if(r1 && !r1->rpo)
80774a4d8c2SCharles.Forsyth n = postorder(r1, rpo2r, n);
80874a4d8c2SCharles.Forsyth r1 = r->s2;
80974a4d8c2SCharles.Forsyth if(r1 && !r1->rpo)
81074a4d8c2SCharles.Forsyth n = postorder(r1, rpo2r, n);
81174a4d8c2SCharles.Forsyth rpo2r[n] = r;
81274a4d8c2SCharles.Forsyth n++;
81374a4d8c2SCharles.Forsyth return n;
81474a4d8c2SCharles.Forsyth }
81574a4d8c2SCharles.Forsyth
81674a4d8c2SCharles.Forsyth long
rpolca(long * idom,long rpo1,long rpo2)81774a4d8c2SCharles.Forsyth rpolca(long *idom, long rpo1, long rpo2)
81874a4d8c2SCharles.Forsyth {
81974a4d8c2SCharles.Forsyth long t;
82074a4d8c2SCharles.Forsyth
82174a4d8c2SCharles.Forsyth if(rpo1 == -1)
82274a4d8c2SCharles.Forsyth return rpo2;
82374a4d8c2SCharles.Forsyth while(rpo1 != rpo2){
82474a4d8c2SCharles.Forsyth if(rpo1 > rpo2){
82574a4d8c2SCharles.Forsyth t = rpo2;
82674a4d8c2SCharles.Forsyth rpo2 = rpo1;
82774a4d8c2SCharles.Forsyth rpo1 = t;
82874a4d8c2SCharles.Forsyth }
82974a4d8c2SCharles.Forsyth while(rpo1 < rpo2){
83074a4d8c2SCharles.Forsyth t = idom[rpo2];
83174a4d8c2SCharles.Forsyth if(t >= rpo2)
83274a4d8c2SCharles.Forsyth fatal(Z, "bad idom");
83374a4d8c2SCharles.Forsyth rpo2 = t;
83474a4d8c2SCharles.Forsyth }
83574a4d8c2SCharles.Forsyth }
83674a4d8c2SCharles.Forsyth return rpo1;
83774a4d8c2SCharles.Forsyth }
83874a4d8c2SCharles.Forsyth
83974a4d8c2SCharles.Forsyth int
doms(long * idom,long r,long s)84074a4d8c2SCharles.Forsyth doms(long *idom, long r, long s)
84174a4d8c2SCharles.Forsyth {
84274a4d8c2SCharles.Forsyth while(s > r)
84374a4d8c2SCharles.Forsyth s = idom[s];
84474a4d8c2SCharles.Forsyth return s == r;
84574a4d8c2SCharles.Forsyth }
84674a4d8c2SCharles.Forsyth
84774a4d8c2SCharles.Forsyth int
loophead(long * idom,Reg * r)84874a4d8c2SCharles.Forsyth loophead(long *idom, Reg *r)
84974a4d8c2SCharles.Forsyth {
85074a4d8c2SCharles.Forsyth long src;
85174a4d8c2SCharles.Forsyth
85274a4d8c2SCharles.Forsyth src = r->rpo;
85374a4d8c2SCharles.Forsyth if(r->p1 != R && doms(idom, src, r->p1->rpo))
85474a4d8c2SCharles.Forsyth return 1;
85574a4d8c2SCharles.Forsyth for(r = r->p2; r != R; r = r->p2link)
85674a4d8c2SCharles.Forsyth if(doms(idom, src, r->rpo))
85774a4d8c2SCharles.Forsyth return 1;
85874a4d8c2SCharles.Forsyth return 0;
85974a4d8c2SCharles.Forsyth }
86074a4d8c2SCharles.Forsyth
86174a4d8c2SCharles.Forsyth void
loopmark(Reg ** rpo2r,long head,Reg * r)86274a4d8c2SCharles.Forsyth loopmark(Reg **rpo2r, long head, Reg *r)
86374a4d8c2SCharles.Forsyth {
86474a4d8c2SCharles.Forsyth if(r->rpo < head || r->active == head)
86574a4d8c2SCharles.Forsyth return;
86674a4d8c2SCharles.Forsyth r->active = head;
86774a4d8c2SCharles.Forsyth r->loop += LOOP;
86874a4d8c2SCharles.Forsyth if(r->p1 != R)
86974a4d8c2SCharles.Forsyth loopmark(rpo2r, head, r->p1);
87074a4d8c2SCharles.Forsyth for(r = r->p2; r != R; r = r->p2link)
87174a4d8c2SCharles.Forsyth loopmark(rpo2r, head, r);
87274a4d8c2SCharles.Forsyth }
87374a4d8c2SCharles.Forsyth
87474a4d8c2SCharles.Forsyth void
loopit(Reg * r,long nr)87574a4d8c2SCharles.Forsyth loopit(Reg *r, long nr)
87674a4d8c2SCharles.Forsyth {
87774a4d8c2SCharles.Forsyth Reg *r1;
87874a4d8c2SCharles.Forsyth long i, d, me;
87974a4d8c2SCharles.Forsyth
88074a4d8c2SCharles.Forsyth if(nr > maxnr) {
88174a4d8c2SCharles.Forsyth rpo2r = alloc(nr * sizeof(Reg*));
88274a4d8c2SCharles.Forsyth idom = alloc(nr * sizeof(long));
88374a4d8c2SCharles.Forsyth maxnr = nr;
88474a4d8c2SCharles.Forsyth }
88574a4d8c2SCharles.Forsyth
88674a4d8c2SCharles.Forsyth d = postorder(r, rpo2r, 0);
88774a4d8c2SCharles.Forsyth if(d > nr)
88874a4d8c2SCharles.Forsyth fatal(Z, "too many reg nodes");
88974a4d8c2SCharles.Forsyth nr = d;
89074a4d8c2SCharles.Forsyth for(i = 0; i < nr / 2; i++){
89174a4d8c2SCharles.Forsyth r1 = rpo2r[i];
89274a4d8c2SCharles.Forsyth rpo2r[i] = rpo2r[nr - 1 - i];
89374a4d8c2SCharles.Forsyth rpo2r[nr - 1 - i] = r1;
89474a4d8c2SCharles.Forsyth }
89574a4d8c2SCharles.Forsyth for(i = 0; i < nr; i++)
89674a4d8c2SCharles.Forsyth rpo2r[i]->rpo = i;
89774a4d8c2SCharles.Forsyth
89874a4d8c2SCharles.Forsyth idom[0] = 0;
89974a4d8c2SCharles.Forsyth for(i = 0; i < nr; i++){
90074a4d8c2SCharles.Forsyth r1 = rpo2r[i];
90174a4d8c2SCharles.Forsyth me = r1->rpo;
90274a4d8c2SCharles.Forsyth d = -1;
90374a4d8c2SCharles.Forsyth if(r1->p1 != R && r1->p1->rpo < me)
90474a4d8c2SCharles.Forsyth d = r1->p1->rpo;
90574a4d8c2SCharles.Forsyth for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
90674a4d8c2SCharles.Forsyth if(r1->rpo < me)
90774a4d8c2SCharles.Forsyth d = rpolca(idom, d, r1->rpo);
90874a4d8c2SCharles.Forsyth idom[i] = d;
90974a4d8c2SCharles.Forsyth }
91074a4d8c2SCharles.Forsyth
91174a4d8c2SCharles.Forsyth for(i = 0; i < nr; i++){
91274a4d8c2SCharles.Forsyth r1 = rpo2r[i];
91374a4d8c2SCharles.Forsyth r1->loop++;
91474a4d8c2SCharles.Forsyth if(r1->p2 != R && loophead(idom, r1))
91574a4d8c2SCharles.Forsyth loopmark(rpo2r, i, r1);
91674a4d8c2SCharles.Forsyth }
91774a4d8c2SCharles.Forsyth }
91874a4d8c2SCharles.Forsyth
91974a4d8c2SCharles.Forsyth void
synch(Reg * r,Bits dif)92074a4d8c2SCharles.Forsyth synch(Reg *r, Bits dif)
92174a4d8c2SCharles.Forsyth {
92274a4d8c2SCharles.Forsyth Reg *r1;
92374a4d8c2SCharles.Forsyth int z;
92474a4d8c2SCharles.Forsyth
92574a4d8c2SCharles.Forsyth for(r1 = r; r1 != R; r1 = r1->s1) {
92674a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
92774a4d8c2SCharles.Forsyth dif.b[z] = (dif.b[z] &
92874a4d8c2SCharles.Forsyth ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
92974a4d8c2SCharles.Forsyth r1->set.b[z] | r1->regdiff.b[z];
93074a4d8c2SCharles.Forsyth if(dif.b[z] != r1->regdiff.b[z]) {
93174a4d8c2SCharles.Forsyth r1->regdiff.b[z] = dif.b[z];
93274a4d8c2SCharles.Forsyth change++;
93374a4d8c2SCharles.Forsyth }
93474a4d8c2SCharles.Forsyth }
93574a4d8c2SCharles.Forsyth if(r1->active)
93674a4d8c2SCharles.Forsyth break;
93774a4d8c2SCharles.Forsyth r1->active = 1;
93874a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
93974a4d8c2SCharles.Forsyth dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
94074a4d8c2SCharles.Forsyth if(r1->s2 != R)
94174a4d8c2SCharles.Forsyth synch(r1->s2, dif);
94274a4d8c2SCharles.Forsyth }
94374a4d8c2SCharles.Forsyth }
94474a4d8c2SCharles.Forsyth
94574a4d8c2SCharles.Forsyth ulong
allreg(ulong b,Rgn * r)94674a4d8c2SCharles.Forsyth allreg(ulong b, Rgn *r)
94774a4d8c2SCharles.Forsyth {
94874a4d8c2SCharles.Forsyth Var *v;
94974a4d8c2SCharles.Forsyth int i;
95074a4d8c2SCharles.Forsyth
95174a4d8c2SCharles.Forsyth v = var + r->varno;
95274a4d8c2SCharles.Forsyth r->regno = 0;
95374a4d8c2SCharles.Forsyth switch(v->etype) {
95474a4d8c2SCharles.Forsyth
95574a4d8c2SCharles.Forsyth default:
95674a4d8c2SCharles.Forsyth diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
95774a4d8c2SCharles.Forsyth break;
95874a4d8c2SCharles.Forsyth
95974a4d8c2SCharles.Forsyth case TCHAR:
96074a4d8c2SCharles.Forsyth case TUCHAR:
96174a4d8c2SCharles.Forsyth case TSHORT:
96274a4d8c2SCharles.Forsyth case TUSHORT:
96374a4d8c2SCharles.Forsyth case TINT:
96474a4d8c2SCharles.Forsyth case TUINT:
96574a4d8c2SCharles.Forsyth case TLONG:
96674a4d8c2SCharles.Forsyth case TULONG:
96774a4d8c2SCharles.Forsyth case TIND:
96874a4d8c2SCharles.Forsyth case TARRAY:
96974a4d8c2SCharles.Forsyth i = BtoR(~b);
97074a4d8c2SCharles.Forsyth if(i && r->cost > 0) {
97174a4d8c2SCharles.Forsyth r->regno = i;
97274a4d8c2SCharles.Forsyth return RtoB(i);
97374a4d8c2SCharles.Forsyth }
97474a4d8c2SCharles.Forsyth break;
97574a4d8c2SCharles.Forsyth
97674a4d8c2SCharles.Forsyth case TDOUBLE:
97774a4d8c2SCharles.Forsyth case TFLOAT:
97874a4d8c2SCharles.Forsyth break;
97974a4d8c2SCharles.Forsyth }
98074a4d8c2SCharles.Forsyth return 0;
98174a4d8c2SCharles.Forsyth }
98274a4d8c2SCharles.Forsyth
98374a4d8c2SCharles.Forsyth void
paint1(Reg * r,int bn)98474a4d8c2SCharles.Forsyth paint1(Reg *r, int bn)
98574a4d8c2SCharles.Forsyth {
98674a4d8c2SCharles.Forsyth Reg *r1;
98774a4d8c2SCharles.Forsyth Prog *p;
98874a4d8c2SCharles.Forsyth int z;
98974a4d8c2SCharles.Forsyth ulong bb;
99074a4d8c2SCharles.Forsyth
99174a4d8c2SCharles.Forsyth z = bn/32;
99274a4d8c2SCharles.Forsyth bb = 1L<<(bn%32);
99374a4d8c2SCharles.Forsyth if(r->act.b[z] & bb)
99474a4d8c2SCharles.Forsyth return;
99574a4d8c2SCharles.Forsyth for(;;) {
99674a4d8c2SCharles.Forsyth if(!(r->refbehind.b[z] & bb))
99774a4d8c2SCharles.Forsyth break;
99874a4d8c2SCharles.Forsyth r1 = r->p1;
99974a4d8c2SCharles.Forsyth if(r1 == R)
100074a4d8c2SCharles.Forsyth break;
100174a4d8c2SCharles.Forsyth if(!(r1->refahead.b[z] & bb))
100274a4d8c2SCharles.Forsyth break;
100374a4d8c2SCharles.Forsyth if(r1->act.b[z] & bb)
100474a4d8c2SCharles.Forsyth break;
100574a4d8c2SCharles.Forsyth r = r1;
100674a4d8c2SCharles.Forsyth }
100774a4d8c2SCharles.Forsyth
100874a4d8c2SCharles.Forsyth if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
100974a4d8c2SCharles.Forsyth change -= CLOAD * r->loop;
101074a4d8c2SCharles.Forsyth if(debug['R'] && debug['v'])
101174a4d8c2SCharles.Forsyth print("%ld%P\tld %B $%d\n", r->loop,
101274a4d8c2SCharles.Forsyth r->prog, blsh(bn), change);
101374a4d8c2SCharles.Forsyth }
101474a4d8c2SCharles.Forsyth for(;;) {
101574a4d8c2SCharles.Forsyth r->act.b[z] |= bb;
101674a4d8c2SCharles.Forsyth p = r->prog;
101774a4d8c2SCharles.Forsyth
101874a4d8c2SCharles.Forsyth if(r->use1.b[z] & bb) {
101974a4d8c2SCharles.Forsyth change += CREF * r->loop;
1020*45a20ab7Sforsyth if(p->as == AFMOVL || p->as == AFMOVW)
102174a4d8c2SCharles.Forsyth if(BtoR(bb) != D_F0)
102274a4d8c2SCharles.Forsyth change = -CINF;
102374a4d8c2SCharles.Forsyth if(debug['R'] && debug['v'])
102474a4d8c2SCharles.Forsyth print("%ld%P\tu1 %B $%d\n", r->loop,
102574a4d8c2SCharles.Forsyth p, blsh(bn), change);
102674a4d8c2SCharles.Forsyth }
102774a4d8c2SCharles.Forsyth
102874a4d8c2SCharles.Forsyth if((r->use2.b[z]|r->set.b[z]) & bb) {
102974a4d8c2SCharles.Forsyth change += CREF * r->loop;
1030*45a20ab7Sforsyth if(p->as == AFMOVL || p->as == AFMOVW)
103174a4d8c2SCharles.Forsyth if(BtoR(bb) != D_F0)
103274a4d8c2SCharles.Forsyth change = -CINF;
103374a4d8c2SCharles.Forsyth if(debug['R'] && debug['v'])
103474a4d8c2SCharles.Forsyth print("%ld%P\tu2 %B $%d\n", r->loop,
103574a4d8c2SCharles.Forsyth p, blsh(bn), change);
103674a4d8c2SCharles.Forsyth }
103774a4d8c2SCharles.Forsyth
103874a4d8c2SCharles.Forsyth if(STORE(r) & r->regdiff.b[z] & bb) {
103974a4d8c2SCharles.Forsyth change -= CLOAD * r->loop;
1040*45a20ab7Sforsyth if(p->as == AFMOVL || p->as == AFMOVW)
104174a4d8c2SCharles.Forsyth if(BtoR(bb) != D_F0)
104274a4d8c2SCharles.Forsyth change = -CINF;
104374a4d8c2SCharles.Forsyth if(debug['R'] && debug['v'])
104474a4d8c2SCharles.Forsyth print("%ld%P\tst %B $%d\n", r->loop,
104574a4d8c2SCharles.Forsyth p, blsh(bn), change);
104674a4d8c2SCharles.Forsyth }
104774a4d8c2SCharles.Forsyth
104874a4d8c2SCharles.Forsyth if(r->refbehind.b[z] & bb)
104974a4d8c2SCharles.Forsyth for(r1 = r->p2; r1 != R; r1 = r1->p2link)
105074a4d8c2SCharles.Forsyth if(r1->refahead.b[z] & bb)
105174a4d8c2SCharles.Forsyth paint1(r1, bn);
105274a4d8c2SCharles.Forsyth
105374a4d8c2SCharles.Forsyth if(!(r->refahead.b[z] & bb))
105474a4d8c2SCharles.Forsyth break;
105574a4d8c2SCharles.Forsyth r1 = r->s2;
105674a4d8c2SCharles.Forsyth if(r1 != R)
105774a4d8c2SCharles.Forsyth if(r1->refbehind.b[z] & bb)
105874a4d8c2SCharles.Forsyth paint1(r1, bn);
105974a4d8c2SCharles.Forsyth r = r->s1;
106074a4d8c2SCharles.Forsyth if(r == R)
106174a4d8c2SCharles.Forsyth break;
106274a4d8c2SCharles.Forsyth if(r->act.b[z] & bb)
106374a4d8c2SCharles.Forsyth break;
106474a4d8c2SCharles.Forsyth if(!(r->refbehind.b[z] & bb))
106574a4d8c2SCharles.Forsyth break;
106674a4d8c2SCharles.Forsyth }
106774a4d8c2SCharles.Forsyth }
106874a4d8c2SCharles.Forsyth
106974a4d8c2SCharles.Forsyth ulong
regset(Reg * r,ulong bb)107074a4d8c2SCharles.Forsyth regset(Reg *r, ulong bb)
107174a4d8c2SCharles.Forsyth {
107274a4d8c2SCharles.Forsyth ulong b, set;
107374a4d8c2SCharles.Forsyth Adr v;
107474a4d8c2SCharles.Forsyth int c;
107574a4d8c2SCharles.Forsyth
107674a4d8c2SCharles.Forsyth set = 0;
107774a4d8c2SCharles.Forsyth v = zprog.from;
107874a4d8c2SCharles.Forsyth while(b = bb & ~(bb-1)) {
107974a4d8c2SCharles.Forsyth v.type = BtoR(b);
108074a4d8c2SCharles.Forsyth c = copyu(r->prog, &v, A);
108174a4d8c2SCharles.Forsyth if(c == 3)
108274a4d8c2SCharles.Forsyth set |= b;
108374a4d8c2SCharles.Forsyth bb &= ~b;
108474a4d8c2SCharles.Forsyth }
108574a4d8c2SCharles.Forsyth return set;
108674a4d8c2SCharles.Forsyth }
108774a4d8c2SCharles.Forsyth
108874a4d8c2SCharles.Forsyth ulong
reguse(Reg * r,ulong bb)108974a4d8c2SCharles.Forsyth reguse(Reg *r, ulong bb)
109074a4d8c2SCharles.Forsyth {
109174a4d8c2SCharles.Forsyth ulong b, set;
109274a4d8c2SCharles.Forsyth Adr v;
109374a4d8c2SCharles.Forsyth int c;
109474a4d8c2SCharles.Forsyth
109574a4d8c2SCharles.Forsyth set = 0;
109674a4d8c2SCharles.Forsyth v = zprog.from;
109774a4d8c2SCharles.Forsyth while(b = bb & ~(bb-1)) {
109874a4d8c2SCharles.Forsyth v.type = BtoR(b);
109974a4d8c2SCharles.Forsyth c = copyu(r->prog, &v, A);
110074a4d8c2SCharles.Forsyth if(c == 1 || c == 2 || c == 4)
110174a4d8c2SCharles.Forsyth set |= b;
110274a4d8c2SCharles.Forsyth bb &= ~b;
110374a4d8c2SCharles.Forsyth }
110474a4d8c2SCharles.Forsyth return set;
110574a4d8c2SCharles.Forsyth }
110674a4d8c2SCharles.Forsyth
110774a4d8c2SCharles.Forsyth ulong
paint2(Reg * r,int bn)110874a4d8c2SCharles.Forsyth paint2(Reg *r, int bn)
110974a4d8c2SCharles.Forsyth {
111074a4d8c2SCharles.Forsyth Reg *r1;
111174a4d8c2SCharles.Forsyth int z;
111274a4d8c2SCharles.Forsyth ulong bb, vreg, x;
111374a4d8c2SCharles.Forsyth
111474a4d8c2SCharles.Forsyth z = bn/32;
111574a4d8c2SCharles.Forsyth bb = 1L << (bn%32);
111674a4d8c2SCharles.Forsyth vreg = regbits;
111774a4d8c2SCharles.Forsyth if(!(r->act.b[z] & bb))
111874a4d8c2SCharles.Forsyth return vreg;
111974a4d8c2SCharles.Forsyth for(;;) {
112074a4d8c2SCharles.Forsyth if(!(r->refbehind.b[z] & bb))
112174a4d8c2SCharles.Forsyth break;
112274a4d8c2SCharles.Forsyth r1 = r->p1;
112374a4d8c2SCharles.Forsyth if(r1 == R)
112474a4d8c2SCharles.Forsyth break;
112574a4d8c2SCharles.Forsyth if(!(r1->refahead.b[z] & bb))
112674a4d8c2SCharles.Forsyth break;
112774a4d8c2SCharles.Forsyth if(!(r1->act.b[z] & bb))
112874a4d8c2SCharles.Forsyth break;
112974a4d8c2SCharles.Forsyth r = r1;
113074a4d8c2SCharles.Forsyth }
113174a4d8c2SCharles.Forsyth for(;;) {
113274a4d8c2SCharles.Forsyth r->act.b[z] &= ~bb;
113374a4d8c2SCharles.Forsyth
113474a4d8c2SCharles.Forsyth vreg |= r->regu;
113574a4d8c2SCharles.Forsyth
113674a4d8c2SCharles.Forsyth if(r->refbehind.b[z] & bb)
113774a4d8c2SCharles.Forsyth for(r1 = r->p2; r1 != R; r1 = r1->p2link)
113874a4d8c2SCharles.Forsyth if(r1->refahead.b[z] & bb)
113974a4d8c2SCharles.Forsyth vreg |= paint2(r1, bn);
114074a4d8c2SCharles.Forsyth
114174a4d8c2SCharles.Forsyth if(!(r->refahead.b[z] & bb))
114274a4d8c2SCharles.Forsyth break;
114374a4d8c2SCharles.Forsyth r1 = r->s2;
114474a4d8c2SCharles.Forsyth if(r1 != R)
114574a4d8c2SCharles.Forsyth if(r1->refbehind.b[z] & bb)
114674a4d8c2SCharles.Forsyth vreg |= paint2(r1, bn);
114774a4d8c2SCharles.Forsyth r = r->s1;
114874a4d8c2SCharles.Forsyth if(r == R)
114974a4d8c2SCharles.Forsyth break;
115074a4d8c2SCharles.Forsyth if(!(r->act.b[z] & bb))
115174a4d8c2SCharles.Forsyth break;
115274a4d8c2SCharles.Forsyth if(!(r->refbehind.b[z] & bb))
115374a4d8c2SCharles.Forsyth break;
115474a4d8c2SCharles.Forsyth }
115574a4d8c2SCharles.Forsyth
115674a4d8c2SCharles.Forsyth bb = vreg;
115774a4d8c2SCharles.Forsyth for(; r; r=r->s1) {
115874a4d8c2SCharles.Forsyth x = r->regu & ~bb;
115974a4d8c2SCharles.Forsyth if(x) {
116074a4d8c2SCharles.Forsyth vreg |= reguse(r, x);
116174a4d8c2SCharles.Forsyth bb |= regset(r, x);
116274a4d8c2SCharles.Forsyth }
116374a4d8c2SCharles.Forsyth }
116474a4d8c2SCharles.Forsyth return vreg;
116574a4d8c2SCharles.Forsyth }
116674a4d8c2SCharles.Forsyth
116774a4d8c2SCharles.Forsyth void
paint3(Reg * r,int bn,long rb,int rn)116874a4d8c2SCharles.Forsyth paint3(Reg *r, int bn, long rb, int rn)
116974a4d8c2SCharles.Forsyth {
117074a4d8c2SCharles.Forsyth Reg *r1;
117174a4d8c2SCharles.Forsyth Prog *p;
117274a4d8c2SCharles.Forsyth int z;
117374a4d8c2SCharles.Forsyth ulong bb;
117474a4d8c2SCharles.Forsyth
117574a4d8c2SCharles.Forsyth z = bn/32;
117674a4d8c2SCharles.Forsyth bb = 1L << (bn%32);
117774a4d8c2SCharles.Forsyth if(r->act.b[z] & bb)
117874a4d8c2SCharles.Forsyth return;
117974a4d8c2SCharles.Forsyth for(;;) {
118074a4d8c2SCharles.Forsyth if(!(r->refbehind.b[z] & bb))
118174a4d8c2SCharles.Forsyth break;
118274a4d8c2SCharles.Forsyth r1 = r->p1;
118374a4d8c2SCharles.Forsyth if(r1 == R)
118474a4d8c2SCharles.Forsyth break;
118574a4d8c2SCharles.Forsyth if(!(r1->refahead.b[z] & bb))
118674a4d8c2SCharles.Forsyth break;
118774a4d8c2SCharles.Forsyth if(r1->act.b[z] & bb)
118874a4d8c2SCharles.Forsyth break;
118974a4d8c2SCharles.Forsyth r = r1;
119074a4d8c2SCharles.Forsyth }
119174a4d8c2SCharles.Forsyth
119274a4d8c2SCharles.Forsyth if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
119374a4d8c2SCharles.Forsyth addmove(r, bn, rn, 0);
119474a4d8c2SCharles.Forsyth for(;;) {
119574a4d8c2SCharles.Forsyth r->act.b[z] |= bb;
119674a4d8c2SCharles.Forsyth p = r->prog;
119774a4d8c2SCharles.Forsyth
119874a4d8c2SCharles.Forsyth if(r->use1.b[z] & bb) {
119974a4d8c2SCharles.Forsyth if(debug['R'])
120074a4d8c2SCharles.Forsyth print("%P", p);
120174a4d8c2SCharles.Forsyth addreg(&p->from, rn);
120274a4d8c2SCharles.Forsyth if(debug['R'])
120374a4d8c2SCharles.Forsyth print("\t.c%P\n", p);
120474a4d8c2SCharles.Forsyth }
120574a4d8c2SCharles.Forsyth if((r->use2.b[z]|r->set.b[z]) & bb) {
120674a4d8c2SCharles.Forsyth if(debug['R'])
120774a4d8c2SCharles.Forsyth print("%P", p);
120874a4d8c2SCharles.Forsyth addreg(&p->to, rn);
120974a4d8c2SCharles.Forsyth if(debug['R'])
121074a4d8c2SCharles.Forsyth print("\t.c%P\n", p);
121174a4d8c2SCharles.Forsyth }
121274a4d8c2SCharles.Forsyth
121374a4d8c2SCharles.Forsyth if(STORE(r) & r->regdiff.b[z] & bb)
121474a4d8c2SCharles.Forsyth addmove(r, bn, rn, 1);
121574a4d8c2SCharles.Forsyth r->regu |= rb;
121674a4d8c2SCharles.Forsyth
121774a4d8c2SCharles.Forsyth if(r->refbehind.b[z] & bb)
121874a4d8c2SCharles.Forsyth for(r1 = r->p2; r1 != R; r1 = r1->p2link)
121974a4d8c2SCharles.Forsyth if(r1->refahead.b[z] & bb)
122074a4d8c2SCharles.Forsyth paint3(r1, bn, rb, rn);
122174a4d8c2SCharles.Forsyth
122274a4d8c2SCharles.Forsyth if(!(r->refahead.b[z] & bb))
122374a4d8c2SCharles.Forsyth break;
122474a4d8c2SCharles.Forsyth r1 = r->s2;
122574a4d8c2SCharles.Forsyth if(r1 != R)
122674a4d8c2SCharles.Forsyth if(r1->refbehind.b[z] & bb)
122774a4d8c2SCharles.Forsyth paint3(r1, bn, rb, rn);
122874a4d8c2SCharles.Forsyth r = r->s1;
122974a4d8c2SCharles.Forsyth if(r == R)
123074a4d8c2SCharles.Forsyth break;
123174a4d8c2SCharles.Forsyth if(r->act.b[z] & bb)
123274a4d8c2SCharles.Forsyth break;
123374a4d8c2SCharles.Forsyth if(!(r->refbehind.b[z] & bb))
123474a4d8c2SCharles.Forsyth break;
123574a4d8c2SCharles.Forsyth }
123674a4d8c2SCharles.Forsyth }
123774a4d8c2SCharles.Forsyth
123874a4d8c2SCharles.Forsyth void
addreg(Adr * a,int rn)123974a4d8c2SCharles.Forsyth addreg(Adr *a, int rn)
124074a4d8c2SCharles.Forsyth {
124174a4d8c2SCharles.Forsyth
124274a4d8c2SCharles.Forsyth a->sym = 0;
124374a4d8c2SCharles.Forsyth a->offset = 0;
124474a4d8c2SCharles.Forsyth a->type = rn;
124574a4d8c2SCharles.Forsyth }
124674a4d8c2SCharles.Forsyth
124774a4d8c2SCharles.Forsyth long
RtoB(int r)124874a4d8c2SCharles.Forsyth RtoB(int r)
124974a4d8c2SCharles.Forsyth {
125074a4d8c2SCharles.Forsyth
125174a4d8c2SCharles.Forsyth if(r < D_AX || r > D_DI)
125274a4d8c2SCharles.Forsyth return 0;
125374a4d8c2SCharles.Forsyth return 1L << (r-D_AX);
125474a4d8c2SCharles.Forsyth }
125574a4d8c2SCharles.Forsyth
125674a4d8c2SCharles.Forsyth int
BtoR(long b)125774a4d8c2SCharles.Forsyth BtoR(long b)
125874a4d8c2SCharles.Forsyth {
125974a4d8c2SCharles.Forsyth
126074a4d8c2SCharles.Forsyth b &= 0xffL;
126174a4d8c2SCharles.Forsyth if(b == 0)
126274a4d8c2SCharles.Forsyth return 0;
126374a4d8c2SCharles.Forsyth return bitno(b) + D_AX;
126474a4d8c2SCharles.Forsyth }
1265