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