xref: /plan9-contrib/sys/src/cmd/ic/reg.c (revision ce95e1b3727b9cb1c223ffbed69aff21a8ced255)
1*ce95e1b3SDavid du Colombier #include "gc.h"
2*ce95e1b3SDavid du Colombier 
3*ce95e1b3SDavid du Colombier void	addsplits(void);
4*ce95e1b3SDavid du Colombier 
5*ce95e1b3SDavid du Colombier Reg*
rega(void)6*ce95e1b3SDavid du Colombier rega(void)
7*ce95e1b3SDavid du Colombier {
8*ce95e1b3SDavid du Colombier 	Reg *r;
9*ce95e1b3SDavid du Colombier 
10*ce95e1b3SDavid du Colombier 	r = freer;
11*ce95e1b3SDavid du Colombier 	if(r == R) {
12*ce95e1b3SDavid du Colombier 		r = alloc(sizeof(*r));
13*ce95e1b3SDavid du Colombier 	} else
14*ce95e1b3SDavid du Colombier 		freer = r->link;
15*ce95e1b3SDavid du Colombier 
16*ce95e1b3SDavid du Colombier 	*r = zreg;
17*ce95e1b3SDavid du Colombier 	return r;
18*ce95e1b3SDavid du Colombier }
19*ce95e1b3SDavid du Colombier 
20*ce95e1b3SDavid du Colombier int
rcmp(void * a1,void * a2)21*ce95e1b3SDavid du Colombier rcmp(void *a1, void *a2)
22*ce95e1b3SDavid du Colombier {
23*ce95e1b3SDavid du Colombier 	Rgn *p1, *p2;
24*ce95e1b3SDavid du Colombier 	int c1, c2;
25*ce95e1b3SDavid du Colombier 
26*ce95e1b3SDavid du Colombier 	p1 = (Rgn*)a1;
27*ce95e1b3SDavid du Colombier 	p2 = (Rgn*)a2;
28*ce95e1b3SDavid du Colombier 	c1 = p2->cost;
29*ce95e1b3SDavid du Colombier 	c2 = p1->cost;
30*ce95e1b3SDavid du Colombier 	if(c1 -= c2)
31*ce95e1b3SDavid du Colombier 		return c1;
32*ce95e1b3SDavid du Colombier 	return p2->varno - p1->varno;
33*ce95e1b3SDavid du Colombier }
34*ce95e1b3SDavid du Colombier 
35*ce95e1b3SDavid du Colombier void
regopt(Prog * p)36*ce95e1b3SDavid du Colombier regopt(Prog *p)
37*ce95e1b3SDavid du Colombier {
38*ce95e1b3SDavid du Colombier 	Reg *r, *r1, *r2;
39*ce95e1b3SDavid du Colombier 	Prog *p1;
40*ce95e1b3SDavid du Colombier 	int i, z;
41*ce95e1b3SDavid du Colombier 	long initpc, val, npc;
42*ce95e1b3SDavid du Colombier 	ulong vreg;
43*ce95e1b3SDavid du Colombier 	Bits bit;
44*ce95e1b3SDavid du Colombier 	struct
45*ce95e1b3SDavid du Colombier 	{
46*ce95e1b3SDavid du Colombier 		long	m;
47*ce95e1b3SDavid du Colombier 		long	c;
48*ce95e1b3SDavid du Colombier 		Reg*	p;
49*ce95e1b3SDavid du Colombier 	} log5[6], *lp;
50*ce95e1b3SDavid du Colombier 
51*ce95e1b3SDavid du Colombier 	firstr = R;
52*ce95e1b3SDavid du Colombier 	lastr = R;
53*ce95e1b3SDavid du Colombier 	nvar = 0;
54*ce95e1b3SDavid du Colombier 	regbits = 0;
55*ce95e1b3SDavid du Colombier 	for(z=0; z<BITS; z++) {
56*ce95e1b3SDavid du Colombier 		externs.b[z] = 0;
57*ce95e1b3SDavid du Colombier 		params.b[z] = 0;
58*ce95e1b3SDavid du Colombier 		consts.b[z] = 0;
59*ce95e1b3SDavid du Colombier 		addrs.b[z] = 0;
60*ce95e1b3SDavid du Colombier 	}
61*ce95e1b3SDavid du Colombier 
62*ce95e1b3SDavid du Colombier 	/*
63*ce95e1b3SDavid du Colombier 	 * pass 1
64*ce95e1b3SDavid du Colombier 	 * build aux data structure
65*ce95e1b3SDavid du Colombier 	 * allocate pcs
66*ce95e1b3SDavid du Colombier 	 * find use and set of variables
67*ce95e1b3SDavid du Colombier 	 */
68*ce95e1b3SDavid du Colombier 	val = 5L * 5L * 5L * 5L * 5L;
69*ce95e1b3SDavid du Colombier 	lp = log5;
70*ce95e1b3SDavid du Colombier 	for(i=0; i<5; i++) {
71*ce95e1b3SDavid du Colombier 		lp->m = val;
72*ce95e1b3SDavid du Colombier 		lp->c = 0;
73*ce95e1b3SDavid du Colombier 		lp->p = R;
74*ce95e1b3SDavid du Colombier 		val /= 5L;
75*ce95e1b3SDavid du Colombier 		lp++;
76*ce95e1b3SDavid du Colombier 	}
77*ce95e1b3SDavid du Colombier 	val = 0;
78*ce95e1b3SDavid du Colombier 	for(; p != P; p = p->link) {
79*ce95e1b3SDavid du Colombier 		switch(p->as) {
80*ce95e1b3SDavid du Colombier 		case ADATA:
81*ce95e1b3SDavid du Colombier 		case AGLOBL:
82*ce95e1b3SDavid du Colombier 		case ANAME:
83*ce95e1b3SDavid du Colombier 		case ASIGNAME:
84*ce95e1b3SDavid du Colombier 			continue;
85*ce95e1b3SDavid du Colombier 		}
86*ce95e1b3SDavid du Colombier 		r = rega();
87*ce95e1b3SDavid du Colombier 		if(firstr == R) {
88*ce95e1b3SDavid du Colombier 			firstr = r;
89*ce95e1b3SDavid du Colombier 			lastr = r;
90*ce95e1b3SDavid du Colombier 		} else {
91*ce95e1b3SDavid du Colombier 			lastr->link = r;
92*ce95e1b3SDavid du Colombier 			r->p1 = lastr;
93*ce95e1b3SDavid du Colombier 			lastr->s1 = r;
94*ce95e1b3SDavid du Colombier 			lastr = r;
95*ce95e1b3SDavid du Colombier 		}
96*ce95e1b3SDavid du Colombier 		r->prog = p;
97*ce95e1b3SDavid du Colombier 		r->pc = val;
98*ce95e1b3SDavid du Colombier 		val++;
99*ce95e1b3SDavid du Colombier 
100*ce95e1b3SDavid du Colombier 		lp = log5;
101*ce95e1b3SDavid du Colombier 		for(i=0; i<5; i++) {
102*ce95e1b3SDavid du Colombier 			lp->c--;
103*ce95e1b3SDavid du Colombier 			if(lp->c <= 0) {
104*ce95e1b3SDavid du Colombier 				lp->c = lp->m;
105*ce95e1b3SDavid du Colombier 				if(lp->p != R)
106*ce95e1b3SDavid du Colombier 					lp->p->log5 = r;
107*ce95e1b3SDavid du Colombier 				lp->p = r;
108*ce95e1b3SDavid du Colombier 				(lp+1)->c = 0;
109*ce95e1b3SDavid du Colombier 				break;
110*ce95e1b3SDavid du Colombier 			}
111*ce95e1b3SDavid du Colombier 			lp++;
112*ce95e1b3SDavid du Colombier 		}
113*ce95e1b3SDavid du Colombier 
114*ce95e1b3SDavid du Colombier 		r1 = r->p1;
115*ce95e1b3SDavid du Colombier 		if(r1 != R)
116*ce95e1b3SDavid du Colombier 		switch(r1->prog->as) {
117*ce95e1b3SDavid du Colombier 		case ARET:
118*ce95e1b3SDavid du Colombier 		case AJMP:
119*ce95e1b3SDavid du Colombier 			r->p1 = R;
120*ce95e1b3SDavid du Colombier 			r1->s1 = R;
121*ce95e1b3SDavid du Colombier 		}
122*ce95e1b3SDavid du Colombier 
123*ce95e1b3SDavid du Colombier 		/*
124*ce95e1b3SDavid du Colombier 		 * left side always read
125*ce95e1b3SDavid du Colombier 		 */
126*ce95e1b3SDavid du Colombier 		bit = mkvar(&p->from, p->as==AMOVW || p->as==AMOV);
127*ce95e1b3SDavid du Colombier 		for(z=0; z<BITS; z++)
128*ce95e1b3SDavid du Colombier 			r->use1.b[z] |= bit.b[z];
129*ce95e1b3SDavid du Colombier 
130*ce95e1b3SDavid du Colombier 		/*
131*ce95e1b3SDavid du Colombier 		 * right side depends on opcode
132*ce95e1b3SDavid du Colombier 		 */
133*ce95e1b3SDavid du Colombier 		bit = mkvar(&p->to, 0);
134*ce95e1b3SDavid du Colombier 		if(bany(&bit))
135*ce95e1b3SDavid du Colombier 		switch(p->as) {
136*ce95e1b3SDavid du Colombier 		default:
137*ce95e1b3SDavid du Colombier 			diag(Z, "reg: unknown asop: %A", p->as);
138*ce95e1b3SDavid du Colombier 			break;
139*ce95e1b3SDavid du Colombier 
140*ce95e1b3SDavid du Colombier 		/*
141*ce95e1b3SDavid du Colombier 		 * right side write
142*ce95e1b3SDavid du Colombier 		 */
143*ce95e1b3SDavid du Colombier 		case ANOP:
144*ce95e1b3SDavid du Colombier 		case AMOVB:
145*ce95e1b3SDavid du Colombier 		case AMOVBU:
146*ce95e1b3SDavid du Colombier 		case AMOVH:
147*ce95e1b3SDavid du Colombier 		case AMOVHU:
148*ce95e1b3SDavid du Colombier 		case AMOVW:
149*ce95e1b3SDavid du Colombier 		case AMOV:
150*ce95e1b3SDavid du Colombier 		case AMOVF:
151*ce95e1b3SDavid du Colombier 		case AMOVD:
152*ce95e1b3SDavid du Colombier 			for(z=0; z<BITS; z++)
153*ce95e1b3SDavid du Colombier 				r->set.b[z] |= bit.b[z];
154*ce95e1b3SDavid du Colombier 			break;
155*ce95e1b3SDavid du Colombier 
156*ce95e1b3SDavid du Colombier 		/*
157*ce95e1b3SDavid du Colombier 		 * funny
158*ce95e1b3SDavid du Colombier 		 */
159*ce95e1b3SDavid du Colombier 		case AJAL:
160*ce95e1b3SDavid du Colombier 			for(z=0; z<BITS; z++)
161*ce95e1b3SDavid du Colombier 				addrs.b[z] |= bit.b[z];
162*ce95e1b3SDavid du Colombier 			break;
163*ce95e1b3SDavid du Colombier 		}
164*ce95e1b3SDavid du Colombier 	}
165*ce95e1b3SDavid du Colombier 	if(firstr == R)
166*ce95e1b3SDavid du Colombier 		return;
167*ce95e1b3SDavid du Colombier 	initpc = pc - val;
168*ce95e1b3SDavid du Colombier 	npc = val;
169*ce95e1b3SDavid du Colombier 
170*ce95e1b3SDavid du Colombier 	/*
171*ce95e1b3SDavid du Colombier 	 * pass 2
172*ce95e1b3SDavid du Colombier 	 * turn branch references to pointers
173*ce95e1b3SDavid du Colombier 	 * build back pointers
174*ce95e1b3SDavid du Colombier 	 */
175*ce95e1b3SDavid du Colombier 	for(r = firstr; r != R; r = r->link) {
176*ce95e1b3SDavid du Colombier 		p = r->prog;
177*ce95e1b3SDavid du Colombier 		if(p->to.type == D_BRANCH) {
178*ce95e1b3SDavid du Colombier 			val = p->to.offset - initpc;
179*ce95e1b3SDavid du Colombier 			r1 = firstr;
180*ce95e1b3SDavid du Colombier 			while(r1 != R) {
181*ce95e1b3SDavid du Colombier 				r2 = r1->log5;
182*ce95e1b3SDavid du Colombier 				if(r2 != R && val >= r2->pc) {
183*ce95e1b3SDavid du Colombier 					r1 = r2;
184*ce95e1b3SDavid du Colombier 					continue;
185*ce95e1b3SDavid du Colombier 				}
186*ce95e1b3SDavid du Colombier 				if(r1->pc == val)
187*ce95e1b3SDavid du Colombier 					break;
188*ce95e1b3SDavid du Colombier 				r1 = r1->link;
189*ce95e1b3SDavid du Colombier 			}
190*ce95e1b3SDavid du Colombier 			if(r1 == R) {
191*ce95e1b3SDavid du Colombier 				nearln = p->lineno;
192*ce95e1b3SDavid du Colombier 				diag(Z, "ref not found\n%P", p);
193*ce95e1b3SDavid du Colombier 				continue;
194*ce95e1b3SDavid du Colombier 			}
195*ce95e1b3SDavid du Colombier 			if(r1 == r) {
196*ce95e1b3SDavid du Colombier 				nearln = p->lineno;
197*ce95e1b3SDavid du Colombier 				diag(Z, "ref to self\n%P", p);
198*ce95e1b3SDavid du Colombier 				continue;
199*ce95e1b3SDavid du Colombier 			}
200*ce95e1b3SDavid du Colombier 			r->s2 = r1;
201*ce95e1b3SDavid du Colombier 			r->p2link = r1->p2;
202*ce95e1b3SDavid du Colombier 			r1->p2 = r;
203*ce95e1b3SDavid du Colombier 		}
204*ce95e1b3SDavid du Colombier 	}
205*ce95e1b3SDavid du Colombier 	if(debug['R']) {
206*ce95e1b3SDavid du Colombier 		p = firstr->prog;
207*ce95e1b3SDavid du Colombier 		print("\n%L %D\n", p->lineno, &p->from);
208*ce95e1b3SDavid du Colombier 	}
209*ce95e1b3SDavid du Colombier 
210*ce95e1b3SDavid du Colombier 	/*
211*ce95e1b3SDavid du Colombier 	 * pass 2.5
212*ce95e1b3SDavid du Colombier 	 * find looping structure
213*ce95e1b3SDavid du Colombier 	 */
214*ce95e1b3SDavid du Colombier 	for(r = firstr; r != R; r = r->link)
215*ce95e1b3SDavid du Colombier 		r->active = 0;
216*ce95e1b3SDavid du Colombier 	change = 0;
217*ce95e1b3SDavid du Colombier 	loopit(firstr, npc);
218*ce95e1b3SDavid du Colombier 
219*ce95e1b3SDavid du Colombier 	/*
220*ce95e1b3SDavid du Colombier 	 * pass 3
221*ce95e1b3SDavid du Colombier 	 * iterate propagating usage
222*ce95e1b3SDavid du Colombier 	 * 	back until flow graph is complete
223*ce95e1b3SDavid du Colombier 	 */
224*ce95e1b3SDavid du Colombier loop1:
225*ce95e1b3SDavid du Colombier 	change = 0;
226*ce95e1b3SDavid du Colombier 	for(r = firstr; r != R; r = r->link)
227*ce95e1b3SDavid du Colombier 		r->active = 0;
228*ce95e1b3SDavid du Colombier 	for(r = firstr; r != R; r = r->link)
229*ce95e1b3SDavid du Colombier 		if(r->prog->as == ARET)
230*ce95e1b3SDavid du Colombier 			prop(r, zbits, zbits);
231*ce95e1b3SDavid du Colombier loop11:
232*ce95e1b3SDavid du Colombier 	/* pick up unreachable code */
233*ce95e1b3SDavid du Colombier 	i = 0;
234*ce95e1b3SDavid du Colombier 	for(r = firstr; r != R; r = r1) {
235*ce95e1b3SDavid du Colombier 		r1 = r->link;
236*ce95e1b3SDavid du Colombier 		if(r1 && r1->active && !r->active) {
237*ce95e1b3SDavid du Colombier 			prop(r, zbits, zbits);
238*ce95e1b3SDavid du Colombier 			i = 1;
239*ce95e1b3SDavid du Colombier 		}
240*ce95e1b3SDavid du Colombier 	}
241*ce95e1b3SDavid du Colombier 	if(i)
242*ce95e1b3SDavid du Colombier 		goto loop11;
243*ce95e1b3SDavid du Colombier 	if(change)
244*ce95e1b3SDavid du Colombier 		goto loop1;
245*ce95e1b3SDavid du Colombier 
246*ce95e1b3SDavid du Colombier 
247*ce95e1b3SDavid du Colombier 	/*
248*ce95e1b3SDavid du Colombier 	 * pass 4
249*ce95e1b3SDavid du Colombier 	 * iterate propagating register/variable synchrony
250*ce95e1b3SDavid du Colombier 	 * 	forward until graph is complete
251*ce95e1b3SDavid du Colombier 	 */
252*ce95e1b3SDavid du Colombier loop2:
253*ce95e1b3SDavid du Colombier 	change = 0;
254*ce95e1b3SDavid du Colombier 	for(r = firstr; r != R; r = r->link)
255*ce95e1b3SDavid du Colombier 		r->active = 0;
256*ce95e1b3SDavid du Colombier 	synch(firstr, zbits);
257*ce95e1b3SDavid du Colombier 	if(change)
258*ce95e1b3SDavid du Colombier 		goto loop2;
259*ce95e1b3SDavid du Colombier 
260*ce95e1b3SDavid du Colombier 	addsplits();
261*ce95e1b3SDavid du Colombier 
262*ce95e1b3SDavid du Colombier 	if(debug['R'] && debug['v']) {
263*ce95e1b3SDavid du Colombier 		print("\nprop structure:\n");
264*ce95e1b3SDavid du Colombier 		for(r = firstr; r != R; r = r->link) {
265*ce95e1b3SDavid du Colombier 			print("%ld:%P", r->loop, r->prog);
266*ce95e1b3SDavid du Colombier 			for(z=0; z<BITS; z++)
267*ce95e1b3SDavid du Colombier 				bit.b[z] = r->set.b[z] |
268*ce95e1b3SDavid du Colombier 					r->refahead.b[z] | r->calahead.b[z] |
269*ce95e1b3SDavid du Colombier 					r->refbehind.b[z] | r->calbehind.b[z] |
270*ce95e1b3SDavid du Colombier 					r->use1.b[z] | r->use2.b[z];
271*ce95e1b3SDavid du Colombier 			if(bany(&bit)) {
272*ce95e1b3SDavid du Colombier 				print("\t");
273*ce95e1b3SDavid du Colombier 				if(bany(&r->use1))
274*ce95e1b3SDavid du Colombier 					print(" u1=%B", r->use1);
275*ce95e1b3SDavid du Colombier 				if(bany(&r->use2))
276*ce95e1b3SDavid du Colombier 					print(" u2=%B", r->use2);
277*ce95e1b3SDavid du Colombier 				if(bany(&r->set))
278*ce95e1b3SDavid du Colombier 					print(" st=%B", r->set);
279*ce95e1b3SDavid du Colombier 				if(bany(&r->refahead))
280*ce95e1b3SDavid du Colombier 					print(" ra=%B", r->refahead);
281*ce95e1b3SDavid du Colombier 				if(bany(&r->calahead))
282*ce95e1b3SDavid du Colombier 					print(" ca=%B", r->calahead);
283*ce95e1b3SDavid du Colombier 				if(bany(&r->refbehind))
284*ce95e1b3SDavid du Colombier 					print(" rb=%B", r->refbehind);
285*ce95e1b3SDavid du Colombier 				if(bany(&r->calbehind))
286*ce95e1b3SDavid du Colombier 					print(" cb=%B", r->calbehind);
287*ce95e1b3SDavid du Colombier 				if(bany(&r->regdiff))
288*ce95e1b3SDavid du Colombier 					print(" rd=%B", r->regdiff);
289*ce95e1b3SDavid du Colombier 			}
290*ce95e1b3SDavid du Colombier 			print("\n");
291*ce95e1b3SDavid du Colombier 		}
292*ce95e1b3SDavid du Colombier 	}
293*ce95e1b3SDavid du Colombier 
294*ce95e1b3SDavid du Colombier 	/*
295*ce95e1b3SDavid du Colombier 	 * pass 5
296*ce95e1b3SDavid du Colombier 	 * isolate regions
297*ce95e1b3SDavid du Colombier 	 * calculate costs (paint1)
298*ce95e1b3SDavid du Colombier 	 */
299*ce95e1b3SDavid du Colombier 	r = firstr;
300*ce95e1b3SDavid du Colombier 	if(r) {
301*ce95e1b3SDavid du Colombier 		for(z=0; z<BITS; z++)
302*ce95e1b3SDavid du Colombier 			bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
303*ce95e1b3SDavid du Colombier 			  ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
304*ce95e1b3SDavid du Colombier 		if(bany(&bit)) {
305*ce95e1b3SDavid du Colombier 			nearln = r->prog->lineno;
306*ce95e1b3SDavid du Colombier 			warn(Z, "used and not set: %B", bit);
307*ce95e1b3SDavid du Colombier 			if(debug['R'] && !debug['w'])
308*ce95e1b3SDavid du Colombier 				print("used and not set: %B\n", bit);
309*ce95e1b3SDavid du Colombier 		}
310*ce95e1b3SDavid du Colombier 	}
311*ce95e1b3SDavid du Colombier 
312*ce95e1b3SDavid du Colombier 	for(r = firstr; r != R; r = r->link)
313*ce95e1b3SDavid du Colombier 		r->act = zbits;
314*ce95e1b3SDavid du Colombier 	rgp = region;
315*ce95e1b3SDavid du Colombier 	nregion = 0;
316*ce95e1b3SDavid du Colombier 	for(r = firstr; r != R; r = r->link) {
317*ce95e1b3SDavid du Colombier 		for(z=0; z<BITS; z++)
318*ce95e1b3SDavid du Colombier 			bit.b[z] = r->set.b[z] &
319*ce95e1b3SDavid du Colombier 			  ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
320*ce95e1b3SDavid du Colombier 		if(bany(&bit)) {
321*ce95e1b3SDavid du Colombier 			nearln = r->prog->lineno;
322*ce95e1b3SDavid du Colombier 			warn(Z, "set and not used: %B", bit);
323*ce95e1b3SDavid du Colombier 			if(debug['R'])
324*ce95e1b3SDavid du Colombier 				print("set and not used: %B\n", bit);
325*ce95e1b3SDavid du Colombier 			excise(r);
326*ce95e1b3SDavid du Colombier 		}
327*ce95e1b3SDavid du Colombier 		for(z=0; z<BITS; z++)
328*ce95e1b3SDavid du Colombier 			bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
329*ce95e1b3SDavid du Colombier 		while(bany(&bit)) {
330*ce95e1b3SDavid du Colombier 			i = bnum(bit);
331*ce95e1b3SDavid du Colombier 			rgp->enter = r;
332*ce95e1b3SDavid du Colombier 			rgp->varno = i;
333*ce95e1b3SDavid du Colombier 			change = 0;
334*ce95e1b3SDavid du Colombier 			if(debug['R'] && debug['v'])
335*ce95e1b3SDavid du Colombier 				print("\n");
336*ce95e1b3SDavid du Colombier 			paint1(r, i);
337*ce95e1b3SDavid du Colombier 			bit.b[i/32] &= ~(1L<<(i%32));
338*ce95e1b3SDavid du Colombier 			if(change <= 0) {
339*ce95e1b3SDavid du Colombier 				if(debug['R'])
340*ce95e1b3SDavid du Colombier 					print("%L $%d: %B\n",
341*ce95e1b3SDavid du Colombier 						r->prog->lineno, change, blsh(i));
342*ce95e1b3SDavid du Colombier 				continue;
343*ce95e1b3SDavid du Colombier 			}
344*ce95e1b3SDavid du Colombier 			rgp->cost = change;
345*ce95e1b3SDavid du Colombier 			nregion++;
346*ce95e1b3SDavid du Colombier 			if(nregion >= NRGN) {
347*ce95e1b3SDavid du Colombier 				warn(Z, "too many regions");
348*ce95e1b3SDavid du Colombier 				goto brk;
349*ce95e1b3SDavid du Colombier 			}
350*ce95e1b3SDavid du Colombier 			rgp++;
351*ce95e1b3SDavid du Colombier 		}
352*ce95e1b3SDavid du Colombier 	}
353*ce95e1b3SDavid du Colombier brk:
354*ce95e1b3SDavid du Colombier 	qsort(region, nregion, sizeof(region[0]), rcmp);
355*ce95e1b3SDavid du Colombier 
356*ce95e1b3SDavid du Colombier 	/*
357*ce95e1b3SDavid du Colombier 	 * pass 6
358*ce95e1b3SDavid du Colombier 	 * determine used registers (paint2)
359*ce95e1b3SDavid du Colombier 	 * replace code (paint3)
360*ce95e1b3SDavid du Colombier 	 */
361*ce95e1b3SDavid du Colombier 	rgp = region;
362*ce95e1b3SDavid du Colombier 	for(i=0; i<nregion; i++) {
363*ce95e1b3SDavid du Colombier 		bit = blsh(rgp->varno);
364*ce95e1b3SDavid du Colombier 		vreg = paint2(rgp->enter, rgp->varno);
365*ce95e1b3SDavid du Colombier 		vreg = allreg(vreg, rgp);
366*ce95e1b3SDavid du Colombier 		if(debug['R']) {
367*ce95e1b3SDavid du Colombier 			if(rgp->regno >= NREG)
368*ce95e1b3SDavid du Colombier 				print("%L $%d F%d: %B\n",
369*ce95e1b3SDavid du Colombier 					rgp->enter->prog->lineno,
370*ce95e1b3SDavid du Colombier 					rgp->cost,
371*ce95e1b3SDavid du Colombier 					rgp->regno-NREG,
372*ce95e1b3SDavid du Colombier 					bit);
373*ce95e1b3SDavid du Colombier 			else
374*ce95e1b3SDavid du Colombier 				print("%L $%d R%d: %B\n",
375*ce95e1b3SDavid du Colombier 					rgp->enter->prog->lineno,
376*ce95e1b3SDavid du Colombier 					rgp->cost,
377*ce95e1b3SDavid du Colombier 					rgp->regno,
378*ce95e1b3SDavid du Colombier 					bit);
379*ce95e1b3SDavid du Colombier 		}
380*ce95e1b3SDavid du Colombier 		if(rgp->regno != 0)
381*ce95e1b3SDavid du Colombier 			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
382*ce95e1b3SDavid du Colombier 		rgp++;
383*ce95e1b3SDavid du Colombier 	}
384*ce95e1b3SDavid du Colombier 	/*
385*ce95e1b3SDavid du Colombier 	 * pass 7
386*ce95e1b3SDavid du Colombier 	 * peep-hole on basic block
387*ce95e1b3SDavid du Colombier 	 */
388*ce95e1b3SDavid du Colombier 	if(!debug['R'] || debug['P'])
389*ce95e1b3SDavid du Colombier 		peep();
390*ce95e1b3SDavid du Colombier 
391*ce95e1b3SDavid du Colombier 	/*
392*ce95e1b3SDavid du Colombier 	 * pass 8
393*ce95e1b3SDavid du Colombier 	 * recalculate pc
394*ce95e1b3SDavid du Colombier 	 */
395*ce95e1b3SDavid du Colombier 	val = initpc;
396*ce95e1b3SDavid du Colombier 	for(r = firstr; r != R; r = r1) {
397*ce95e1b3SDavid du Colombier 		r->pc = val;
398*ce95e1b3SDavid du Colombier 		p = r->prog;
399*ce95e1b3SDavid du Colombier 		p1 = P;
400*ce95e1b3SDavid du Colombier 		r1 = r->link;
401*ce95e1b3SDavid du Colombier 		if(r1 != R)
402*ce95e1b3SDavid du Colombier 			p1 = r1->prog;
403*ce95e1b3SDavid du Colombier 		for(; p != p1; p = p->link) {
404*ce95e1b3SDavid du Colombier 			switch(p->as) {
405*ce95e1b3SDavid du Colombier 			default:
406*ce95e1b3SDavid du Colombier 				val++;
407*ce95e1b3SDavid du Colombier 				break;
408*ce95e1b3SDavid du Colombier 
409*ce95e1b3SDavid du Colombier 			case ANOP:
410*ce95e1b3SDavid du Colombier 			case ADATA:
411*ce95e1b3SDavid du Colombier 			case AGLOBL:
412*ce95e1b3SDavid du Colombier 			case ANAME:
413*ce95e1b3SDavid du Colombier 			case ASIGNAME:
414*ce95e1b3SDavid du Colombier 				break;
415*ce95e1b3SDavid du Colombier 			}
416*ce95e1b3SDavid du Colombier 		}
417*ce95e1b3SDavid du Colombier 	}
418*ce95e1b3SDavid du Colombier 	pc = val;
419*ce95e1b3SDavid du Colombier 
420*ce95e1b3SDavid du Colombier 	/*
421*ce95e1b3SDavid du Colombier 	 * fix up branches
422*ce95e1b3SDavid du Colombier 	 */
423*ce95e1b3SDavid du Colombier 	if(debug['R'])
424*ce95e1b3SDavid du Colombier 		if(bany(&addrs))
425*ce95e1b3SDavid du Colombier 			print("addrs: %B\n", addrs);
426*ce95e1b3SDavid du Colombier 
427*ce95e1b3SDavid du Colombier 	r1 = 0; /* set */
428*ce95e1b3SDavid du Colombier 	for(r = firstr; r != R; r = r->link) {
429*ce95e1b3SDavid du Colombier 		p = r->prog;
430*ce95e1b3SDavid du Colombier 		if(p->to.type == D_BRANCH)
431*ce95e1b3SDavid du Colombier 			p->to.offset = r->s2->pc;
432*ce95e1b3SDavid du Colombier 		r1 = r;
433*ce95e1b3SDavid du Colombier 	}
434*ce95e1b3SDavid du Colombier 
435*ce95e1b3SDavid du Colombier 	/*
436*ce95e1b3SDavid du Colombier 	 * last pass
437*ce95e1b3SDavid du Colombier 	 * fix unsigned stores (needed as type hint in pass 6)
438*ce95e1b3SDavid du Colombier 	 * eliminate nops
439*ce95e1b3SDavid du Colombier 	 * free aux structures
440*ce95e1b3SDavid du Colombier 	 */
441*ce95e1b3SDavid du Colombier 	for(p = firstr->prog; p != P; p = p->link){
442*ce95e1b3SDavid du Colombier 		if(p->to.type == D_OREG){
443*ce95e1b3SDavid du Colombier 			switch(p->as){
444*ce95e1b3SDavid du Colombier 			case AMOVBU:
445*ce95e1b3SDavid du Colombier 				p->as = AMOVB;
446*ce95e1b3SDavid du Colombier 				break;
447*ce95e1b3SDavid du Colombier 			case AMOVHU:
448*ce95e1b3SDavid du Colombier 				p->as = AMOVH;
449*ce95e1b3SDavid du Colombier 				break;
450*ce95e1b3SDavid du Colombier 			}
451*ce95e1b3SDavid du Colombier 		}
452*ce95e1b3SDavid du Colombier 		while(p->link && p->link->as == ANOP)
453*ce95e1b3SDavid du Colombier 			p->link = p->link->link;
454*ce95e1b3SDavid du Colombier 	}
455*ce95e1b3SDavid du Colombier 	if(r1 != R) {
456*ce95e1b3SDavid du Colombier 		r1->link = freer;
457*ce95e1b3SDavid du Colombier 		freer = firstr;
458*ce95e1b3SDavid du Colombier 	}
459*ce95e1b3SDavid du Colombier }
460*ce95e1b3SDavid du Colombier 
461*ce95e1b3SDavid du Colombier void
addsplits(void)462*ce95e1b3SDavid du Colombier addsplits(void)
463*ce95e1b3SDavid du Colombier {
464*ce95e1b3SDavid du Colombier 	Reg *r, *r1;
465*ce95e1b3SDavid du Colombier 	int z, i;
466*ce95e1b3SDavid du Colombier 	Bits bit;
467*ce95e1b3SDavid du Colombier 
468*ce95e1b3SDavid du Colombier 	for(r = firstr; r != R; r = r->link) {
469*ce95e1b3SDavid du Colombier 		if(r->loop > 1)
470*ce95e1b3SDavid du Colombier 			continue;
471*ce95e1b3SDavid du Colombier 		if(r->prog->as == AJAL)
472*ce95e1b3SDavid du Colombier 			continue;
473*ce95e1b3SDavid du Colombier 		for(r1 = r->p2; r1 != R; r1 = r1->p2link) {
474*ce95e1b3SDavid du Colombier 			if(r1->loop <= 1)
475*ce95e1b3SDavid du Colombier 				continue;
476*ce95e1b3SDavid du Colombier 			for(z=0; z<BITS; z++)
477*ce95e1b3SDavid du Colombier 				bit.b[z] = r1->calbehind.b[z] &
478*ce95e1b3SDavid du Colombier 					(r->refahead.b[z] | r->use1.b[z] | r->use2.b[z]) &
479*ce95e1b3SDavid du Colombier 					~(r->calahead.b[z] & addrs.b[z]);
480*ce95e1b3SDavid du Colombier 			while(bany(&bit)) {
481*ce95e1b3SDavid du Colombier 				i = bnum(bit);
482*ce95e1b3SDavid du Colombier 				bit.b[i/32] &= ~(1L << (i%32));
483*ce95e1b3SDavid du Colombier 			}
484*ce95e1b3SDavid du Colombier 		}
485*ce95e1b3SDavid du Colombier 	}
486*ce95e1b3SDavid du Colombier }
487*ce95e1b3SDavid du Colombier 
488*ce95e1b3SDavid du Colombier /*
489*ce95e1b3SDavid du Colombier  * add mov b,rn
490*ce95e1b3SDavid du Colombier  * just after r
491*ce95e1b3SDavid du Colombier  */
492*ce95e1b3SDavid du Colombier void
addmove(Reg * r,int bn,int rn,int f)493*ce95e1b3SDavid du Colombier addmove(Reg *r, int bn, int rn, int f)
494*ce95e1b3SDavid du Colombier {
495*ce95e1b3SDavid du Colombier 	Prog *p, *p1;
496*ce95e1b3SDavid du Colombier 	Adr *a;
497*ce95e1b3SDavid du Colombier 	Var *v;
498*ce95e1b3SDavid du Colombier 
499*ce95e1b3SDavid du Colombier 	p1 = alloc(sizeof(*p1));
500*ce95e1b3SDavid du Colombier 	*p1 = zprog;
501*ce95e1b3SDavid du Colombier 	p = r->prog;
502*ce95e1b3SDavid du Colombier 
503*ce95e1b3SDavid du Colombier 	p1->link = p->link;
504*ce95e1b3SDavid du Colombier 	p->link = p1;
505*ce95e1b3SDavid du Colombier 	p1->lineno = p->lineno;
506*ce95e1b3SDavid du Colombier 
507*ce95e1b3SDavid du Colombier 	v = var + bn;
508*ce95e1b3SDavid du Colombier 
509*ce95e1b3SDavid du Colombier 	a = &p1->to;
510*ce95e1b3SDavid du Colombier 	a->sym = v->sym;
511*ce95e1b3SDavid du Colombier 	a->name = v->name;
512*ce95e1b3SDavid du Colombier 	a->offset = v->offset;
513*ce95e1b3SDavid du Colombier 	a->etype = v->etype;
514*ce95e1b3SDavid du Colombier 	a->type = D_OREG;
515*ce95e1b3SDavid du Colombier 	if(a->etype == TARRAY || a->sym == S)
516*ce95e1b3SDavid du Colombier 		a->type = D_CONST;
517*ce95e1b3SDavid du Colombier 
518*ce95e1b3SDavid du Colombier 	p1->as = AMOVW;
519*ce95e1b3SDavid du Colombier 	if(v->etype == TCHAR || v->etype == TUCHAR)
520*ce95e1b3SDavid du Colombier 		p1->as = AMOVB;
521*ce95e1b3SDavid du Colombier 	if(v->etype == TSHORT || v->etype == TUSHORT)
522*ce95e1b3SDavid du Colombier 		p1->as = AMOVH;
523*ce95e1b3SDavid du Colombier 	if(v->etype == TFLOAT)
524*ce95e1b3SDavid du Colombier 		p1->as = AMOVF;
525*ce95e1b3SDavid du Colombier 	if(v->etype == TDOUBLE)
526*ce95e1b3SDavid du Colombier 		p1->as = AMOVD;
527*ce95e1b3SDavid du Colombier 	if(thechar == 'j')
528*ce95e1b3SDavid du Colombier 	if(v->etype == TVLONG || v->etype == TUVLONG || v->etype == TIND)
529*ce95e1b3SDavid du Colombier 		p1->as = AMOV;
530*ce95e1b3SDavid du Colombier 
531*ce95e1b3SDavid du Colombier 	p1->from.type = D_REG;
532*ce95e1b3SDavid du Colombier 	p1->from.reg = rn;
533*ce95e1b3SDavid du Colombier 	if(rn >= NREG) {
534*ce95e1b3SDavid du Colombier 		p1->from.type = D_FREG;
535*ce95e1b3SDavid du Colombier 		p1->from.reg = rn-NREG;
536*ce95e1b3SDavid du Colombier 	}
537*ce95e1b3SDavid du Colombier 	if(!f) {
538*ce95e1b3SDavid du Colombier 		p1->from = *a;
539*ce95e1b3SDavid du Colombier 		*a = zprog.from;
540*ce95e1b3SDavid du Colombier 		a->type = D_REG;
541*ce95e1b3SDavid du Colombier 		a->reg = rn;
542*ce95e1b3SDavid du Colombier 		if(rn >= NREG) {
543*ce95e1b3SDavid du Colombier 			a->type = D_FREG;
544*ce95e1b3SDavid du Colombier 			a->reg = rn-NREG;
545*ce95e1b3SDavid du Colombier 		}
546*ce95e1b3SDavid du Colombier 		if(v->etype == TUCHAR)
547*ce95e1b3SDavid du Colombier 			p1->as = AMOVBU;
548*ce95e1b3SDavid du Colombier 		if(v->etype == TUSHORT)
549*ce95e1b3SDavid du Colombier 			p1->as = AMOVHU;
550*ce95e1b3SDavid du Colombier 	}
551*ce95e1b3SDavid du Colombier 	if(debug['R'])
552*ce95e1b3SDavid du Colombier 		print("%P\t.a%P\n", p, p1);
553*ce95e1b3SDavid du Colombier }
554*ce95e1b3SDavid du Colombier 
555*ce95e1b3SDavid du Colombier Bits
mkvar(Adr * a,int docon)556*ce95e1b3SDavid du Colombier mkvar(Adr *a, int docon)
557*ce95e1b3SDavid du Colombier {
558*ce95e1b3SDavid du Colombier 	Var *v;
559*ce95e1b3SDavid du Colombier 	int i, t, n, et, z;
560*ce95e1b3SDavid du Colombier 	long o;
561*ce95e1b3SDavid du Colombier 	Bits bit;
562*ce95e1b3SDavid du Colombier 	Sym *s;
563*ce95e1b3SDavid du Colombier 
564*ce95e1b3SDavid du Colombier 	t = a->type;
565*ce95e1b3SDavid du Colombier 	if(t == D_REG && a->reg != NREG)
566*ce95e1b3SDavid du Colombier 		regbits |= RtoB(a->reg);
567*ce95e1b3SDavid du Colombier 	if(t == D_FREG && a->reg != NREG)
568*ce95e1b3SDavid du Colombier 		regbits |= FtoB(a->reg);
569*ce95e1b3SDavid du Colombier 	s = a->sym;
570*ce95e1b3SDavid du Colombier 	o = a->offset;
571*ce95e1b3SDavid du Colombier 	et = a->etype;
572*ce95e1b3SDavid du Colombier 	if(s == S) {
573*ce95e1b3SDavid du Colombier 		if(t != D_CONST || !docon || a->reg != NREG)
574*ce95e1b3SDavid du Colombier 			goto none;
575*ce95e1b3SDavid du Colombier 		et = TLONG;
576*ce95e1b3SDavid du Colombier 	}
577*ce95e1b3SDavid du Colombier 	if(t == D_CONST) {
578*ce95e1b3SDavid du Colombier 		if(s == S && sval(o))
579*ce95e1b3SDavid du Colombier 			goto none;
580*ce95e1b3SDavid du Colombier 	}
581*ce95e1b3SDavid du Colombier 
582*ce95e1b3SDavid du Colombier 	n = a->name;
583*ce95e1b3SDavid du Colombier 	v = var;
584*ce95e1b3SDavid du Colombier 	for(i=0; i<nvar; i++) {
585*ce95e1b3SDavid du Colombier 		if(s == v->sym)
586*ce95e1b3SDavid du Colombier 		if(n == v->name)
587*ce95e1b3SDavid du Colombier 		if(o == v->offset)
588*ce95e1b3SDavid du Colombier 			goto out;
589*ce95e1b3SDavid du Colombier 		v++;
590*ce95e1b3SDavid du Colombier 	}
591*ce95e1b3SDavid du Colombier 	if(s)
592*ce95e1b3SDavid du Colombier 		if(s->name[0] == '.')
593*ce95e1b3SDavid du Colombier 			goto none;
594*ce95e1b3SDavid du Colombier 	if(nvar >= NVAR) {
595*ce95e1b3SDavid du Colombier 		if(debug['w'] > 1 && s)
596*ce95e1b3SDavid du Colombier 			warn(Z, "variable not optimized: %s", s->name);
597*ce95e1b3SDavid du Colombier 		goto none;
598*ce95e1b3SDavid du Colombier 	}
599*ce95e1b3SDavid du Colombier 	i = nvar;
600*ce95e1b3SDavid du Colombier 	nvar++;
601*ce95e1b3SDavid du Colombier 	v = &var[i];
602*ce95e1b3SDavid du Colombier 	v->sym = s;
603*ce95e1b3SDavid du Colombier 	v->offset = o;
604*ce95e1b3SDavid du Colombier 	v->etype = et;
605*ce95e1b3SDavid du Colombier 	v->name = n;
606*ce95e1b3SDavid du Colombier 	if(debug['R'])
607*ce95e1b3SDavid du Colombier 		print("bit=%2d et=%2d %D\n", i, et, a);
608*ce95e1b3SDavid du Colombier out:
609*ce95e1b3SDavid du Colombier 	bit = blsh(i);
610*ce95e1b3SDavid du Colombier 	if(n == D_EXTERN || n == D_STATIC)
611*ce95e1b3SDavid du Colombier 		for(z=0; z<BITS; z++)
612*ce95e1b3SDavid du Colombier 			externs.b[z] |= bit.b[z];
613*ce95e1b3SDavid du Colombier 	if(n == D_PARAM)
614*ce95e1b3SDavid du Colombier 		for(z=0; z<BITS; z++)
615*ce95e1b3SDavid du Colombier 			params.b[z] |= bit.b[z];
616*ce95e1b3SDavid du Colombier 	if(v->etype != et || !typechlpfd[et])	/* funny punning */
617*ce95e1b3SDavid du Colombier 		for(z=0; z<BITS; z++)
618*ce95e1b3SDavid du Colombier 			addrs.b[z] |= bit.b[z];
619*ce95e1b3SDavid du Colombier 	if(t == D_CONST) {
620*ce95e1b3SDavid du Colombier 		if(s == S) {
621*ce95e1b3SDavid du Colombier 			for(z=0; z<BITS; z++)
622*ce95e1b3SDavid du Colombier 				consts.b[z] |= bit.b[z];
623*ce95e1b3SDavid du Colombier 			return bit;
624*ce95e1b3SDavid du Colombier 		}
625*ce95e1b3SDavid du Colombier 		if(et != TARRAY)
626*ce95e1b3SDavid du Colombier 			for(z=0; z<BITS; z++)
627*ce95e1b3SDavid du Colombier 				addrs.b[z] |= bit.b[z];
628*ce95e1b3SDavid du Colombier 		for(z=0; z<BITS; z++)
629*ce95e1b3SDavid du Colombier 			params.b[z] |= bit.b[z];
630*ce95e1b3SDavid du Colombier 		return bit;
631*ce95e1b3SDavid du Colombier 	}
632*ce95e1b3SDavid du Colombier 	if(t == D_OREG)
633*ce95e1b3SDavid du Colombier 		return bit;
634*ce95e1b3SDavid du Colombier 
635*ce95e1b3SDavid du Colombier none:
636*ce95e1b3SDavid du Colombier 	return zbits;
637*ce95e1b3SDavid du Colombier }
638*ce95e1b3SDavid du Colombier 
639*ce95e1b3SDavid du Colombier void
prop(Reg * r,Bits ref,Bits cal)640*ce95e1b3SDavid du Colombier prop(Reg *r, Bits ref, Bits cal)
641*ce95e1b3SDavid du Colombier {
642*ce95e1b3SDavid du Colombier 	Reg *r1, *r2;
643*ce95e1b3SDavid du Colombier 	int z;
644*ce95e1b3SDavid du Colombier 
645*ce95e1b3SDavid du Colombier 	for(r1 = r; r1 != R; r1 = r1->p1) {
646*ce95e1b3SDavid du Colombier 		for(z=0; z<BITS; z++) {
647*ce95e1b3SDavid du Colombier 			ref.b[z] |= r1->refahead.b[z];
648*ce95e1b3SDavid du Colombier 			if(ref.b[z] != r1->refahead.b[z]) {
649*ce95e1b3SDavid du Colombier 				r1->refahead.b[z] = ref.b[z];
650*ce95e1b3SDavid du Colombier 				change++;
651*ce95e1b3SDavid du Colombier 			}
652*ce95e1b3SDavid du Colombier 			cal.b[z] |= r1->calahead.b[z];
653*ce95e1b3SDavid du Colombier 			if(cal.b[z] != r1->calahead.b[z]) {
654*ce95e1b3SDavid du Colombier 				r1->calahead.b[z] = cal.b[z];
655*ce95e1b3SDavid du Colombier 				change++;
656*ce95e1b3SDavid du Colombier 			}
657*ce95e1b3SDavid du Colombier 		}
658*ce95e1b3SDavid du Colombier 		switch(r1->prog->as) {
659*ce95e1b3SDavid du Colombier 		case AJAL:
660*ce95e1b3SDavid du Colombier 			for(z=0; z<BITS; z++) {
661*ce95e1b3SDavid du Colombier 				cal.b[z] |= ref.b[z] | externs.b[z];
662*ce95e1b3SDavid du Colombier 				ref.b[z] = 0;
663*ce95e1b3SDavid du Colombier 			}
664*ce95e1b3SDavid du Colombier 			break;
665*ce95e1b3SDavid du Colombier 
666*ce95e1b3SDavid du Colombier 		case ATEXT:
667*ce95e1b3SDavid du Colombier 			for(z=0; z<BITS; z++) {
668*ce95e1b3SDavid du Colombier 				cal.b[z] = 0;
669*ce95e1b3SDavid du Colombier 				ref.b[z] = 0;
670*ce95e1b3SDavid du Colombier 			}
671*ce95e1b3SDavid du Colombier 			break;
672*ce95e1b3SDavid du Colombier 
673*ce95e1b3SDavid du Colombier 		case ARET:
674*ce95e1b3SDavid du Colombier 			for(z=0; z<BITS; z++) {
675*ce95e1b3SDavid du Colombier 				cal.b[z] = externs.b[z];
676*ce95e1b3SDavid du Colombier 				ref.b[z] = 0;
677*ce95e1b3SDavid du Colombier 			}
678*ce95e1b3SDavid du Colombier 		}
679*ce95e1b3SDavid du Colombier 		for(z=0; z<BITS; z++) {
680*ce95e1b3SDavid du Colombier 			ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
681*ce95e1b3SDavid du Colombier 				r1->use1.b[z] | r1->use2.b[z];
682*ce95e1b3SDavid du Colombier 			cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
683*ce95e1b3SDavid du Colombier 			r1->refbehind.b[z] = ref.b[z];
684*ce95e1b3SDavid du Colombier 			r1->calbehind.b[z] = cal.b[z];
685*ce95e1b3SDavid du Colombier 		}
686*ce95e1b3SDavid du Colombier 		if(r1->active)
687*ce95e1b3SDavid du Colombier 			break;
688*ce95e1b3SDavid du Colombier 		r1->active = 1;
689*ce95e1b3SDavid du Colombier 	}
690*ce95e1b3SDavid du Colombier 	for(; r != r1; r = r->p1)
691*ce95e1b3SDavid du Colombier 		for(r2 = r->p2; r2 != R; r2 = r2->p2link)
692*ce95e1b3SDavid du Colombier 			prop(r2, r->refbehind, r->calbehind);
693*ce95e1b3SDavid du Colombier }
694*ce95e1b3SDavid du Colombier 
695*ce95e1b3SDavid du Colombier /*
696*ce95e1b3SDavid du Colombier  * find looping structure
697*ce95e1b3SDavid du Colombier  *
698*ce95e1b3SDavid du Colombier  * 1) find reverse postordering
699*ce95e1b3SDavid du Colombier  * 2) find approximate dominators,
700*ce95e1b3SDavid du Colombier  *	the actual dominators if the flow graph is reducible
701*ce95e1b3SDavid du Colombier  *	otherwise, dominators plus some other non-dominators.
702*ce95e1b3SDavid du Colombier  *	See Matthew S. Hecht and Jeffrey D. Ullman,
703*ce95e1b3SDavid du Colombier  *	"Analysis of a Simple Algorithm for Global Data Flow Problems",
704*ce95e1b3SDavid du Colombier  *	Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
705*ce95e1b3SDavid du Colombier  *	Oct. 1-3, 1973, pp.  207-217.
706*ce95e1b3SDavid du Colombier  * 3) find all nodes with a predecessor dominated by the current node.
707*ce95e1b3SDavid du Colombier  *	such a node is a loop head.
708*ce95e1b3SDavid du Colombier  *	recursively, all preds with a greater rpo number are in the loop
709*ce95e1b3SDavid du Colombier  */
710*ce95e1b3SDavid du Colombier long
postorder(Reg * r,Reg ** rpo2r,long n)711*ce95e1b3SDavid du Colombier postorder(Reg *r, Reg **rpo2r, long n)
712*ce95e1b3SDavid du Colombier {
713*ce95e1b3SDavid du Colombier 	Reg *r1;
714*ce95e1b3SDavid du Colombier 
715*ce95e1b3SDavid du Colombier 	r->rpo = 1;
716*ce95e1b3SDavid du Colombier 	r1 = r->s1;
717*ce95e1b3SDavid du Colombier 	if(r1 && !r1->rpo)
718*ce95e1b3SDavid du Colombier 		n = postorder(r1, rpo2r, n);
719*ce95e1b3SDavid du Colombier 	r1 = r->s2;
720*ce95e1b3SDavid du Colombier 	if(r1 && !r1->rpo)
721*ce95e1b3SDavid du Colombier 		n = postorder(r1, rpo2r, n);
722*ce95e1b3SDavid du Colombier 	rpo2r[n] = r;
723*ce95e1b3SDavid du Colombier 	n++;
724*ce95e1b3SDavid du Colombier 	return n;
725*ce95e1b3SDavid du Colombier }
726*ce95e1b3SDavid du Colombier 
727*ce95e1b3SDavid du Colombier long
rpolca(long * idom,long rpo1,long rpo2)728*ce95e1b3SDavid du Colombier rpolca(long *idom, long rpo1, long rpo2)
729*ce95e1b3SDavid du Colombier {
730*ce95e1b3SDavid du Colombier 	long t;
731*ce95e1b3SDavid du Colombier 
732*ce95e1b3SDavid du Colombier 	if(rpo1 == -1)
733*ce95e1b3SDavid du Colombier 		return rpo2;
734*ce95e1b3SDavid du Colombier 	while(rpo1 != rpo2){
735*ce95e1b3SDavid du Colombier 		if(rpo1 > rpo2){
736*ce95e1b3SDavid du Colombier 			t = rpo2;
737*ce95e1b3SDavid du Colombier 			rpo2 = rpo1;
738*ce95e1b3SDavid du Colombier 			rpo1 = t;
739*ce95e1b3SDavid du Colombier 		}
740*ce95e1b3SDavid du Colombier 		while(rpo1 < rpo2){
741*ce95e1b3SDavid du Colombier 			t = idom[rpo2];
742*ce95e1b3SDavid du Colombier 			if(t >= rpo2)
743*ce95e1b3SDavid du Colombier 				fatal(Z, "bad idom");
744*ce95e1b3SDavid du Colombier 			rpo2 = t;
745*ce95e1b3SDavid du Colombier 		}
746*ce95e1b3SDavid du Colombier 	}
747*ce95e1b3SDavid du Colombier 	return rpo1;
748*ce95e1b3SDavid du Colombier }
749*ce95e1b3SDavid du Colombier 
750*ce95e1b3SDavid du Colombier int
doms(long * idom,long r,long s)751*ce95e1b3SDavid du Colombier doms(long *idom, long r, long s)
752*ce95e1b3SDavid du Colombier {
753*ce95e1b3SDavid du Colombier 	while(s > r)
754*ce95e1b3SDavid du Colombier 		s = idom[s];
755*ce95e1b3SDavid du Colombier 	return s == r;
756*ce95e1b3SDavid du Colombier }
757*ce95e1b3SDavid du Colombier 
758*ce95e1b3SDavid du Colombier int
loophead(long * idom,Reg * r)759*ce95e1b3SDavid du Colombier loophead(long *idom, Reg *r)
760*ce95e1b3SDavid du Colombier {
761*ce95e1b3SDavid du Colombier 	long src;
762*ce95e1b3SDavid du Colombier 
763*ce95e1b3SDavid du Colombier 	src = r->rpo;
764*ce95e1b3SDavid du Colombier 	if(r->p1 != R && doms(idom, src, r->p1->rpo))
765*ce95e1b3SDavid du Colombier 		return 1;
766*ce95e1b3SDavid du Colombier 	for(r = r->p2; r != R; r = r->p2link)
767*ce95e1b3SDavid du Colombier 		if(doms(idom, src, r->rpo))
768*ce95e1b3SDavid du Colombier 			return 1;
769*ce95e1b3SDavid du Colombier 	return 0;
770*ce95e1b3SDavid du Colombier }
771*ce95e1b3SDavid du Colombier 
772*ce95e1b3SDavid du Colombier void
loopmark(Reg ** rpo2r,long head,Reg * r)773*ce95e1b3SDavid du Colombier loopmark(Reg **rpo2r, long head, Reg *r)
774*ce95e1b3SDavid du Colombier {
775*ce95e1b3SDavid du Colombier 	if(r->rpo < head || r->active == head)
776*ce95e1b3SDavid du Colombier 		return;
777*ce95e1b3SDavid du Colombier 	r->active = head;
778*ce95e1b3SDavid du Colombier 	r->loop += LOOP;
779*ce95e1b3SDavid du Colombier 	if(r->p1 != R)
780*ce95e1b3SDavid du Colombier 		loopmark(rpo2r, head, r->p1);
781*ce95e1b3SDavid du Colombier 	for(r = r->p2; r != R; r = r->p2link)
782*ce95e1b3SDavid du Colombier 		loopmark(rpo2r, head, r);
783*ce95e1b3SDavid du Colombier }
784*ce95e1b3SDavid du Colombier 
785*ce95e1b3SDavid du Colombier void
loopit(Reg * r,long nr)786*ce95e1b3SDavid du Colombier loopit(Reg *r, long nr)
787*ce95e1b3SDavid du Colombier {
788*ce95e1b3SDavid du Colombier 	Reg *r1;
789*ce95e1b3SDavid du Colombier 	long i, d, me;
790*ce95e1b3SDavid du Colombier 
791*ce95e1b3SDavid du Colombier 	if(nr > maxnr) {
792*ce95e1b3SDavid du Colombier 		rpo2r = alloc(nr * sizeof(Reg*));
793*ce95e1b3SDavid du Colombier 		idom = alloc(nr * sizeof(long));
794*ce95e1b3SDavid du Colombier 		maxnr = nr;
795*ce95e1b3SDavid du Colombier 	}
796*ce95e1b3SDavid du Colombier 
797*ce95e1b3SDavid du Colombier 	d = postorder(r, rpo2r, 0);
798*ce95e1b3SDavid du Colombier 	if(d > nr)
799*ce95e1b3SDavid du Colombier 		fatal(Z, "too many reg nodes");
800*ce95e1b3SDavid du Colombier 	nr = d;
801*ce95e1b3SDavid du Colombier 	for(i = 0; i < nr / 2; i++){
802*ce95e1b3SDavid du Colombier 		r1 = rpo2r[i];
803*ce95e1b3SDavid du Colombier 		rpo2r[i] = rpo2r[nr - 1 - i];
804*ce95e1b3SDavid du Colombier 		rpo2r[nr - 1 - i] = r1;
805*ce95e1b3SDavid du Colombier 	}
806*ce95e1b3SDavid du Colombier 	for(i = 0; i < nr; i++)
807*ce95e1b3SDavid du Colombier 		rpo2r[i]->rpo = i;
808*ce95e1b3SDavid du Colombier 
809*ce95e1b3SDavid du Colombier 	idom[0] = 0;
810*ce95e1b3SDavid du Colombier 	for(i = 0; i < nr; i++){
811*ce95e1b3SDavid du Colombier 		r1 = rpo2r[i];
812*ce95e1b3SDavid du Colombier 		me = r1->rpo;
813*ce95e1b3SDavid du Colombier 		d = -1;
814*ce95e1b3SDavid du Colombier 		if(r1->p1 != R && r1->p1->rpo < me)
815*ce95e1b3SDavid du Colombier 			d = r1->p1->rpo;
816*ce95e1b3SDavid du Colombier 		for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
817*ce95e1b3SDavid du Colombier 			if(r1->rpo < me)
818*ce95e1b3SDavid du Colombier 				d = rpolca(idom, d, r1->rpo);
819*ce95e1b3SDavid du Colombier 		idom[i] = d;
820*ce95e1b3SDavid du Colombier 	}
821*ce95e1b3SDavid du Colombier 
822*ce95e1b3SDavid du Colombier 	for(i = 0; i < nr; i++){
823*ce95e1b3SDavid du Colombier 		r1 = rpo2r[i];
824*ce95e1b3SDavid du Colombier 		r1->loop++;
825*ce95e1b3SDavid du Colombier 		if(r1->p2 != R && loophead(idom, r1))
826*ce95e1b3SDavid du Colombier 			loopmark(rpo2r, i, r1);
827*ce95e1b3SDavid du Colombier 	}
828*ce95e1b3SDavid du Colombier }
829*ce95e1b3SDavid du Colombier 
830*ce95e1b3SDavid du Colombier void
synch(Reg * r,Bits dif)831*ce95e1b3SDavid du Colombier synch(Reg *r, Bits dif)
832*ce95e1b3SDavid du Colombier {
833*ce95e1b3SDavid du Colombier 	Reg *r1;
834*ce95e1b3SDavid du Colombier 	int z;
835*ce95e1b3SDavid du Colombier 
836*ce95e1b3SDavid du Colombier 	for(r1 = r; r1 != R; r1 = r1->s1) {
837*ce95e1b3SDavid du Colombier 		for(z=0; z<BITS; z++) {
838*ce95e1b3SDavid du Colombier 			dif.b[z] = (dif.b[z] &
839*ce95e1b3SDavid du Colombier 				~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
840*ce95e1b3SDavid du Colombier 					r1->set.b[z] | r1->regdiff.b[z];
841*ce95e1b3SDavid du Colombier 			if(dif.b[z] != r1->regdiff.b[z]) {
842*ce95e1b3SDavid du Colombier 				r1->regdiff.b[z] = dif.b[z];
843*ce95e1b3SDavid du Colombier 				change++;
844*ce95e1b3SDavid du Colombier 			}
845*ce95e1b3SDavid du Colombier 		}
846*ce95e1b3SDavid du Colombier 		if(r1->active)
847*ce95e1b3SDavid du Colombier 			break;
848*ce95e1b3SDavid du Colombier 		r1->active = 1;
849*ce95e1b3SDavid du Colombier 		for(z=0; z<BITS; z++)
850*ce95e1b3SDavid du Colombier 			dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
851*ce95e1b3SDavid du Colombier 		if(r1->s2 != R)
852*ce95e1b3SDavid du Colombier 			synch(r1->s2, dif);
853*ce95e1b3SDavid du Colombier 	}
854*ce95e1b3SDavid du Colombier }
855*ce95e1b3SDavid du Colombier 
856*ce95e1b3SDavid du Colombier ulong
allreg(ulong b,Rgn * r)857*ce95e1b3SDavid du Colombier allreg(ulong b, Rgn *r)
858*ce95e1b3SDavid du Colombier {
859*ce95e1b3SDavid du Colombier 	Var *v;
860*ce95e1b3SDavid du Colombier 	int i;
861*ce95e1b3SDavid du Colombier 
862*ce95e1b3SDavid du Colombier 	v = var + r->varno;
863*ce95e1b3SDavid du Colombier 	r->regno = 0;
864*ce95e1b3SDavid du Colombier 	switch(v->etype) {
865*ce95e1b3SDavid du Colombier 
866*ce95e1b3SDavid du Colombier 	default:
867*ce95e1b3SDavid du Colombier 		diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
868*ce95e1b3SDavid du Colombier 		break;
869*ce95e1b3SDavid du Colombier 
870*ce95e1b3SDavid du Colombier 	case TCHAR:
871*ce95e1b3SDavid du Colombier 	case TUCHAR:
872*ce95e1b3SDavid du Colombier 	case TSHORT:
873*ce95e1b3SDavid du Colombier 	case TUSHORT:
874*ce95e1b3SDavid du Colombier 	case TINT:
875*ce95e1b3SDavid du Colombier 	case TUINT:
876*ce95e1b3SDavid du Colombier 	case TLONG:
877*ce95e1b3SDavid du Colombier 	case TULONG:
878*ce95e1b3SDavid du Colombier 	case TIND:
879*ce95e1b3SDavid du Colombier 	case TARRAY:
880*ce95e1b3SDavid du Colombier 		i = BtoR(~b);
881*ce95e1b3SDavid du Colombier 		if(i && r->cost >= 0) {
882*ce95e1b3SDavid du Colombier 			r->regno = i;
883*ce95e1b3SDavid du Colombier 			return RtoB(i);
884*ce95e1b3SDavid du Colombier 		}
885*ce95e1b3SDavid du Colombier 		break;
886*ce95e1b3SDavid du Colombier 
887*ce95e1b3SDavid du Colombier 	case TDOUBLE:
888*ce95e1b3SDavid du Colombier 	case TFLOAT:
889*ce95e1b3SDavid du Colombier 		i = BtoF(~b);
890*ce95e1b3SDavid du Colombier 		if(i && r->cost >= 0) {
891*ce95e1b3SDavid du Colombier 			r->regno = i+NREG;
892*ce95e1b3SDavid du Colombier 			return FtoB(i);
893*ce95e1b3SDavid du Colombier 		}
894*ce95e1b3SDavid du Colombier 		break;
895*ce95e1b3SDavid du Colombier 	}
896*ce95e1b3SDavid du Colombier 	return 0;
897*ce95e1b3SDavid du Colombier }
898*ce95e1b3SDavid du Colombier 
899*ce95e1b3SDavid du Colombier void
paint1(Reg * r,int bn)900*ce95e1b3SDavid du Colombier paint1(Reg *r, int bn)
901*ce95e1b3SDavid du Colombier {
902*ce95e1b3SDavid du Colombier 	Reg *r1;
903*ce95e1b3SDavid du Colombier 	Prog *p;
904*ce95e1b3SDavid du Colombier 	int z;
905*ce95e1b3SDavid du Colombier 	ulong bb;
906*ce95e1b3SDavid du Colombier 
907*ce95e1b3SDavid du Colombier 	z = bn/32;
908*ce95e1b3SDavid du Colombier 	bb = 1L<<(bn%32);
909*ce95e1b3SDavid du Colombier 	if(r->act.b[z] & bb)
910*ce95e1b3SDavid du Colombier 		return;
911*ce95e1b3SDavid du Colombier 	for(;;) {
912*ce95e1b3SDavid du Colombier 		if(!(r->refbehind.b[z] & bb))
913*ce95e1b3SDavid du Colombier 			break;
914*ce95e1b3SDavid du Colombier 		r1 = r->p1;
915*ce95e1b3SDavid du Colombier 		if(r1 == R)
916*ce95e1b3SDavid du Colombier 			break;
917*ce95e1b3SDavid du Colombier 		if(!(r1->refahead.b[z] & bb))
918*ce95e1b3SDavid du Colombier 			break;
919*ce95e1b3SDavid du Colombier 		if(r1->act.b[z] & bb)
920*ce95e1b3SDavid du Colombier 			break;
921*ce95e1b3SDavid du Colombier 		r = r1;
922*ce95e1b3SDavid du Colombier 	}
923*ce95e1b3SDavid du Colombier 
924*ce95e1b3SDavid du Colombier 	if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb) {
925*ce95e1b3SDavid du Colombier 		change -= CLOAD * r->loop;
926*ce95e1b3SDavid du Colombier 		if(debug['R'] && debug['v'])
927*ce95e1b3SDavid du Colombier 			print("%ld%P\tld %B $%d\n", r->loop,
928*ce95e1b3SDavid du Colombier 				r->prog, blsh(bn), change);
929*ce95e1b3SDavid du Colombier 	}
930*ce95e1b3SDavid du Colombier 	for(;;) {
931*ce95e1b3SDavid du Colombier 		r->act.b[z] |= bb;
932*ce95e1b3SDavid du Colombier 		p = r->prog;
933*ce95e1b3SDavid du Colombier 
934*ce95e1b3SDavid du Colombier 		if(r->use1.b[z] & bb) {
935*ce95e1b3SDavid du Colombier 			change += CREF * r->loop;
936*ce95e1b3SDavid du Colombier 			if(debug['R'] && debug['v'])
937*ce95e1b3SDavid du Colombier 				print("%ld%P\tu1 %B $%d\n", r->loop,
938*ce95e1b3SDavid du Colombier 					p, blsh(bn), change);
939*ce95e1b3SDavid du Colombier 		}
940*ce95e1b3SDavid du Colombier 
941*ce95e1b3SDavid du Colombier 		if((r->use2.b[z]|r->set.b[z]) & bb) {
942*ce95e1b3SDavid du Colombier 			change += CREF * r->loop;
943*ce95e1b3SDavid du Colombier 			if(debug['R'] && debug['v'])
944*ce95e1b3SDavid du Colombier 				print("%ld%P\tu2 %B $%d\n", r->loop,
945*ce95e1b3SDavid du Colombier 					p, blsh(bn), change);
946*ce95e1b3SDavid du Colombier 		}
947*ce95e1b3SDavid du Colombier 
948*ce95e1b3SDavid du Colombier 		if(STORE(r) & r->regdiff.b[z] & bb) {
949*ce95e1b3SDavid du Colombier 			change -= CLOAD * r->loop;
950*ce95e1b3SDavid du Colombier 			if(debug['R'] && debug['v'])
951*ce95e1b3SDavid du Colombier 				print("%ld%P\tst %B $%d\n", r->loop,
952*ce95e1b3SDavid du Colombier 					p, blsh(bn), change);
953*ce95e1b3SDavid du Colombier 		}
954*ce95e1b3SDavid du Colombier 
955*ce95e1b3SDavid du Colombier 		if(r->refbehind.b[z] & bb)
956*ce95e1b3SDavid du Colombier 			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
957*ce95e1b3SDavid du Colombier 				if(r1->refahead.b[z] & bb)
958*ce95e1b3SDavid du Colombier 					paint1(r1, bn);
959*ce95e1b3SDavid du Colombier 
960*ce95e1b3SDavid du Colombier 		if(!(r->refahead.b[z] & bb))
961*ce95e1b3SDavid du Colombier 			break;
962*ce95e1b3SDavid du Colombier 		r1 = r->s2;
963*ce95e1b3SDavid du Colombier 		if(r1 != R)
964*ce95e1b3SDavid du Colombier 			if(r1->refbehind.b[z] & bb)
965*ce95e1b3SDavid du Colombier 				paint1(r1, bn);
966*ce95e1b3SDavid du Colombier 		r = r->s1;
967*ce95e1b3SDavid du Colombier 		if(r == R)
968*ce95e1b3SDavid du Colombier 			break;
969*ce95e1b3SDavid du Colombier 		if(r->act.b[z] & bb)
970*ce95e1b3SDavid du Colombier 			break;
971*ce95e1b3SDavid du Colombier 		if(!(r->refbehind.b[z] & bb))
972*ce95e1b3SDavid du Colombier 			break;
973*ce95e1b3SDavid du Colombier 	}
974*ce95e1b3SDavid du Colombier }
975*ce95e1b3SDavid du Colombier 
976*ce95e1b3SDavid du Colombier ulong
paint2(Reg * r,int bn)977*ce95e1b3SDavid du Colombier paint2(Reg *r, int bn)
978*ce95e1b3SDavid du Colombier {
979*ce95e1b3SDavid du Colombier 	Reg *r1;
980*ce95e1b3SDavid du Colombier 	int z;
981*ce95e1b3SDavid du Colombier 	ulong bb, vreg;
982*ce95e1b3SDavid du Colombier 
983*ce95e1b3SDavid du Colombier 	z = bn/32;
984*ce95e1b3SDavid du Colombier 	bb = 1L << (bn%32);
985*ce95e1b3SDavid du Colombier 	vreg = regbits;
986*ce95e1b3SDavid du Colombier 	if(!(r->act.b[z] & bb))
987*ce95e1b3SDavid du Colombier 		return vreg;
988*ce95e1b3SDavid du Colombier 	for(;;) {
989*ce95e1b3SDavid du Colombier 		if(!(r->refbehind.b[z] & bb))
990*ce95e1b3SDavid du Colombier 			break;
991*ce95e1b3SDavid du Colombier 		r1 = r->p1;
992*ce95e1b3SDavid du Colombier 		if(r1 == R)
993*ce95e1b3SDavid du Colombier 			break;
994*ce95e1b3SDavid du Colombier 		if(!(r1->refahead.b[z] & bb))
995*ce95e1b3SDavid du Colombier 			break;
996*ce95e1b3SDavid du Colombier 		if(!(r1->act.b[z] & bb))
997*ce95e1b3SDavid du Colombier 			break;
998*ce95e1b3SDavid du Colombier 		r = r1;
999*ce95e1b3SDavid du Colombier 	}
1000*ce95e1b3SDavid du Colombier 	for(;;) {
1001*ce95e1b3SDavid du Colombier 		r->act.b[z] &= ~bb;
1002*ce95e1b3SDavid du Colombier 
1003*ce95e1b3SDavid du Colombier 		vreg |= r->regu;
1004*ce95e1b3SDavid du Colombier 
1005*ce95e1b3SDavid du Colombier 		if(r->refbehind.b[z] & bb)
1006*ce95e1b3SDavid du Colombier 			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
1007*ce95e1b3SDavid du Colombier 				if(r1->refahead.b[z] & bb)
1008*ce95e1b3SDavid du Colombier 					vreg |= paint2(r1, bn);
1009*ce95e1b3SDavid du Colombier 
1010*ce95e1b3SDavid du Colombier 		if(!(r->refahead.b[z] & bb))
1011*ce95e1b3SDavid du Colombier 			break;
1012*ce95e1b3SDavid du Colombier 		r1 = r->s2;
1013*ce95e1b3SDavid du Colombier 		if(r1 != R)
1014*ce95e1b3SDavid du Colombier 			if(r1->refbehind.b[z] & bb)
1015*ce95e1b3SDavid du Colombier 				vreg |= paint2(r1, bn);
1016*ce95e1b3SDavid du Colombier 		r = r->s1;
1017*ce95e1b3SDavid du Colombier 		if(r == R)
1018*ce95e1b3SDavid du Colombier 			break;
1019*ce95e1b3SDavid du Colombier 		if(!(r->act.b[z] & bb))
1020*ce95e1b3SDavid du Colombier 			break;
1021*ce95e1b3SDavid du Colombier 		if(!(r->refbehind.b[z] & bb))
1022*ce95e1b3SDavid du Colombier 			break;
1023*ce95e1b3SDavid du Colombier 	}
1024*ce95e1b3SDavid du Colombier 	return vreg;
1025*ce95e1b3SDavid du Colombier }
1026*ce95e1b3SDavid du Colombier 
1027*ce95e1b3SDavid du Colombier void
paint3(Reg * r,int bn,long rb,int rn)1028*ce95e1b3SDavid du Colombier paint3(Reg *r, int bn, long rb, int rn)
1029*ce95e1b3SDavid du Colombier {
1030*ce95e1b3SDavid du Colombier 	Reg *r1;
1031*ce95e1b3SDavid du Colombier 	Prog *p;
1032*ce95e1b3SDavid du Colombier 	int z;
1033*ce95e1b3SDavid du Colombier 	ulong bb;
1034*ce95e1b3SDavid du Colombier 
1035*ce95e1b3SDavid du Colombier 	z = bn/32;
1036*ce95e1b3SDavid du Colombier 	bb = 1L << (bn%32);
1037*ce95e1b3SDavid du Colombier 	if(r->act.b[z] & bb)
1038*ce95e1b3SDavid du Colombier 		return;
1039*ce95e1b3SDavid du Colombier 	for(;;) {
1040*ce95e1b3SDavid du Colombier 		if(!(r->refbehind.b[z] & bb))
1041*ce95e1b3SDavid du Colombier 			break;
1042*ce95e1b3SDavid du Colombier 		r1 = r->p1;
1043*ce95e1b3SDavid du Colombier 		if(r1 == R)
1044*ce95e1b3SDavid du Colombier 			break;
1045*ce95e1b3SDavid du Colombier 		if(!(r1->refahead.b[z] & bb))
1046*ce95e1b3SDavid du Colombier 			break;
1047*ce95e1b3SDavid du Colombier 		if(r1->act.b[z] & bb)
1048*ce95e1b3SDavid du Colombier 			break;
1049*ce95e1b3SDavid du Colombier 		r = r1;
1050*ce95e1b3SDavid du Colombier 	}
1051*ce95e1b3SDavid du Colombier 
1052*ce95e1b3SDavid du Colombier 	if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
1053*ce95e1b3SDavid du Colombier 		addmove(r, bn, rn, 0);
1054*ce95e1b3SDavid du Colombier 	for(;;) {
1055*ce95e1b3SDavid du Colombier 		r->act.b[z] |= bb;
1056*ce95e1b3SDavid du Colombier 		p = r->prog;
1057*ce95e1b3SDavid du Colombier 
1058*ce95e1b3SDavid du Colombier 		if(r->use1.b[z] & bb) {
1059*ce95e1b3SDavid du Colombier 			if(debug['R'])
1060*ce95e1b3SDavid du Colombier 				print("%P", p);
1061*ce95e1b3SDavid du Colombier 			addreg(&p->from, rn);
1062*ce95e1b3SDavid du Colombier 			switch(p->as){
1063*ce95e1b3SDavid du Colombier 			case AMOVB:
1064*ce95e1b3SDavid du Colombier 			case AMOVBU:
1065*ce95e1b3SDavid du Colombier 			case AMOVH:
1066*ce95e1b3SDavid du Colombier 			case AMOVHU:
1067*ce95e1b3SDavid du Colombier 			case AMOVW:
1068*ce95e1b3SDavid du Colombier 			case AMOVWU:
1069*ce95e1b3SDavid du Colombier 				p->as = AMOV;
1070*ce95e1b3SDavid du Colombier 			}
1071*ce95e1b3SDavid du Colombier 			if(debug['R'])
1072*ce95e1b3SDavid du Colombier 				print("\t.c%P\n", p);
1073*ce95e1b3SDavid du Colombier 		}
1074*ce95e1b3SDavid du Colombier 		if((r->use2.b[z]|r->set.b[z]) & bb) {
1075*ce95e1b3SDavid du Colombier 			if(debug['R'])
1076*ce95e1b3SDavid du Colombier 				print("%P", p);
1077*ce95e1b3SDavid du Colombier 			addreg(&p->to, rn);
1078*ce95e1b3SDavid du Colombier 			if(debug['R'])
1079*ce95e1b3SDavid du Colombier 				print("\t.c%P\n", p);
1080*ce95e1b3SDavid du Colombier 		}
1081*ce95e1b3SDavid du Colombier 
1082*ce95e1b3SDavid du Colombier 		if(STORE(r) & r->regdiff.b[z] & bb)
1083*ce95e1b3SDavid du Colombier 			addmove(r, bn, rn, 1);
1084*ce95e1b3SDavid du Colombier 		r->regu |= rb;
1085*ce95e1b3SDavid du Colombier 
1086*ce95e1b3SDavid du Colombier 		if(r->refbehind.b[z] & bb)
1087*ce95e1b3SDavid du Colombier 			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
1088*ce95e1b3SDavid du Colombier 				if(r1->refahead.b[z] & bb)
1089*ce95e1b3SDavid du Colombier 					paint3(r1, bn, rb, rn);
1090*ce95e1b3SDavid du Colombier 
1091*ce95e1b3SDavid du Colombier 		if(!(r->refahead.b[z] & bb))
1092*ce95e1b3SDavid du Colombier 			break;
1093*ce95e1b3SDavid du Colombier 		r1 = r->s2;
1094*ce95e1b3SDavid du Colombier 		if(r1 != R)
1095*ce95e1b3SDavid du Colombier 			if(r1->refbehind.b[z] & bb)
1096*ce95e1b3SDavid du Colombier 				paint3(r1, bn, rb, rn);
1097*ce95e1b3SDavid du Colombier 		r = r->s1;
1098*ce95e1b3SDavid du Colombier 		if(r == R)
1099*ce95e1b3SDavid du Colombier 			break;
1100*ce95e1b3SDavid du Colombier 		if(r->act.b[z] & bb)
1101*ce95e1b3SDavid du Colombier 			break;
1102*ce95e1b3SDavid du Colombier 		if(!(r->refbehind.b[z] & bb))
1103*ce95e1b3SDavid du Colombier 			break;
1104*ce95e1b3SDavid du Colombier 	}
1105*ce95e1b3SDavid du Colombier }
1106*ce95e1b3SDavid du Colombier 
1107*ce95e1b3SDavid du Colombier void
addreg(Adr * a,int rn)1108*ce95e1b3SDavid du Colombier addreg(Adr *a, int rn)
1109*ce95e1b3SDavid du Colombier {
1110*ce95e1b3SDavid du Colombier 
1111*ce95e1b3SDavid du Colombier 	a->sym = 0;
1112*ce95e1b3SDavid du Colombier 	a->name = D_NONE;
1113*ce95e1b3SDavid du Colombier 	a->type = D_REG;
1114*ce95e1b3SDavid du Colombier 	a->reg = rn;
1115*ce95e1b3SDavid du Colombier 	if(rn >= NREG) {
1116*ce95e1b3SDavid du Colombier 		a->type = D_FREG;
1117*ce95e1b3SDavid du Colombier 		a->reg = rn-NREG;
1118*ce95e1b3SDavid du Colombier 	}
1119*ce95e1b3SDavid du Colombier }
1120*ce95e1b3SDavid du Colombier 
1121*ce95e1b3SDavid du Colombier /*
1122*ce95e1b3SDavid du Colombier  *	bit	reg
1123*ce95e1b3SDavid du Colombier  *	0	R9
1124*ce95e1b3SDavid du Colombier  *	1	R10
1125*ce95e1b3SDavid du Colombier  *  ... ...
1126*ce95e1b3SDavid du Colombier  *  6   R15
1127*ce95e1b3SDavid du Colombier  */
1128*ce95e1b3SDavid du Colombier long
RtoB(int r)1129*ce95e1b3SDavid du Colombier RtoB(int r)
1130*ce95e1b3SDavid du Colombier {
1131*ce95e1b3SDavid du Colombier 
1132*ce95e1b3SDavid du Colombier 	if(r < 9 || r > 15)
1133*ce95e1b3SDavid du Colombier 		return 0;
1134*ce95e1b3SDavid du Colombier 	return 1L << (r-9);
1135*ce95e1b3SDavid du Colombier }
1136*ce95e1b3SDavid du Colombier 
1137*ce95e1b3SDavid du Colombier int
BtoR(long b)1138*ce95e1b3SDavid du Colombier BtoR(long b)
1139*ce95e1b3SDavid du Colombier {
1140*ce95e1b3SDavid du Colombier 
1141*ce95e1b3SDavid du Colombier 	b &= 0x007fL;
1142*ce95e1b3SDavid du Colombier 	if(b == 0)
1143*ce95e1b3SDavid du Colombier 		return 0;
1144*ce95e1b3SDavid du Colombier 	return bitno(b) + 9;
1145*ce95e1b3SDavid du Colombier }
1146*ce95e1b3SDavid du Colombier 
1147*ce95e1b3SDavid du Colombier /*
1148*ce95e1b3SDavid du Colombier  *	bit	reg
1149*ce95e1b3SDavid du Colombier  *	7	F1
1150*ce95e1b3SDavid du Colombier  *	8	F2
1151*ce95e1b3SDavid du Colombier  *	...	...
1152*ce95e1b3SDavid du Colombier  *	31	F25
1153*ce95e1b3SDavid du Colombier  */
1154*ce95e1b3SDavid du Colombier long
FtoB(int f)1155*ce95e1b3SDavid du Colombier FtoB(int f)
1156*ce95e1b3SDavid du Colombier {
1157*ce95e1b3SDavid du Colombier 
1158*ce95e1b3SDavid du Colombier 	if(f < 1 || f > 25)
1159*ce95e1b3SDavid du Colombier 		return 0;
1160*ce95e1b3SDavid du Colombier 	return 1L << (f + 6);
1161*ce95e1b3SDavid du Colombier }
1162*ce95e1b3SDavid du Colombier 
1163*ce95e1b3SDavid du Colombier int
BtoF(long b)1164*ce95e1b3SDavid du Colombier BtoF(long b)
1165*ce95e1b3SDavid du Colombier {
1166*ce95e1b3SDavid du Colombier 
1167*ce95e1b3SDavid du Colombier 	b &= 0x03ffff80L;
1168*ce95e1b3SDavid du Colombier 	if(b == 0)
1169*ce95e1b3SDavid du Colombier 		return 0;
1170*ce95e1b3SDavid du Colombier 	return bitno(b) - 6;
1171*ce95e1b3SDavid du Colombier }
1172