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