xref: /csrg-svn/old/pcc/c2.vax/c20.c (revision 1495)
1*1495Sbill #
2*1495Sbill static	char sccsid[] = "@(#)c20.c 4.1 10/17/80";
3*1495Sbill /* char C20[] = {"@(#)c20.c 1.33 80/08/08 10:01:02"}; /* sccs ident */
4*1495Sbill /*
5*1495Sbill  *	 C object code improver
6*1495Sbill  */
7*1495Sbill 
8*1495Sbill #include "c2.h"
9*1495Sbill #include <stdio.h>
10*1495Sbill #include <ctype.h>
11*1495Sbill 
12*1495Sbill char _sibuf[BUFSIZ], _sobuf[BUFSIZ];
13*1495Sbill int ioflag;
14*1495Sbill int	isn	= 2000000;
15*1495Sbill struct optab *oplook();
16*1495Sbill struct optab *getline();
17*1495Sbill int lgensym[10] =
18*1495Sbill   {100000,200000,300000,400000,500000,600000,700000,800000,900000,1000000};
19*1495Sbill 
20*1495Sbill struct node *
21*1495Sbill alloc(an)
22*1495Sbill {
23*1495Sbill 	register int n;
24*1495Sbill 	register char *p;
25*1495Sbill 
26*1495Sbill 	n = an;
27*1495Sbill 	n++;
28*1495Sbill 	n &= ~01;
29*1495Sbill 	if (lasta+n >= lastr) {
30*1495Sbill 		if (sbrk(2000) == -1) {
31*1495Sbill 			fprintf(stderr, "Optimizer: out of space\n");
32*1495Sbill 			exit(1);
33*1495Sbill 		}
34*1495Sbill 		lastr += 2000;
35*1495Sbill 	}
36*1495Sbill 	p = lasta;
37*1495Sbill 	lasta += n;
38*1495Sbill 	return(p);
39*1495Sbill }
40*1495Sbill 
41*1495Sbill main(argc, argv)
42*1495Sbill char **argv;
43*1495Sbill {
44*1495Sbill 	register int niter, maxiter, isend;
45*1495Sbill 	int nflag,infound;
46*1495Sbill 
47*1495Sbill 	nflag = 0; infound=0; argc--; argv++;
48*1495Sbill 	while (argc>0) {/* get flags */
49*1495Sbill 		if (**argv=='+') debug++;
50*1495Sbill 		else if (**argv=='-') {
51*1495Sbill 			if ((*argv)[1]=='i') ioflag++; else nflag++;
52*1495Sbill 		} else if (infound==0) {
53*1495Sbill 			if (freopen(*argv, "r", stdin) ==NULL) {
54*1495Sbill 				fprintf(stderr,"C2: can't find %s\n", *argv);
55*1495Sbill 				exit(1);
56*1495Sbill 			}
57*1495Sbill 			setbuf(stdin,_sibuf); ++infound;
58*1495Sbill 		} else if (freopen(*argv, "w", stdout) ==NULL) {
59*1495Sbill 			fprintf(stderr,"C2: can't create %s\n", *argv);
60*1495Sbill 			exit(1);
61*1495Sbill 		}
62*1495Sbill 		setbuf(stdout,_sobuf);
63*1495Sbill 		argc--; argv++;
64*1495Sbill 	}
65*1495Sbill 	lasta = lastr = sbrk(2);
66*1495Sbill 	opsetup();
67*1495Sbill 	lasta = firstr = lastr = alloc(0);
68*1495Sbill 	maxiter = 0;
69*1495Sbill 	do {
70*1495Sbill 		isend = input();
71*1495Sbill 		niter = 0;
72*1495Sbill 		bmove();
73*1495Sbill 		do {
74*1495Sbill 			refcount();
75*1495Sbill 			do {
76*1495Sbill 				iterate();
77*1495Sbill 				clearreg();
78*1495Sbill 				niter++;
79*1495Sbill 			} while (nchange);
80*1495Sbill 			comjump();
81*1495Sbill 			rmove();
82*1495Sbill 		} while (nchange || jumpsw());
83*1495Sbill 		addsob();
84*1495Sbill 		output();
85*1495Sbill 		if (niter > maxiter)
86*1495Sbill 			maxiter = niter;
87*1495Sbill 		lasta = firstr;
88*1495Sbill 	} while (isend);
89*1495Sbill 	if (nflag) {
90*1495Sbill 		fprintf(stderr,"%d iterations\n", maxiter);
91*1495Sbill 		fprintf(stderr,"%d jumps to jumps\n", nbrbr);
92*1495Sbill 		fprintf(stderr,"%d inst. after jumps\n", iaftbr);
93*1495Sbill 		fprintf(stderr,"%d jumps to .+1\n", njp1);
94*1495Sbill 		fprintf(stderr,"%d redundant labels\n", nrlab);
95*1495Sbill 		fprintf(stderr,"%d cross-jumps\n", nxjump);
96*1495Sbill 		fprintf(stderr,"%d code motions\n", ncmot);
97*1495Sbill 		fprintf(stderr,"%d branches reversed\n", nrevbr);
98*1495Sbill 		fprintf(stderr,"%d redundant moves\n", redunm);
99*1495Sbill 		fprintf(stderr,"%d simplified addresses\n", nsaddr);
100*1495Sbill 		fprintf(stderr,"%d loops inverted\n", loopiv);
101*1495Sbill 		fprintf(stderr,"%d redundant jumps\n", nredunj);
102*1495Sbill 		fprintf(stderr,"%d common seqs before jmp's\n", ncomj);
103*1495Sbill 		fprintf(stderr,"%d skips over jumps\n", nskip);
104*1495Sbill 		fprintf(stderr,"%d sob's added\n", nsob);
105*1495Sbill 		fprintf(stderr,"%d redundant tst's\n", nrtst);
106*1495Sbill 		fprintf(stderr,"%d jump on bit\n", nbj);
107*1495Sbill 		fprintf(stderr,"%d field operations\n", nfield);
108*1495Sbill 		fprintf(stderr,"%dK core\n", ((unsigned)lastr+01777) >> 10);
109*1495Sbill 	}
110*1495Sbill 	putc('\n',stdout);
111*1495Sbill 	fflush(stdout); exit(0);
112*1495Sbill }
113*1495Sbill 
114*1495Sbill input()
115*1495Sbill {
116*1495Sbill 	register struct node *p, *lastp;
117*1495Sbill 	struct optab *op; register char *cp1;
118*1495Sbill 	static struct optab F77JSW = {".long", T(JSW,1)};
119*1495Sbill 
120*1495Sbill 	lastp = &first;
121*1495Sbill 	for (;;) {
122*1495Sbill 	  top:
123*1495Sbill 		op = getline();
124*1495Sbill 		if (debug && op==0) fprintf(stderr,"? %s\n",line);
125*1495Sbill 		switch (op->opcode&0377) {
126*1495Sbill 
127*1495Sbill 		case LABEL:
128*1495Sbill 			p = alloc(sizeof first);
129*1495Sbill 			if (isdigit(line[0]) && (p->labno=locdef(line)) ||
130*1495Sbill 			  (line[0] == 'L') && (p->labno=getnum(line+1))) {
131*1495Sbill 				p->combop = LABEL;
132*1495Sbill 				if (isn<=p->labno) isn=1+p->labno;
133*1495Sbill 				p->code = 0;
134*1495Sbill 			} else {
135*1495Sbill 				p->combop = DLABEL;
136*1495Sbill 				p->labno = 0;
137*1495Sbill 				p->code = copy(line);
138*1495Sbill 			}
139*1495Sbill 			break;
140*1495Sbill 
141*1495Sbill 		case LGEN:
142*1495Sbill 			if (*curlp!='L' && !locuse(curlp)) goto std;
143*1495Sbill 			op= &F77JSW;
144*1495Sbill 		case JBR:
145*1495Sbill 			if (op->opcode==T(JBR,RET) || op->opcode==T(JBR,RSB)) goto std;
146*1495Sbill 		case CBR:
147*1495Sbill 		case JMP:
148*1495Sbill 		case JSW:
149*1495Sbill 		case SOBGEQ: case SOBGTR: case AOBLEQ: case AOBLSS: case ACB:
150*1495Sbill 			p = alloc(sizeof first);
151*1495Sbill 			p->combop = op->opcode; p->code=0; cp1=curlp;
152*1495Sbill 			if ((!isdigit(*cp1) || 0==(p->labno=locuse(cp1))) &&
153*1495Sbill 			  (*cp1!='L' || 0==(p->labno = getnum(cp1+1)))) {/* jbs, etc.? */
154*1495Sbill 				while (*cp1++); while (*--cp1!=',' && cp1!=curlp);
155*1495Sbill 				if (cp1==curlp ||
156*1495Sbill 				  (!isdigit(*++cp1) || 0==(p->labno=locuse(cp1))) &&
157*1495Sbill 				  (*cp1!='L' || 0==(p->labno=getnum(cp1+1))))
158*1495Sbill 					p->labno = 0;
159*1495Sbill 				else *--cp1=0;
160*1495Sbill 				p->code = copy(curlp);
161*1495Sbill 			}
162*1495Sbill 			if (isn<=p->labno) isn=1+p->labno;
163*1495Sbill 			break;
164*1495Sbill 
165*1495Sbill 		case MOVA:
166*1495Sbill 			p=alloc(sizeof first);
167*1495Sbill 			p->combop=op->opcode; p->code=0; cp1=curlp+1;
168*1495Sbill 			if (cp1[-1]=='L' || isdigit(cp1[-1])) {
169*1495Sbill 				while (*cp1++!=','); *--cp1=0;
170*1495Sbill 				if (0!=(p->labno=locuse(curlp)) ||
171*1495Sbill 					0!=(p->labno=getnum(curlp+1))) p->code=copy(cp1+1);
172*1495Sbill 				else {*cp1=','; p->code=copy(curlp);}
173*1495Sbill 			} else {p->code=copy(--cp1); p->labno=0;}
174*1495Sbill 			break;
175*1495Sbill 
176*1495Sbill 		case SET:
177*1495Sbill 		case COMM:
178*1495Sbill 		case LCOMM:
179*1495Sbill 			printf("%s\n",line); goto top;
180*1495Sbill 
181*1495Sbill 		case BSS:
182*1495Sbill 		case DATA:
183*1495Sbill 			for (;;) {
184*1495Sbill 				printf("%s%c",line,(op->opcode==LABEL ? ':' : '\n'));
185*1495Sbill 				if (op->opcode==TEXT) goto top;
186*1495Sbill 				if (END==(op=getline())->opcode) {/* dangling .data is bad for you */
187*1495Sbill 					printf(".text\n");
188*1495Sbill 					break;
189*1495Sbill 				}
190*1495Sbill 			}
191*1495Sbill 
192*1495Sbill 		std:
193*1495Sbill 		default:
194*1495Sbill 			p = alloc(sizeof first);
195*1495Sbill 			p->combop = op->opcode;
196*1495Sbill 			p->labno = 0;
197*1495Sbill 			p->code = copy(curlp);
198*1495Sbill 			break;
199*1495Sbill 
200*1495Sbill 		}
201*1495Sbill 		p->forw = 0;
202*1495Sbill 		p->back = lastp;
203*1495Sbill 		p->pop = op;
204*1495Sbill 		lastp->forw = p;
205*1495Sbill 		lastp = p;
206*1495Sbill 		p->ref = 0;
207*1495Sbill 		if (p->op==CASE) {
208*1495Sbill 			char *lp; int ncase;
209*1495Sbill 			lp=curlp; while (*lp++); while (*--lp!='$'); ncase=getnum(lp+1);
210*1495Sbill 			if (LABEL!=(getline())->opcode) abort(-2);
211*1495Sbill 			do {
212*1495Sbill 				if (WGEN!=(getline())->opcode) abort(-3);
213*1495Sbill 				p = alloc(sizeof first); p->combop = JSW; p->code = 0;
214*1495Sbill 				lp=curlp; while(*lp++!='-'); *--lp=0; p->labno=getnum(curlp+1);
215*1495Sbill 				if (isn<=p->labno) isn=1+p->labno;
216*1495Sbill 				p->forw = 0; p->back = lastp; lastp->forw = p; lastp = p;
217*1495Sbill 				p->ref = 0; p->pop=0;
218*1495Sbill 			} while (--ncase>=0);
219*1495Sbill 		}
220*1495Sbill 		if (op->opcode==EROU)
221*1495Sbill 			return(1);
222*1495Sbill 		if (op->opcode==END)
223*1495Sbill 			return(0);
224*1495Sbill 	}
225*1495Sbill }
226*1495Sbill 
227*1495Sbill struct optab *
228*1495Sbill getline()
229*1495Sbill {
230*1495Sbill 	register char *lp;
231*1495Sbill 	register c;
232*1495Sbill 	static struct optab OPLABEL={"",LABEL};
233*1495Sbill 	static struct optab OPEND={"",END};
234*1495Sbill 
235*1495Sbill 	lp = line;
236*1495Sbill 	while (EOF!=(c=getchar()) && isspace(c));
237*1495Sbill 	while (EOF!=c) {
238*1495Sbill 		if (c==':') {
239*1495Sbill 			*lp++ = 0;
240*1495Sbill 			return(&OPLABEL);
241*1495Sbill 		}
242*1495Sbill 		if (c=='\n') {
243*1495Sbill 			*lp++ = 0;
244*1495Sbill 			return(oplook());
245*1495Sbill 		}
246*1495Sbill 		*lp++ = c;
247*1495Sbill 		c = getchar();
248*1495Sbill 	}
249*1495Sbill 	*lp++ = 0;
250*1495Sbill 	return(&OPEND);
251*1495Sbill }
252*1495Sbill 
253*1495Sbill long
254*1495Sbill getnum(p)
255*1495Sbill register char *p;
256*1495Sbill {
257*1495Sbill 	register c; int neg; register long n;
258*1495Sbill 
259*1495Sbill 	n = 0; neg=0; if (*p=='-') {++neg; ++p;}
260*1495Sbill 	while (isdigit(c = *p++)) {
261*1495Sbill 		 c -= '0'; n *= 10; if (neg) n -= c; else n += c;
262*1495Sbill 	}
263*1495Sbill 	if (*--p != 0)
264*1495Sbill 		return(0);
265*1495Sbill 	return(n);
266*1495Sbill }
267*1495Sbill 
268*1495Sbill locuse(p)
269*1495Sbill register char *p;
270*1495Sbill {
271*1495Sbill 	register c; int neg; register long n;
272*1495Sbill 
273*1495Sbill 	if (!isdigit(p[0]) || p[1] != 'f' && p[1] != 'b' || p[2]) return(0);
274*1495Sbill 	return (lgensym[p[0] - '0'] - (p[1] == 'b'));
275*1495Sbill }
276*1495Sbill 
277*1495Sbill locdef(p)
278*1495Sbill register char *p;
279*1495Sbill {
280*1495Sbill 
281*1495Sbill 	if (!isdigit(p[0]) || p[1]) return(0);
282*1495Sbill 	return (lgensym[p[0] - '0']++);
283*1495Sbill }
284*1495Sbill 
285*1495Sbill output()
286*1495Sbill {
287*1495Sbill 	register struct node *t;
288*1495Sbill 	int casebas;
289*1495Sbill 
290*1495Sbill 	t = &first;
291*1495Sbill 	while (t = t->forw) switch (t->op) {
292*1495Sbill 
293*1495Sbill 	case END:
294*1495Sbill 		fflush(stdout);
295*1495Sbill 		return;
296*1495Sbill 
297*1495Sbill 	case LABEL:
298*1495Sbill 		printf("L%d:", t->labno);
299*1495Sbill 		continue;
300*1495Sbill 
301*1495Sbill 	case DLABEL:
302*1495Sbill 		printf("%s:", t->code);
303*1495Sbill 		continue;
304*1495Sbill 
305*1495Sbill 	case CASE:
306*1495Sbill 		casebas=0;
307*1495Sbill 
308*1495Sbill 	default: std:
309*1495Sbill 		if (t->pop==0) {/* must find it */
310*1495Sbill 			register struct optab *p;
311*1495Sbill 			for (p=optab; p->opstring[0]; ++p)
312*1495Sbill 				if (p->opcode==t->combop) {t->pop=p; break;}
313*1495Sbill 		}
314*1495Sbill 		printf("%s", t->pop->opstring);
315*1495Sbill 		if (t->code) printf("\t%s", t->code);
316*1495Sbill 		if (t->labno!=0) printf("%cL%d\n",
317*1495Sbill 							(t->code ? ',' : '\t'),
318*1495Sbill 							t->labno);
319*1495Sbill 		else printf("\n");
320*1495Sbill 		continue;
321*1495Sbill 
322*1495Sbill 	case MOVA:
323*1495Sbill 		if (t->labno==0) goto std;
324*1495Sbill 		printf("mova%c\tL%d,%s\n","bwlq"[t->subop-BYTE],t->labno,t->code);
325*1495Sbill 		continue;
326*1495Sbill 
327*1495Sbill 	case JSW:
328*1495Sbill 		if (t->subop!=0) {/* F77JSW */
329*1495Sbill 			printf(".long\tL%d\n",t->labno); continue;
330*1495Sbill 		}
331*1495Sbill 		if (casebas==0) printf("L%d:\n",casebas=isn++);
332*1495Sbill 		printf(".word	L%d-L%d\n", t->labno, casebas);
333*1495Sbill 		continue;
334*1495Sbill 
335*1495Sbill 	}
336*1495Sbill }
337*1495Sbill 
338*1495Sbill char *
339*1495Sbill copy(ap)
340*1495Sbill char *ap;
341*1495Sbill {
342*1495Sbill 	register char *p, *np;
343*1495Sbill 	char *onp;
344*1495Sbill 	register n;
345*1495Sbill 	int na;
346*1495Sbill 
347*1495Sbill 	na = nargs();
348*1495Sbill 	p = ap;
349*1495Sbill 	n = 0;
350*1495Sbill 	if (*p==0)
351*1495Sbill 		return(0);
352*1495Sbill 	do
353*1495Sbill 		n++;
354*1495Sbill 	while (*p++);
355*1495Sbill 	if (na>1) {
356*1495Sbill 		p = (&ap)[1];
357*1495Sbill 		while (*p++)
358*1495Sbill 			n++;
359*1495Sbill 	}
360*1495Sbill 	onp = np = alloc(n);
361*1495Sbill 	p = ap;
362*1495Sbill 	while (*np++ = *p++);
363*1495Sbill 	if (na>1) {
364*1495Sbill 		p = (&ap)[1];
365*1495Sbill 		np--;
366*1495Sbill 		while (*np++ = *p++);
367*1495Sbill 	}
368*1495Sbill 	return(onp);
369*1495Sbill }
370*1495Sbill 
371*1495Sbill #define	OPHS	560
372*1495Sbill struct optab *ophash[OPHS];
373*1495Sbill 
374*1495Sbill opsetup()
375*1495Sbill {
376*1495Sbill 	register struct optab *optp, **ophp;
377*1495Sbill 	register int i,t;
378*1495Sbill 
379*1495Sbill 	for(i=NREG+5;--i>=0;) regs[i]=alloc(20);
380*1495Sbill 	for (optp = optab; optp->opstring[0]; optp++) {
381*1495Sbill 		t=7; i=0; while (--t>=0) i+= i+optp->opstring[t];
382*1495Sbill 		ophp = &ophash[i % OPHS];
383*1495Sbill 		while (*ophp++) {
384*1495Sbill /*			fprintf(stderr,"\ncollision: %d %s %s",
385*1495Sbill /*				ophp-1-ophash,optp->opstring,(*(ophp-1))->opstring);
386*1495Sbill */
387*1495Sbill 			if (ophp > &ophash[OPHS])
388*1495Sbill 				ophp = ophash;
389*1495Sbill 		}
390*1495Sbill 		*--ophp = optp;
391*1495Sbill 	}
392*1495Sbill }
393*1495Sbill 
394*1495Sbill struct optab *
395*1495Sbill oplook()
396*1495Sbill {
397*1495Sbill 	register struct optab *optp,**ophp;
398*1495Sbill 	register char *p,*p2;
399*1495Sbill 	register int t;
400*1495Sbill 	char tempop[20];
401*1495Sbill 	static struct optab OPNULL={"",0};
402*1495Sbill 
403*1495Sbill 	for (p=line, p2=tempop; *p && !isspace(*p); *p2++= *p++); *p2=0; p2=p;
404*1495Sbill 	while (isspace(*p2)) ++p2; curlp=p2;
405*1495Sbill 	t=0; while(--p>=line) t += t+*p; ophp = &ophash[t % OPHS];
406*1495Sbill 	while (optp = *ophp) {
407*1495Sbill 		if (equstr(tempop,optp->opstring)) return(optp);
408*1495Sbill 		if ((++ophp) >= &ophash[OPHS]) ophp = ophash;
409*1495Sbill 	}
410*1495Sbill 	curlp = line;
411*1495Sbill 	return(&OPNULL);
412*1495Sbill }
413*1495Sbill 
414*1495Sbill refcount()
415*1495Sbill {
416*1495Sbill 	register struct node *p, *lp;
417*1495Sbill 	struct node *labhash[LABHS];
418*1495Sbill 	register struct node **hp;
419*1495Sbill 
420*1495Sbill 	for (hp = labhash; hp < &labhash[LABHS];)
421*1495Sbill 		*hp++ = 0;
422*1495Sbill 	for (p = first.forw; p!=0; p = p->forw)
423*1495Sbill 		if (p->op==LABEL) {
424*1495Sbill 			labhash[p->labno % LABHS] = p;
425*1495Sbill 			p->refc = 0;
426*1495Sbill 		}
427*1495Sbill 	for (p = first.forw; p!=0; p = p->forw) {
428*1495Sbill 		if (p->combop==JBR || p->op==CBR || p->op==JSW || p->op==JMP
429*1495Sbill 		  || p->op==SOBGEQ || p->op==SOBGTR || p->op==AOBLEQ || p->op==AOBLSS
430*1495Sbill 		  || p->op==ACB || (p->op==MOVA && p->labno!=0)) {
431*1495Sbill 			p->ref = 0;
432*1495Sbill 			lp = labhash[p->labno % LABHS];
433*1495Sbill 			if (lp==0 || p->labno!=lp->labno)
434*1495Sbill 			for (lp = first.forw; lp!=0; lp = lp->forw) {
435*1495Sbill 				if (lp->op==LABEL && p->labno==lp->labno)
436*1495Sbill 					break;
437*1495Sbill 			}
438*1495Sbill 			if (lp) {
439*1495Sbill 				hp = nonlab(lp)->back;
440*1495Sbill 				if (hp!=lp) {
441*1495Sbill 					p->labno = hp->labno;
442*1495Sbill 					lp = hp;
443*1495Sbill 				}
444*1495Sbill 				p->ref = lp;
445*1495Sbill 				lp->refc++;
446*1495Sbill 			}
447*1495Sbill 		}
448*1495Sbill 	}
449*1495Sbill 	for (p = first.forw; p!=0; p = p->forw)
450*1495Sbill 		if (p->op==LABEL && p->refc==0
451*1495Sbill 		 && (lp = nonlab(p))->op && lp->op!=JSW)
452*1495Sbill 			decref(p);
453*1495Sbill }
454*1495Sbill 
455*1495Sbill iterate()
456*1495Sbill {
457*1495Sbill 	register struct node *p, *rp, *p1;
458*1495Sbill 
459*1495Sbill 	nchange = 0;
460*1495Sbill 	for (p = first.forw; p!=0; p = p->forw) {
461*1495Sbill 		if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) {
462*1495Sbill 			rp = nonlab(p->ref);
463*1495Sbill 			if (rp->op==JBR && rp->labno && p->labno!=rp->labno) {
464*1495Sbill 				nbrbr++;
465*1495Sbill 				p->labno = rp->labno;
466*1495Sbill 				decref(p->ref);
467*1495Sbill 				rp->ref->refc++;
468*1495Sbill 				p->ref = rp->ref;
469*1495Sbill 				nchange++;
470*1495Sbill 			}
471*1495Sbill 		}
472*1495Sbill #ifndef COPYCODE
473*1495Sbill 		if (p->op==CBR && (p1 = p->forw)->combop==JBR) {/* combop: RET problems */
474*1495Sbill #else
475*1495Sbill 		if (p->op==CBR && (p1 = p->forw)->combop==JBR &&
476*1495Sbill 		    p->ref) {/* combop: RET problems */
477*1495Sbill #endif
478*1495Sbill 			rp = p->ref;
479*1495Sbill 			do
480*1495Sbill 				rp = rp->back;
481*1495Sbill 			while (rp->op==LABEL);
482*1495Sbill 			if (rp==p1) {
483*1495Sbill 				decref(p->ref);
484*1495Sbill 				p->ref = p1->ref;
485*1495Sbill 				p->labno = p1->labno;
486*1495Sbill #ifdef COPYCODE
487*1495Sbill 				if (p->labno == 0)
488*1495Sbill 					p->code = p1->code;
489*1495Sbill #endif
490*1495Sbill 				p1->forw->back = p;
491*1495Sbill 				p->forw = p1->forw;
492*1495Sbill 				p->subop = revbr[p->subop];
493*1495Sbill 				p->pop=0;
494*1495Sbill 				nchange++;
495*1495Sbill 				nskip++;
496*1495Sbill 			}
497*1495Sbill 		}
498*1495Sbill 		if (p->op==JBR || p->op==JMP) {
499*1495Sbill 			while (p->forw && p->forw->op!=LABEL && p->forw->op!=DLABEL
500*1495Sbill 				&& p->forw->op!=EROU && p->forw->op!=END
501*1495Sbill 				&& p->forw->op!=ALIGN
502*1495Sbill 				&& p->forw->op!=0 && p->forw->op!=DATA) {
503*1495Sbill 				nchange++;
504*1495Sbill 				iaftbr++;
505*1495Sbill 				if (p->forw->ref)
506*1495Sbill 					decref(p->forw->ref);
507*1495Sbill 				p->forw = p->forw->forw;
508*1495Sbill 				p->forw->back = p;
509*1495Sbill 			}
510*1495Sbill 			rp = p->forw;
511*1495Sbill 			while (rp && rp->op==LABEL) {
512*1495Sbill 				if (p->ref == rp) {
513*1495Sbill 					p->back->forw = p->forw;
514*1495Sbill 					p->forw->back = p->back;
515*1495Sbill 					p = p->back;
516*1495Sbill 					decref(rp);
517*1495Sbill 					nchange++;
518*1495Sbill 					njp1++;
519*1495Sbill 					break;
520*1495Sbill 				}
521*1495Sbill 				rp = rp->forw;
522*1495Sbill 			}
523*1495Sbill 			xjump(p);
524*1495Sbill 			p = codemove(p);
525*1495Sbill 		}
526*1495Sbill 	}
527*1495Sbill }
528*1495Sbill 
529*1495Sbill xjump(p1)
530*1495Sbill register struct node *p1;
531*1495Sbill {
532*1495Sbill 	register struct node *p2, *p3;
533*1495Sbill 	int nxj;
534*1495Sbill 
535*1495Sbill 	nxj = 0;
536*1495Sbill 	if ((p2 = p1->ref)==0)
537*1495Sbill 		return(0);
538*1495Sbill 	for (;;) {
539*1495Sbill 		while ((p1 = p1->back) && p1->op==LABEL);
540*1495Sbill 		while ((p2 = p2->back) && p2->op==LABEL);
541*1495Sbill 		if (!equop(p1, p2) || p1==p2)
542*1495Sbill 			return(nxj);
543*1495Sbill 		p3 = insertl(p2);
544*1495Sbill 		p1->combop = JBR;
545*1495Sbill 		p1->pop=0;
546*1495Sbill 		p1->ref = p3;
547*1495Sbill 		p1->labno = p3->labno;
548*1495Sbill 		p1->code = 0;
549*1495Sbill 		nxj++;
550*1495Sbill 		nxjump++;
551*1495Sbill 		nchange++;
552*1495Sbill 	}
553*1495Sbill }
554*1495Sbill 
555*1495Sbill struct node *
556*1495Sbill insertl(op)
557*1495Sbill register struct node *op;
558*1495Sbill {
559*1495Sbill 	register struct node *lp;
560*1495Sbill 
561*1495Sbill 	if (op->op == LABEL) {
562*1495Sbill 		op->refc++;
563*1495Sbill 		return(op);
564*1495Sbill 	}
565*1495Sbill 	if (op->back->op == LABEL) {
566*1495Sbill 		op = op->back;
567*1495Sbill 		op->refc++;
568*1495Sbill 		return(op);
569*1495Sbill 	}
570*1495Sbill 	lp = alloc(sizeof first);
571*1495Sbill 	lp->combop = LABEL;
572*1495Sbill 	lp->labno = isn++;
573*1495Sbill 	lp->ref = 0;
574*1495Sbill 	lp->code = 0;
575*1495Sbill 	lp->refc = 1;
576*1495Sbill 	lp->back = op->back;
577*1495Sbill 	lp->forw = op;
578*1495Sbill 	op->back->forw = lp;
579*1495Sbill 	op->back = lp;
580*1495Sbill 	return(lp);
581*1495Sbill }
582*1495Sbill 
583*1495Sbill struct node *
584*1495Sbill codemove(ap)
585*1495Sbill struct node *ap;
586*1495Sbill {
587*1495Sbill 	register struct node *p1, *p2, *p3;
588*1495Sbill 	struct node *t, *tl;
589*1495Sbill 	int n;
590*1495Sbill 
591*1495Sbill 	p1 = ap;
592*1495Sbill /* last clause to avoid infinite loop on partial compiler droppings:
593*1495Sbill 	L183:	jbr L179
594*1495Sbill 	L191:	jbr L179
595*1495Sbill 			casel r0,$0,$1
596*1495Sbill 	L193:	.word L183-L193
597*1495Sbill 			.word L191-L193
598*1495Sbill 	L179:	ret
599*1495Sbill */
600*1495Sbill 	if (p1->op!=JBR || (p2 = p1->ref)==0 || p2==p1->forw)
601*1495Sbill 		return(p1);
602*1495Sbill 	while (p2->op == LABEL)
603*1495Sbill 		if ((p2 = p2->back) == 0)
604*1495Sbill 			return(p1);
605*1495Sbill 	if (p2->op!=JBR && p2->op!=JMP)
606*1495Sbill 		goto ivloop;
607*1495Sbill 	p2 = p2->forw;
608*1495Sbill 	p3 = p1->ref;
609*1495Sbill 	while (p3) {
610*1495Sbill 		if (p3->op==JBR || p3->op==JMP) {
611*1495Sbill 			if (p1==p3)
612*1495Sbill 				return(p1);
613*1495Sbill 			ncmot++;
614*1495Sbill 			nchange++;
615*1495Sbill 			p1->back->forw = p2;
616*1495Sbill 			p1->forw->back = p3;
617*1495Sbill 			p2->back->forw = p3->forw;
618*1495Sbill 			p3->forw->back = p2->back;
619*1495Sbill 			p2->back = p1->back;
620*1495Sbill 			p3->forw = p1->forw;
621*1495Sbill 			decref(p1->ref);
622*1495Sbill 			return(p2);
623*1495Sbill 		} else
624*1495Sbill 			p3 = p3->forw;
625*1495Sbill 	}
626*1495Sbill 	return(p1);
627*1495Sbill ivloop:
628*1495Sbill 	if (p1->forw->op!=LABEL)
629*1495Sbill 		return(p1);
630*1495Sbill 	p3 = p2 = p2->forw;
631*1495Sbill 	n = 16;
632*1495Sbill 	do {
633*1495Sbill 		if ((p3 = p3->forw) == 0 || p3==p1 || --n==0)
634*1495Sbill 			return(p1);
635*1495Sbill 	} while (p3->op!=CBR || p3->labno!=p1->forw->labno);
636*1495Sbill 	do
637*1495Sbill 		if ((p1 = p1->back) == 0)
638*1495Sbill 			return(ap);
639*1495Sbill 	while (p1!=p3);
640*1495Sbill 	p1 = ap;
641*1495Sbill 	tl = insertl(p1);
642*1495Sbill 	p3->subop = revbr[p3->subop];
643*1495Sbill 	p3->pop=0;
644*1495Sbill 	decref(p3->ref);
645*1495Sbill 	p2->back->forw = p1;
646*1495Sbill 	p3->forw->back = p1;
647*1495Sbill 	p1->back->forw = p2;
648*1495Sbill 	p1->forw->back = p3;
649*1495Sbill 	t = p1->back;
650*1495Sbill 	p1->back = p2->back;
651*1495Sbill 	p2->back = t;
652*1495Sbill 	t = p1->forw;
653*1495Sbill 	p1->forw = p3->forw;
654*1495Sbill 	p3->forw = t;
655*1495Sbill 	p2 = insertl(p1->forw);
656*1495Sbill 	p3->labno = p2->labno;
657*1495Sbill #ifdef COPYCODE
658*1495Sbill 	if (p3->labno == 0)
659*1495Sbill 		p3->code = p2->code;
660*1495Sbill #endif
661*1495Sbill 	p3->ref = p2;
662*1495Sbill 	decref(tl);
663*1495Sbill 	if (tl->refc<=0)
664*1495Sbill 		nrlab--;
665*1495Sbill 	loopiv++;
666*1495Sbill 	nchange++;
667*1495Sbill 	return(p3);
668*1495Sbill }
669*1495Sbill 
670*1495Sbill comjump()
671*1495Sbill {
672*1495Sbill 	register struct node *p1, *p2, *p3;
673*1495Sbill 
674*1495Sbill 	for (p1 = first.forw; p1!=0; p1 = p1->forw)
675*1495Sbill 		if (p1->op==JBR && ((p2 = p1->ref) && p2->refc > 1
676*1495Sbill 				|| p1->subop==RET || p1->subop==RSB))
677*1495Sbill 			for (p3 = p1->forw; p3!=0; p3 = p3->forw)
678*1495Sbill 				if (p3->op==JBR && p3->ref == p2)
679*1495Sbill 					backjmp(p1, p3);
680*1495Sbill }
681*1495Sbill 
682*1495Sbill backjmp(ap1, ap2)
683*1495Sbill struct node *ap1, *ap2;
684*1495Sbill {
685*1495Sbill 	register struct node *p1, *p2, *p3;
686*1495Sbill 
687*1495Sbill 	p1 = ap1;
688*1495Sbill 	p2 = ap2;
689*1495Sbill 	for(;;) {
690*1495Sbill 		while ((p1 = p1->back) && p1->op==LABEL);
691*1495Sbill 		p2 = p2->back;
692*1495Sbill 		if (equop(p1, p2)) {
693*1495Sbill 			p3 = insertl(p1);
694*1495Sbill 			p2->back->forw = p2->forw;
695*1495Sbill 			p2->forw->back = p2->back;
696*1495Sbill 			p2 = p2->forw;
697*1495Sbill 			decref(p2->ref);
698*1495Sbill 			p2->combop = JBR; /* to handle RET */
699*1495Sbill 			p2->pop=0;
700*1495Sbill 			p2->labno = p3->labno;
701*1495Sbill #ifdef COPYCODE
702*1495Sbill 			p2->code = 0;
703*1495Sbill #endif
704*1495Sbill 			p2->ref = p3;
705*1495Sbill 			nchange++;
706*1495Sbill 			ncomj++;
707*1495Sbill 		} else
708*1495Sbill 			return;
709*1495Sbill 	}
710*1495Sbill }
711