xref: /csrg-svn/old/pcc/c2.tahoe/c20.c (revision 31416)
126440Ssam #ifndef lint
2*31416Sbostic static char sccsid[] = "@(#)c20.c	1.5 (Berkeley/CCI) 06/06/87";
326440Ssam #endif
426440Ssam 
526440Ssam /*
626440Ssam  *	 C object code improver
726440Ssam  */
826440Ssam 
926440Ssam #include "c2.h"
1026440Ssam #include <stdio.h>
1126440Ssam #include <ctype.h>
1226440Ssam 
1326440Ssam char _sibuf[BUFSIZ], _sobuf[BUFSIZ];
1426440Ssam int ioflag;
1526440Ssam int isn	= 2000000;
1626440Ssam struct optab *oplook();
1726440Ssam struct optab *getline();
1826440Ssam long lgensym[10] =
1926440Ssam   {100000L,200000L,300000L,400000L,500000L,600000L,700000L,800000L,900000L,1000000L};
2026440Ssam 
2126440Ssam /* VARARGS1 */
error(s1,s2)2226440Ssam error(s1, s2)
2326440Ssam 	char *s1, *s2;
2426440Ssam {
2526440Ssam 	fprintf(stderr, s1, s2);
2626440Ssam 	exit(1);
2726440Ssam }
2826440Ssam 
2926440Ssam struct node *
alloc(an)3026440Ssam alloc(an)
3126440Ssam {
3226440Ssam 	register int n;
3326440Ssam 	register char *p;
3426440Ssam 
3526440Ssam 	n = an;
3626440Ssam 	n+=sizeof(char *)-1;
3726440Ssam 	n &= ~(sizeof(char *)-1);
3826440Ssam 	if (lasta+n >= lastr) {
3926440Ssam 		if (sbrk(2000) == -1)
4026440Ssam 			error("Optimizer: out of space\n");
4126440Ssam 		lastr += 2000;
4226440Ssam 	}
4326440Ssam 	p = lasta;
4426440Ssam 	lasta += n;
4526440Ssam 	return((struct node *)p);
4626440Ssam }
4726440Ssam 
main(argc,argv)4826440Ssam main(argc, argv)
4926440Ssam char **argv;
5026440Ssam {
5126440Ssam 	register int niter, maxiter, isend;
5226440Ssam 	int nflag,infound;
5326440Ssam 
5426440Ssam 	nflag = 0; infound=0; argc--; argv++;
5526440Ssam 	while (argc>0) {/* get flags */
5626440Ssam 		if (**argv=='-') {
5726440Ssam 			switch ((*argv)[1]) {
5829670Ssam 			case 'a': aobflag++; break;
5926440Ssam 			case 'n': nflag++; break;
6026440Ssam 			case 'd': debug++; break;
6126440Ssam 			case 'f': fortflg++; break;
6226440Ssam 			}
6326440Ssam 		} else if (infound==0) {
6426440Ssam 			if (freopen(*argv, "r", stdin) ==NULL)
6526440Ssam 				error("C2: can't find %s\n", *argv);
66*31416Sbostic 			++infound;
6726440Ssam 		} else if (freopen(*argv, "w", stdout) ==NULL)
6826440Ssam 			error("C2: can't create %s\n", *argv);
6926440Ssam 		argc--; argv++;
7026440Ssam 	}
71*31416Sbostic 	setbuf(stdin,_sibuf);
72*31416Sbostic 	setbuf(stdout,_sobuf);
7326440Ssam 	lasta = lastr = (char *)sbrk(2);
7426440Ssam 	opsetup();
7526440Ssam 	lasta = firstr = lastr = (char *)alloc(0);
7626440Ssam 	maxiter = 0;
7726440Ssam 	do {
7826440Ssam 		isend = input();
7926440Ssam 		niter = 0;
8026440Ssam 		bmove();
8126440Ssam 		do {
8226440Ssam 			refcount();
8326440Ssam 			do {
8426440Ssam 				iterate();
8526440Ssam 				clearreg();
8626440Ssam 				niter++;
8726440Ssam 			} while (nchange);
8826440Ssam 			comjump();
8926440Ssam 			rmove();
9026440Ssam 		} while (nchange || jumpsw());
9126440Ssam 		addaob();
9229670Ssam 		interleave();
9326440Ssam 		output();
9426440Ssam 		if (niter > maxiter)
9526440Ssam 			maxiter = niter;
9626440Ssam 		lasta = firstr;
9726440Ssam 	} while (isend);
9826440Ssam 	if (nflag) {
9926440Ssam 		score("iterations", maxiter);
10026440Ssam 		score("jumps to jumps", nbrbr);
10126440Ssam 		score("inst. after jumps", iaftbr);
10226440Ssam 		score("jumps to .+1", njp1);
10326440Ssam 		score("redundant labels", nrlab);
10426440Ssam 		score("cross-jumps", nxjump);
10526440Ssam 		score("code motions", ncmot);
10626440Ssam 		score("branches reversed", nrevbr);
10726440Ssam 		score("redundant moves", redunm);
10826440Ssam 		score("simplified addresses", nsaddr);
10926440Ssam 		score("loops inverted", loopiv);
11026440Ssam 		score("redundant jumps", nredunj);
11126440Ssam 		score("common seqs before jmp's", ncomj);
11226440Ssam 		score("skips over jumps", nskip);
11326440Ssam 		score("aob's added", naob);
11426440Ssam 		score("redundant tst's", nrtst);
11526440Ssam 		score("jump on bit", nbj);
11626440Ssam 		score("redundant accumulator stores", nst);
11726440Ssam 		score("redundant accumulator loads", nld);
11826440Ssam 		score("K core", ((unsigned)lastr+01777) >> 10);
11926440Ssam 	}
12026440Ssam 	putc('\n',stdout);
12126440Ssam 	fflush(stdout); exit(0);
12226440Ssam }
12326440Ssam 
score(s,n)12426440Ssam score(s, n)
12526440Ssam 	char *s;
12626440Ssam {
12726440Ssam 	if(n > 0)
12826440Ssam 		fprintf(stderr, "%d %s\n", n, s);
12926440Ssam }
13026440Ssam 
input()13126440Ssam input()
13226440Ssam {
13326440Ssam 	register struct node *p, *lastp;
13426440Ssam 	register struct optab *op; register char *cp1;
13526440Ssam 	static struct optab F77JSW = {".long", JSW, 1};
13626440Ssam 
13726440Ssam 	lastp = &first;
13826440Ssam 	for (;;) {
13926440Ssam 	  top:
14026440Ssam 		op = getline();
14126440Ssam 		if (debug && op==0) fprintf(stderr,"? %s\n",line);
14226440Ssam 		switch (op->opcod) {
14326440Ssam 
14426440Ssam 		case LABEL:
14526440Ssam 			p = alloc(sizeof first);
14626440Ssam 			if (isdigit(line[0]) && (p->labno=locdef(line)) ||
14726440Ssam 			  (line[0] == 'L') && (p->labno=getnum(line+1))) {
14826440Ssam 				p->op = LABEL; p->subop = 0;
14926440Ssam 				if (p->labno<100000L && isn<=p->labno) isn=1+p->labno;
15026440Ssam 				p->code = 0;
15126440Ssam 			} else {
15226440Ssam 				p->op = DLABEL; p->subop = 0;
15326440Ssam 				p->labno = 0;
15426440Ssam 				p->code = copy(line);
15526440Ssam 			}
15626440Ssam 			break;
15726440Ssam 
15826440Ssam 		case LGEN:
15926440Ssam 			if (*curlp!='L' && !locuse(curlp)) goto std;
16026440Ssam 			op= &F77JSW;
16126440Ssam 		case JBR:
16226440Ssam 			if (op->opcod==JBR && (op->subopcod&0xF)==RET) goto std;
16326440Ssam 		case CBR:
16426440Ssam 		case JMP:
16526440Ssam 		case JSW:
16626440Ssam 		case AOBLEQ: case AOBLSS:
16726440Ssam 			p = alloc(sizeof first);
16826440Ssam 			p->op = op->opcod; p->subop = op->subopcod;
16926440Ssam 			p->code=0; cp1=curlp;
17026440Ssam 			if ((!isdigit(*cp1) || 0==(p->labno=locuse(cp1))) &&
17126440Ssam 			  (*cp1!='L' || 0==(p->labno = getnum(cp1+1)))) {/* jbs, etc.? */
17226440Ssam 				while (*cp1++); while (*--cp1!=',' && cp1!=curlp);
17326440Ssam 				if (cp1==curlp ||
17426440Ssam 				  (!isdigit(*++cp1) || 0==(p->labno=locuse(cp1))) &&
17526440Ssam 				  (*cp1!='L' || 0==(p->labno=getnum(cp1+1))))
17626440Ssam 					p->labno = 0;
17726440Ssam 				else *--cp1=0;
17826440Ssam 				p->code = copy(curlp);
17926440Ssam 			}
18026440Ssam 			if (isn<=p->labno) isn=1+p->labno;
18126440Ssam 			break;
18226440Ssam 
18326440Ssam 		case MOVA:
18426440Ssam 			p=alloc(sizeof first);
18526440Ssam 			p->op = op->opcod; p->subop = op->subopcod;
18626440Ssam 			p->code=0; cp1=curlp+1;
18726440Ssam 			if (cp1[-1]=='L' || isdigit(cp1[-1])) {
18826440Ssam 				while (*cp1++!=','); *--cp1=0;
18926440Ssam 				if (0!=(p->labno=locuse(curlp)) ||
19026440Ssam 					0!=(p->labno=getnum(curlp+1))) p->code=copy(cp1+1);
19126440Ssam 				else {*cp1=','; p->code=copy(curlp);}
19226440Ssam 			} else {p->code=copy(--cp1); p->labno=0;}
19326440Ssam 			break;
19426440Ssam 
19526440Ssam 		case MOV:
19626440Ssam 			p=alloc(sizeof first);
19726440Ssam 			p->op = op->opcod; p->subop = op->subopcod;
19826440Ssam 			p->code = copy(curlp);
19926440Ssam 			p->labno = 0;
20026440Ssam 			cp1=curlp+1;
20126440Ssam 			if ((cp1[-1]=='$') && (cp1[0] == 'L')) {
20226440Ssam 				while (*cp1++!=','); *--cp1 =0;
20326440Ssam 				p->labno = getnum(curlp+2);
20426440Ssam 				}
20526440Ssam 			break;
20626440Ssam 		case MOVBLK:	/* used implicitly */
20726440Ssam 			curlp = "(r0),(r1),(r2)";
20826440Ssam 			goto std;
20926440Ssam 
21026440Ssam 		case SET:
21126440Ssam 		case COMM:
21226440Ssam 		case LCOMM:
21326440Ssam 			printf("%s\n",line); goto top;
21426440Ssam 
21526440Ssam 		case BSS:
21626440Ssam 		case DATA:
21726440Ssam 			for (;;) {
21826440Ssam 				printf("%s%c",line,(op->opcod==LABEL ? ':' : '\n'));
21926440Ssam 				if (op->opcod==TEXT) goto top;
22026440Ssam 				if (END==(op=getline())->opcod) {/* dangling .data is bad for you */
22126440Ssam 					printf(".text\n");
22226440Ssam 					break;
22326440Ssam 				}
22426440Ssam 			}
22526440Ssam 
22626440Ssam 		std:
22726440Ssam 		default:
22826440Ssam 			p = alloc(sizeof first);
22926440Ssam 			p->op = op->opcod; p->subop = op->subopcod;
23026440Ssam 			p->labno = 0;
23126440Ssam 			p->code = copy(curlp);
23226440Ssam 			break;
23326440Ssam 
23426440Ssam 		}
23526440Ssam 		p->forw = 0;
23626440Ssam 		p->back = lastp;
23726440Ssam 		p->pop = op;
23826440Ssam 		lastp->forw = p;
23926440Ssam 		lastp = p;
24026440Ssam 		p->ref = 0;
24126440Ssam 		if (p->op==CASE) {
24226440Ssam 			char *lp; int ncase;
24326440Ssam 			lp=curlp; while (*lp++); while (*--lp!='$'); ncase=getnum(lp+1);
24426440Ssam 			if (ALIGN!=(getline())->opcod || LABEL!=(getline())->opcod) caserr();
24526440Ssam 			do {
24626440Ssam 				if (WGEN!=(getline())->opcod) caserr();
24726440Ssam 				p = alloc(sizeof first);
24826440Ssam 				p->op = JSW; p->subop = 0;
24926440Ssam 				p->code = 0;
25026440Ssam 				lp=curlp; while(*lp++!='-'); *--lp=0; p->labno=getnum(curlp+1);
25126440Ssam 				if (isn<=p->labno) isn=1+p->labno;
25226440Ssam 				p->forw = 0; p->back = lastp; lastp->forw = p; lastp = p;
25326440Ssam 				p->ref = 0; p->pop=0;
25426440Ssam 			} while (--ncase>=0);
25526440Ssam 		}
25626440Ssam 		if (op->opcod==EROU)
25726440Ssam 			return(1);
25826440Ssam 		if (op->opcod==END)
25926440Ssam 			return(0);
26026440Ssam 	}
26126440Ssam }
26226440Ssam 
caserr()26326440Ssam caserr()
26426440Ssam {
26526440Ssam 	error("C2: improper casel instruction\n");
26626440Ssam }
26726440Ssam 
26826440Ssam struct optab *
getline()26926440Ssam getline()
27026440Ssam {
27126440Ssam 	register char *lp;
27226440Ssam 	register int c;
27326440Ssam 	static struct optab OPLABEL={"",LABEL,0};
27426440Ssam 	static struct optab OPEND={"",END,0};
27526440Ssam 
27626440Ssam 	lp = line;
27726440Ssam again:
27826440Ssam 	while (EOF!=(c=getchar()) && isspace(c));
27926440Ssam 	if (c=='#') {
28026440Ssam 		while((c=getchar()) != '\n');
28126440Ssam 		goto again;
28226440Ssam 	}
28326440Ssam 	while (EOF!=c) {
28426440Ssam 		if (c==':') {
28526440Ssam 			*lp++ = 0;
28626440Ssam 			return(&OPLABEL);
28726440Ssam 		}
28826440Ssam 		if (c=='\n') {
28926440Ssam 			*lp++ = 0;
29026440Ssam 			return(oplook());
29126440Ssam 		}
29226440Ssam 		if (c=='"')
29326440Ssam 			do {
29426440Ssam 				if (c=='\\') {
29526440Ssam 					*lp++ = c;
29626440Ssam 					c = getchar();
29726440Ssam 				}
29826440Ssam 				*lp++ = c;
29926440Ssam 				c = getchar();
30026440Ssam 			} while(c!='"');
30126440Ssam 		*lp++ = c;
30226440Ssam 		c = getchar();
30326440Ssam 	}
30426440Ssam 	*lp++ = 0;
30526440Ssam 	return(&OPEND);
30626440Ssam }
30726440Ssam 
30826440Ssam long
getnum(p)30926440Ssam getnum(p)
31026440Ssam register char *p;
31126440Ssam {
31226440Ssam 	register int c, neg, n;
31326440Ssam 
31426440Ssam 	n = 0; neg=0; if (*p=='-') {++neg; ++p;}
31526440Ssam 	while (isdigit(c = *p++)) {
31626440Ssam 		 c -= '0'; n *= 10; if (neg) n -= c; else n += c;
31726440Ssam 	}
31826440Ssam 	if (*--p != 0)
31926440Ssam 		return(0);
32026440Ssam 	return(n);
32126440Ssam }
32226440Ssam 
locuse(p)32326440Ssam locuse(p)
32426440Ssam register char *p;
32526440Ssam {
32626440Ssam 
32726440Ssam 	if (!isdigit(p[0]) || p[1] != 'f' && p[1] != 'b' || p[2]) return(0);
32826440Ssam 	return (lgensym[p[0] - '0'] - (p[1] == 'b'));
32926440Ssam }
33026440Ssam 
locdef(p)33126440Ssam locdef(p)
33226440Ssam register char *p;
33326440Ssam {
33426440Ssam 
33526440Ssam 	if (!isdigit(p[0]) || p[1]) return(0);
33626440Ssam 	return (lgensym[p[0] - '0']++);
33726440Ssam }
33826440Ssam 
output()33926440Ssam output()
34026440Ssam {
34126440Ssam 	register struct node *t;
34226440Ssam 	int casebas;
34326440Ssam 
34426440Ssam 	t = &first;
34526440Ssam 	while (t = t->forw) switch (t->op) {
34626440Ssam 
34726440Ssam 	case END:
34826440Ssam 		fflush(stdout);
34926440Ssam 		return;
35026440Ssam 
35126440Ssam 	case LABEL:
35226440Ssam 		printf("L%d:", t->labno);
35326440Ssam 		continue;
35426440Ssam 
35526440Ssam 	case DLABEL:
35626440Ssam 		printf("%s:", t->code);
35726440Ssam 		continue;
35826440Ssam 
35926440Ssam 	case CASE:
36026440Ssam 		casebas=0;
36126440Ssam 
36226440Ssam 	default: std:
36326440Ssam 		if (t->pop==0) {/* must find it */
36426440Ssam 			register struct optab *p;
36526440Ssam 			for (p=optab; p->opstring[0]; ++p)
36626440Ssam 				if (p->opcod==t->op && p->subopcod==t->subop) {
36726440Ssam 					t->pop=p; break;}
36826440Ssam 		}
36926440Ssam 		printf("%s", t->pop->opstring);
37026440Ssam 		if (t->code) printf("\t%s", t->code);
37126440Ssam 		if (t->op != MOV ) {
37226440Ssam 		if (t->labno!=0) printf("%cL%d\n",
37326440Ssam 							(t->code ? ',' : '\t'),
37426440Ssam 							t->labno);
37526440Ssam 
37626440Ssam 		else printf("\n");
37726440Ssam 		}
37826440Ssam 		else printf("\n");
37926440Ssam 		continue;
38026440Ssam 
38126440Ssam 	case MOVA:
38226440Ssam 		if (t->labno==0) goto std;
38326440Ssam 		printf("mova%c\tL%d,%s\n","bwlq"[t->subop-BYTE],t->labno,t->code);
38426440Ssam 		continue;
38526440Ssam 
38626440Ssam 	case MOVBLK:
38726440Ssam 		t->code = 0;
38826440Ssam 		goto std;
38926440Ssam 
39026440Ssam 	case JSW:
39126440Ssam 		if (t->subop!=0) {/* F77JSW */
39226440Ssam 			printf(".long\tL%d\n",t->labno); continue;
39326440Ssam 		}
39426440Ssam 		if (casebas==0) printf(".align 1\nL%d:\n",casebas=isn++);
39526440Ssam 		printf(".word	L%d-L%d\n", t->labno, casebas);
39626440Ssam 		continue;
39726440Ssam 
39826440Ssam 	}
39926440Ssam }
40026440Ssam 
40126440Ssam char *
copy(ap)40226440Ssam copy(ap)
40326440Ssam char *ap;
40426440Ssam {
40526440Ssam 	register char *p, *np, *onp;
40626440Ssam 	register int n;
40726440Ssam 
40826440Ssam 	p = ap;
40926440Ssam 	n = 0;
41026440Ssam 	if (*p==0)
41126440Ssam 		return(0);
41226440Ssam 	do
41326440Ssam 		n++;
41426440Ssam 	while (*p++);
41526440Ssam 	onp = np = (char *)alloc(n);
41626440Ssam 	p = ap;
41726440Ssam 	while (*np++ = *p++);
41826440Ssam 	return(onp);
41926440Ssam }
42026440Ssam 
42126440Ssam #define	OPHS	560
42226440Ssam struct optab *ophash[OPHS];
42326440Ssam 
opsetup()42426440Ssam opsetup()
42526440Ssam {
42626440Ssam 	register struct optab *optp, **ophp;
42726440Ssam 	register int i,t;
42826440Ssam 
42926440Ssam 	for(i=RT1+5;--i>=0;) regs[i]=(char *)alloc(C2_ASIZE);
43026440Ssam 	for (optp = optab; optp->opstring[0]; optp++) {
43126440Ssam 		t=7; i=0; while (--t>=0) i+= i+optp->opstring[t];
43226440Ssam 		ophp = &ophash[i % OPHS];
43326440Ssam 		while (*ophp++) {
43426440Ssam /*			fprintf(stderr,"\ncollision: %d %s %s",
43526440Ssam /*				ophp-1-ophash,optp->opstring,(*(ophp-1))->opstring);
43626440Ssam */
43726440Ssam 			if (ophp > &ophash[OPHS])
43826440Ssam 				ophp = ophash;
43926440Ssam 		}
44026440Ssam 		*--ophp = optp;
44126440Ssam 	}
44226440Ssam }
44326440Ssam 
44426440Ssam struct optab *
oplook()44526440Ssam oplook()
44626440Ssam {
44726440Ssam 	register struct optab *optp,**ophp;
44826440Ssam 	register char *p,*p2;
44926440Ssam 	register int t;
45026440Ssam 	char tempop[20];
45129775Ssam 	static struct optab OPNULL={"",NIL,0};
45226440Ssam 
45326440Ssam 	for (p=line, p2=tempop; *p && !isspace(*p); *p2++= *p++); *p2=0; p2=p;
45426440Ssam 	while (isspace(*p2)) ++p2; curlp=p2;
45526440Ssam 	t=0; while(--p>=line) t += t+*p; ophp = &ophash[t % OPHS];
45626440Ssam 	while (optp = *ophp) {
45726440Ssam 		if (equstr(tempop,optp->opstring)) return(optp);
45826440Ssam 		if ((++ophp) >= &ophash[OPHS]) ophp = ophash;
45926440Ssam 	}
46026440Ssam 	curlp = line;
46126440Ssam 	return(&OPNULL);
46226440Ssam }
46326440Ssam 
refcount()46426440Ssam refcount()
46526440Ssam {
46626440Ssam 	register struct node *p, *lp, *np;
46726440Ssam 	struct node *labhash[LABHS];
46826440Ssam 	register struct node **hp;
46926440Ssam 
47026440Ssam 	for (hp = labhash; hp < &labhash[LABHS];)
47126440Ssam 		*hp++ = 0;
47226440Ssam 	for (p = first.forw; p!=0; p = p->forw)
47326440Ssam 		if (p->op==LABEL) {
47426440Ssam 			labhash[p->labno % LABHS] = p;
47526440Ssam 			p->refc = 0;
47626440Ssam 		}
47726440Ssam 	for (p = first.forw; p!=0; p = p->forw) {
47826440Ssam 		if (p->op==JBR && p->subop==0 || p->op==CBR || p->op==JSW || p->op==JMP
47926440Ssam 		  || p->op==AOBLEQ || p->op==AOBLSS
48026440Ssam 		  || (p->op==MOVA && p->labno!=0)
48126440Ssam 	          || (p->op==MOV && p->labno!=0)){
48226440Ssam 			p->ref = 0;
48326440Ssam 			lp = labhash[p->labno % LABHS];
48426440Ssam 			if (lp==0 || p->labno!=lp->labno)
48526440Ssam 			for (lp = first.forw; lp!=0; lp = lp->forw) {
48626440Ssam 				if (lp->op==LABEL && p->labno==lp->labno)
48726440Ssam 					break;
48826440Ssam 			}
48926440Ssam 			if (lp) {
49026440Ssam 				np = nonlab(lp)->back;
49126440Ssam 				if (np!=lp) {
49226440Ssam 					p->labno = np->labno;
49326440Ssam 					lp = np;
49426440Ssam 				}
49526440Ssam 				p->ref = lp;
49626440Ssam 				lp->refc++;
49726440Ssam 			}
49826440Ssam 		}
49926440Ssam 	}
50026440Ssam 	for (p = first.forw; p!=0; p = p->forw)
50126440Ssam 		if (p->op==LABEL && p->refc==0
50226440Ssam 		 && (lp = nonlab(p))->op && lp->op!=JSW)
50326440Ssam 			decref(p);
50426440Ssam }
50526440Ssam 
iterate()50626440Ssam iterate()
50726440Ssam {
50826440Ssam 	register struct node *p, *rp, *p1;
50926440Ssam 
51026440Ssam 	nchange = 0;
51126440Ssam 	for (p = first.forw; p!=0; p = p->forw) {
51226440Ssam 		if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) {
51326440Ssam 			rp = nonlab(p->ref);
51426440Ssam 			if (rp->op==JBR && rp->labno && p->labno!=rp->labno) {
51526440Ssam 				nbrbr++;
51626440Ssam 				p->labno = rp->labno;
51726440Ssam 				decref(p->ref);
51826440Ssam 				rp->ref->refc++;
51926440Ssam 				p->ref = rp->ref;
52026440Ssam 				nchange++;
52126440Ssam 			}
52226440Ssam 		}
52326440Ssam 		if (p->op==CBR && (p1 = p->forw)->op==JBR && p1->subop==0
52426440Ssam #ifdef COPYCODE
52526440Ssam 		 && p->ref
52626440Ssam #endif
52726440Ssam 		    ) {/* RET problems */
52826440Ssam 			rp = p->ref;
52926440Ssam 			do
53026440Ssam 				rp = rp->back;
53126440Ssam 			while (rp->op==LABEL);
53226440Ssam 			if (rp==p1) {
53326440Ssam 				decref(p->ref);
53426440Ssam 				p->ref = p1->ref;
53526440Ssam 				p->labno = p1->labno;
53626440Ssam #ifdef COPYCODE
53726440Ssam 				if (p->labno == 0)
53826440Ssam 					p->code = p1->code;
53926440Ssam #endif
54026440Ssam 				p1->forw->back = p;
54126440Ssam 				p->forw = p1->forw;
54226440Ssam 				p->subop = revbr[p->subop];
54326440Ssam 				p->pop=0;
54426440Ssam 				nchange++;
54526440Ssam 				nskip++;
54626440Ssam 			}
54726440Ssam 		}
54826440Ssam 		if (p->op==JBR || p->op==JMP) {
54926440Ssam 			while ((p1=p->forw)!=0 && p1->op!=LABEL && p1->op!=DLABEL
55026440Ssam 				&& p1->op!=EROU && p1->op!=END
55126440Ssam 				&& p1->op!=ALIGN
55229775Ssam 				&& p1->op!=NIL && p1->op!=DATA) {
55326440Ssam 				nchange++;
55426440Ssam 				iaftbr++;
55526440Ssam 				if (p1->ref)
55626440Ssam 					decref(p1->ref);
55726440Ssam 				p->forw = p1->forw;
55826440Ssam 				p->forw->back = p;
55926440Ssam 			}
56026440Ssam 			rp = p->forw;
56126440Ssam 			while (rp && rp->op==LABEL) {
56226440Ssam 				if (p->ref == rp) {
56326440Ssam 					p->back->forw = p->forw;
56426440Ssam 					p->forw->back = p->back;
56526440Ssam 					p = p->back;
56626440Ssam 					decref(rp);
56726440Ssam 					nchange++;
56826440Ssam 					njp1++;
56926440Ssam 					break;
57026440Ssam 				}
57126440Ssam 				rp = rp->forw;
57226440Ssam 			}
57326440Ssam 			xjump(p);
57426440Ssam 			p = codemove(p);
57526440Ssam 		}
57626440Ssam 	}
57726440Ssam }
57826440Ssam 
xjump(p1)57926440Ssam xjump(p1)
58026440Ssam register struct node *p1;
58126440Ssam {
58226440Ssam 	register struct node *p2, *p3;
58326440Ssam 
58426440Ssam 	if ((p2 = p1->ref)==0)
58526440Ssam 		return;
58626440Ssam 	for (;;) {
58726440Ssam 		while ((p1 = p1->back) && p1->op==LABEL);
58826440Ssam 		while ((p2 = p2->back) && p2->op==LABEL);
58926440Ssam 		if (!equop(p1, p2) || p1==p2)
59026440Ssam 			return;
59126440Ssam 		p3 = insertl(p2);
59226440Ssam 		p1->op = JBR; p1->subop = 0;
59326440Ssam 		p1->pop=0;
59426440Ssam 		p1->ref = p3;
59526440Ssam 		p1->labno = p3->labno;
59626440Ssam 		p1->code = 0;
59726440Ssam 		nxjump++;
59826440Ssam 		nchange++;
59926440Ssam 	}
60026440Ssam }
60126440Ssam 
60226440Ssam struct node *
insertl(op)60326440Ssam insertl(op)
60426440Ssam register struct node *op;
60526440Ssam {
60626440Ssam 	register struct node *lp;
60726440Ssam 
60826440Ssam 	if (op->op == LABEL) {
60926440Ssam 		op->refc++;
61026440Ssam 		return(op);
61126440Ssam 	}
61226440Ssam 	if (op->back->op == LABEL) {
61326440Ssam 		op = op->back;
61426440Ssam 		op->refc++;
61526440Ssam 		return(op);
61626440Ssam 	}
61726440Ssam 	lp = alloc(sizeof first);
61826440Ssam 	lp->op = LABEL; lp->subop = 0;
61926440Ssam 	lp->labno = isn++;
62026440Ssam 	lp->ref = 0;
62126440Ssam 	lp->code = 0;
62226440Ssam 	lp->refc = 1;
62326440Ssam 	lp->back = op->back;
62426440Ssam 	lp->forw = op;
62526440Ssam 	op->back->forw = lp;
62626440Ssam 	op->back = lp;
62726440Ssam 	return(lp);
62826440Ssam }
62926440Ssam 
63026440Ssam struct node *
codemove(ap)63126440Ssam codemove(ap)
63226440Ssam struct node *ap;
63326440Ssam {
63426440Ssam 	register struct node *p1, *p2, *p3;
63526440Ssam 	register struct node *t, *tl;
63626440Ssam 	register int n;
63726440Ssam 
63826440Ssam 	p1 = ap;
63926440Ssam 	if (p1->op!=JBR || (p2 = p1->ref)==0 || p2==p1->forw)
64026440Ssam 		return(p1);
64126440Ssam 	while (p2->op == LABEL)
64226440Ssam 		if ((p2 = p2->back) == 0)
64326440Ssam 			return(p1);
64426440Ssam 	if (p2->op!=JBR && p2->op!=JMP)
64526440Ssam 		goto ivloop;
64626440Ssam 	p2 = p2->forw;
64726440Ssam 	p3 = p1->ref;
64826440Ssam 	while (p3) {
64926440Ssam 		if (p3->op==JBR || p3->op==JMP) {
65026440Ssam 			if (p1==p3)
65126440Ssam 				return(p1);
65226440Ssam 			ncmot++;
65326440Ssam 			nchange++;
65426440Ssam 			p1->back->forw = p2;
65526440Ssam 			p1->forw->back = p3;
65626440Ssam 			p2->back->forw = p3->forw;
65726440Ssam 			p3->forw->back = p2->back;
65826440Ssam 			p2->back = p1->back;
65926440Ssam 			p3->forw = p1->forw;
66026440Ssam 			decref(p1->ref);
66126440Ssam 			return(p2);
66226440Ssam 		} else
66326440Ssam 			p3 = p3->forw;
66426440Ssam 	}
66526440Ssam 	return(p1);
66626440Ssam ivloop:
66726440Ssam 	if (p1->forw->op!=LABEL)
66826440Ssam 		return(p1);
66926440Ssam 	p3 = p2 = p2->forw;
67026440Ssam 	n = 16;
67126440Ssam 	do {
67226440Ssam 		if ((p3 = p3->forw) == 0 || p3==p1 || --n==0)
67326440Ssam 			return(p1);
67426440Ssam 	} while (p3->op!=CBR || p3->labno!=p1->forw->labno);
67526440Ssam 	do
67626440Ssam 		if ((p1 = p1->back) == 0)
67726440Ssam 			return(ap);
67826440Ssam 	while (p1!=p3);
67926440Ssam 	p1 = ap;
68026440Ssam 	tl = insertl(p1);
68126440Ssam 	p3->subop = revbr[p3->subop];
68226440Ssam 	p3->pop=0;
68326440Ssam 	decref(p3->ref);
68426440Ssam 	p2->back->forw = p1;
68526440Ssam 	p3->forw->back = p1;
68626440Ssam 	p1->back->forw = p2;
68726440Ssam 	p1->forw->back = p3;
68826440Ssam 	t = p1->back;
68926440Ssam 	p1->back = p2->back;
69026440Ssam 	p2->back = t;
69126440Ssam 	t = p1->forw;
69226440Ssam 	p1->forw = p3->forw;
69326440Ssam 	p3->forw = t;
69426440Ssam 	p2 = insertl(p1->forw);
69526440Ssam 	p3->labno = p2->labno;
69626440Ssam #ifdef COPYCODE
69726440Ssam 	if (p3->labno == 0)
69826440Ssam 		p3->code = p2->code;
69926440Ssam #endif
70026440Ssam 	p3->ref = p2;
70126440Ssam 	decref(tl);
70226440Ssam 	if (tl->refc<=0)
70326440Ssam 		nrlab--;
70426440Ssam 	loopiv++;
70526440Ssam 	nchange++;
70626440Ssam 	return(p3);
70726440Ssam }
70826440Ssam 
comjump()70926440Ssam comjump()
71026440Ssam {
71126440Ssam 	register struct node *p1, *p2, *p3;
71226440Ssam 
71326440Ssam 	for (p1 = first.forw; p1!=0; p1 = p1->forw)
71426440Ssam 		if (p1->op==JBR && ((p2 = p1->ref) && p2->refc > 1
71526440Ssam 				|| (p1->subop&0xF)==RET))
71626440Ssam 			for (p3 = p1->forw; p3!=0; p3 = p3->forw)
71726440Ssam 				if (p3->op==JBR && p3->ref == p2)
71826440Ssam 					backjmp(p1, p3);
71926440Ssam }
72026440Ssam 
72126440Ssam backjmp(ap1, ap2)
72226440Ssam struct node *ap1, *ap2;
72326440Ssam {
72426440Ssam 	register struct node *p1, *p2, *p3;
72526440Ssam 
72626440Ssam 	p1 = ap1;
72726440Ssam 	p2 = ap2;
72826440Ssam 	for(;;) {
72926440Ssam 		while ((p1 = p1->back) && p1->op==LABEL);
73026440Ssam 		p2 = p2->back;
73126440Ssam 		if (equop(p1, p2)) {
73226440Ssam 			p3 = insertl(p1);
73326440Ssam 			p2->back->forw = p2->forw;
73426440Ssam 			p2->forw->back = p2->back;
73526440Ssam 			p2 = p2->forw;
73626440Ssam 			decref(p2->ref);
73726440Ssam 			p2->op = JBR; p2->subop = 0; /* to handle RET */
73826440Ssam 			p2->pop=0;
73926440Ssam 			p2->labno = p3->labno;
74026440Ssam #ifdef COPYCODE
74126440Ssam 			p2->code = 0;
74226440Ssam #endif
74326440Ssam 			p2->ref = p3;
74426440Ssam 			nchange++;
74526440Ssam 			ncomj++;
74626440Ssam 		} else
74726440Ssam 			return;
74826440Ssam 	}
74926440Ssam }
750