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