xref: /csrg-svn/old/pcc/c2.vax/c20.c (revision 43497)
114572Ssam #ifndef lint
2*43497Sbostic static	char sccsid[] = "@(#)c20.c	4.11 (Berkeley) 06/23/90";
314572Ssam #endif
414572Ssam 
51495Sbill /*
61495Sbill  *	 C object code improver
71495Sbill  */
81495Sbill 
91495Sbill #include "c2.h"
101495Sbill #include <stdio.h>
111495Sbill #include <ctype.h>
1218380Sralph #include <sys/types.h>
131495Sbill 
1424398Smckusick char *malloc();
1524398Smckusick char firstr[sizeof (char *)];
1624398Smckusick char *currentb;
1724398Smckusick char *newa;
1824398Smckusick char *lasta;
1924398Smckusick char *lastr;
2024398Smckusick int ncore;
2124398Smckusick 
221495Sbill int ioflag;
2317719Sralph int fflag;
2424398Smckusick 
251508Sbill long	isn	= 2000000;
2624398Smckusick 
271495Sbill struct optab *oplook();
281495Sbill struct optab *getline();
2924398Smckusick 
301508Sbill long lgensym[10] =
311508Sbill   {100000L,200000L,300000L,400000L,500000L,600000L,700000L,800000L,900000L,1000000L};
321495Sbill 
3318380Sralph #define ALLOCSIZE	4096
3418380Sralph 
3524398Smckusick /*
3624398Smckusick  * Cheapo space allocator.  Works much like the old one but uses malloc()
3724398Smckusick  * and doesn't clash with stdio.  Assumes that no one requests more than
3824398Smckusick  * ALLOCSIZE bytes at a time.
3924398Smckusick  */
4024398Smckusick char *
xalloc(n)4124398Smckusick xalloc(n)
4224398Smckusick int n;
431495Sbill {
4424398Smckusick 	register char *nextb = * (char **) currentb;
451495Sbill 
4624398Smckusick 	if (n == 0) {	/* Free everything */
4724398Smckusick 		currentb = firstr;
4824398Smckusick 		nextb = * (char **) currentb;
4924398Smckusick 	}
5024398Smckusick 	if (nextb == NULL) {
5124398Smckusick 		if ((nextb = malloc(ALLOCSIZE)) == NULL) {
521495Sbill 			fprintf(stderr, "Optimizer: out of space\n");
531495Sbill 			exit(1);
541495Sbill 		}
5524398Smckusick 		ncore += (ALLOCSIZE/1024);
5624398Smckusick 		* (char **) currentb = nextb;
5724398Smckusick 		* (char **) nextb = NULL;
581495Sbill 	}
5924398Smckusick 	lasta = nextb + sizeof nextb;
6024398Smckusick 	lastr = nextb + ALLOCSIZE;
6124398Smckusick 	currentb = nextb;
6224398Smckusick 	newa = lasta;
6324398Smckusick 	lasta += XALIGN(n);
6424398Smckusick 	return(newa);
651495Sbill }
661495Sbill 
main(argc,argv)671495Sbill main(argc, argv)
681495Sbill char **argv;
691495Sbill {
701495Sbill 	register int niter, maxiter, isend;
711495Sbill 	int nflag,infound;
721495Sbill 
731495Sbill 	nflag = 0; infound=0; argc--; argv++;
741495Sbill 	while (argc>0) {/* get flags */
751495Sbill 		if (**argv=='+') debug++;
761495Sbill 		else if (**argv=='-') {
7717719Sralph 			if ((*argv)[1]=='i') ioflag++;
7817719Sralph 			else if ((*argv)[1]=='f') fflag++;
7917719Sralph 			else nflag++;
801495Sbill 		} else if (infound==0) {
811495Sbill 			if (freopen(*argv, "r", stdin) ==NULL) {
821495Sbill 				fprintf(stderr,"C2: can't find %s\n", *argv);
831495Sbill 				exit(1);
841495Sbill 			}
8516792Sralph 			++infound;
861495Sbill 		} else if (freopen(*argv, "w", stdout) ==NULL) {
871495Sbill 			fprintf(stderr,"C2: can't create %s\n", *argv);
881495Sbill 			exit(1);
891495Sbill 		}
901495Sbill 		argc--; argv++;
911495Sbill 	}
921495Sbill 	opsetup();
931495Sbill 	maxiter = 0;
941495Sbill 	do {
9524398Smckusick 		(void) xalloc(0);
961495Sbill 		isend = input();
971495Sbill 		niter = 0;
981495Sbill 		bmove();
991495Sbill 		do {
1001495Sbill 			refcount();
1011495Sbill 			do {
1021495Sbill 				iterate();
1031495Sbill 				clearreg();
1041495Sbill 				niter++;
1051495Sbill 			} while (nchange);
1061495Sbill 			comjump();
1071495Sbill 			rmove();
1081495Sbill 		} while (nchange || jumpsw());
1091495Sbill 		addsob();
1101495Sbill 		output();
1111495Sbill 		if (niter > maxiter)
1121495Sbill 			maxiter = niter;
1131495Sbill 	} while (isend);
1141495Sbill 	if (nflag) {
1151495Sbill 		fprintf(stderr,"%d iterations\n", maxiter);
1161495Sbill 		fprintf(stderr,"%d jumps to jumps\n", nbrbr);
1171495Sbill 		fprintf(stderr,"%d inst. after jumps\n", iaftbr);
1181495Sbill 		fprintf(stderr,"%d jumps to .+1\n", njp1);
1191495Sbill 		fprintf(stderr,"%d redundant labels\n", nrlab);
1201495Sbill 		fprintf(stderr,"%d cross-jumps\n", nxjump);
1211495Sbill 		fprintf(stderr,"%d code motions\n", ncmot);
1221495Sbill 		fprintf(stderr,"%d branches reversed\n", nrevbr);
1231495Sbill 		fprintf(stderr,"%d redundant moves\n", redunm);
1241495Sbill 		fprintf(stderr,"%d simplified addresses\n", nsaddr);
1251495Sbill 		fprintf(stderr,"%d loops inverted\n", loopiv);
1261495Sbill 		fprintf(stderr,"%d redundant jumps\n", nredunj);
1271495Sbill 		fprintf(stderr,"%d common seqs before jmp's\n", ncomj);
1281495Sbill 		fprintf(stderr,"%d skips over jumps\n", nskip);
1291495Sbill 		fprintf(stderr,"%d sob's added\n", nsob);
1301495Sbill 		fprintf(stderr,"%d redundant tst's\n", nrtst);
1311495Sbill 		fprintf(stderr,"%d jump on bit\n", nbj);
1321495Sbill 		fprintf(stderr,"%d field operations\n", nfield);
13324398Smckusick 		fprintf(stderr,"%dK core\n", ncore);
1341495Sbill 	}
1351495Sbill 	putc('\n',stdout);
1361495Sbill 	fflush(stdout); exit(0);
1371495Sbill }
1381495Sbill 
input()1391495Sbill input()
1401495Sbill {
1411495Sbill 	register struct node *p, *lastp;
14218380Sralph 	struct optab *opp; register char *cp1;
1431495Sbill 	static struct optab F77JSW = {".long", T(JSW,1)};
1441495Sbill 
1451495Sbill 	lastp = &first;
1461495Sbill 	for (;;) {
1471495Sbill 	  top:
14818380Sralph 		opp = getline();
14918380Sralph 		if (debug && opp==0) fprintf(stderr,"? %s\n",line);
15018380Sralph 		switch (opp->opcode&0377) {
1511495Sbill 
1521495Sbill 		case LABEL:
1531495Sbill 			p = alloc(sizeof first);
1541495Sbill 			if (isdigit(line[0]) && (p->labno=locdef(line)) ||
1551495Sbill 			  (line[0] == 'L') && (p->labno=getnum(line+1))) {
1561495Sbill 				p->combop = LABEL;
1571508Sbill 				if (p->labno<100000L && isn<=p->labno) isn=1+p->labno;
1581495Sbill 				p->code = 0;
1591495Sbill 			} else {
1601495Sbill 				p->combop = DLABEL;
1611495Sbill 				p->labno = 0;
1621495Sbill 				p->code = copy(line);
1631495Sbill 			}
1641495Sbill 			break;
1651495Sbill 
1661495Sbill 		case LGEN:
1671495Sbill 			if (*curlp!='L' && !locuse(curlp)) goto std;
16818380Sralph 			opp= &F77JSW;
1691495Sbill 		case JBR:
17018380Sralph 			if (opp->opcode==T(JBR,RET) || opp->opcode==T(JBR,RSB)) goto std;
1711495Sbill 		case CBR:
1721495Sbill 		case JMP:
1731495Sbill 		case JSW:
1741495Sbill 		case SOBGEQ: case SOBGTR: case AOBLEQ: case AOBLSS: case ACB:
1751495Sbill 			p = alloc(sizeof first);
17618380Sralph 			p->combop = opp->opcode; p->code=0; cp1=curlp;
1771495Sbill 			if ((!isdigit(*cp1) || 0==(p->labno=locuse(cp1))) &&
1781495Sbill 			  (*cp1!='L' || 0==(p->labno = getnum(cp1+1)))) {/* jbs, etc.? */
1791495Sbill 				while (*cp1++); while (*--cp1!=',' && cp1!=curlp);
1801495Sbill 				if (cp1==curlp ||
1811495Sbill 				  (!isdigit(*++cp1) || 0==(p->labno=locuse(cp1))) &&
1821495Sbill 				  (*cp1!='L' || 0==(p->labno=getnum(cp1+1))))
1831495Sbill 					p->labno = 0;
1841495Sbill 				else *--cp1=0;
1851495Sbill 				p->code = copy(curlp);
1861495Sbill 			}
1871495Sbill 			if (isn<=p->labno) isn=1+p->labno;
1881495Sbill 			break;
1891495Sbill 
1901495Sbill 		case MOVA:
1911495Sbill 			p=alloc(sizeof first);
19218380Sralph 			p->combop=opp->opcode; p->code=0; cp1=curlp+1;
1931495Sbill 			if (cp1[-1]=='L' || isdigit(cp1[-1])) {
1941495Sbill 				while (*cp1++!=','); *--cp1=0;
1951495Sbill 				if (0!=(p->labno=locuse(curlp)) ||
1961495Sbill 					0!=(p->labno=getnum(curlp+1))) p->code=copy(cp1+1);
1971495Sbill 				else {*cp1=','; p->code=copy(curlp);}
1981495Sbill 			} else {p->code=copy(--cp1); p->labno=0;}
1991495Sbill 			break;
2001495Sbill 
2011495Sbill 		case SET:
2021495Sbill 		case COMM:
2031495Sbill 		case LCOMM:
2041495Sbill 			printf("%s\n",line); goto top;
2051495Sbill 
2061495Sbill 		case BSS:
2071495Sbill 		case DATA:
2081495Sbill 			for (;;) {
20918380Sralph 				printf("%s%c",line,(opp->opcode==LABEL ? ':' : '\n'));
21018380Sralph 				if (opp->opcode==TEXT) goto top;
21118380Sralph 				if (END==(opp=getline())->opcode) {/* dangling .data is bad for you */
2121495Sbill 					printf(".text\n");
2131495Sbill 					break;
2141495Sbill 				}
2151495Sbill 			}
2161495Sbill 
2171495Sbill 		std:
2181495Sbill 		default:
2191495Sbill 			p = alloc(sizeof first);
22018380Sralph 			p->combop = opp->opcode;
2211495Sbill 			p->labno = 0;
2221495Sbill 			p->code = copy(curlp);
2231495Sbill 			break;
2241495Sbill 
2251495Sbill 		}
2261495Sbill 		p->forw = 0;
2271495Sbill 		p->back = lastp;
22818380Sralph 		p->pop = opp;
2291495Sbill 		lastp->forw = p;
2301495Sbill 		lastp = p;
2311495Sbill 		p->ref = 0;
2321495Sbill 		if (p->op==CASE) {
2331495Sbill 			char *lp; int ncase;
2341495Sbill 			lp=curlp; while (*lp++); while (*--lp!='$'); ncase=getnum(lp+1);
23518380Sralph 			if (LABEL!=(getline())->opcode) {
23618380Sralph 				fprintf(stderr, "c2: garbled 'case' instruction\n");
23718380Sralph 				exit(-2);
23818380Sralph 			}
2391495Sbill 			do {
24018380Sralph 				if (WGEN!=(getline())->opcode) {
24118380Sralph 					fprintf(stderr, "c2: garbled 'case' instruction\n");
24218380Sralph 					exit(-3);
24318380Sralph 				}
2441495Sbill 				p = alloc(sizeof first); p->combop = JSW; p->code = 0;
2451495Sbill 				lp=curlp; while(*lp++!='-'); *--lp=0; p->labno=getnum(curlp+1);
2461495Sbill 				if (isn<=p->labno) isn=1+p->labno;
2471495Sbill 				p->forw = 0; p->back = lastp; lastp->forw = p; lastp = p;
2481495Sbill 				p->ref = 0; p->pop=0;
2491495Sbill 			} while (--ncase>=0);
2501495Sbill 		}
25118380Sralph 		if (opp->opcode==EROU)
2521495Sbill 			return(1);
25318380Sralph 		if (opp->opcode==END)
2541495Sbill 			return(0);
2551495Sbill 	}
2561495Sbill }
2571495Sbill 
2581495Sbill struct optab *
getline()2591495Sbill getline()
2601495Sbill {
2611495Sbill 	register char *lp;
2621495Sbill 	register c;
2631495Sbill 	static struct optab OPLABEL={"",LABEL};
2641495Sbill 	static struct optab OPEND={"",END};
2651495Sbill 
2661495Sbill 	lp = line;
2671495Sbill 	while (EOF!=(c=getchar()) && isspace(c));
2681495Sbill 	while (EOF!=c) {
2691495Sbill 		if (c==':') {
2701495Sbill 			*lp++ = 0;
2711495Sbill 			return(&OPLABEL);
2721495Sbill 		}
2731495Sbill 		if (c=='\n') {
2741495Sbill 			*lp++ = 0;
2751495Sbill 			return(oplook());
2761495Sbill 		}
2771495Sbill 		*lp++ = c;
2781495Sbill 		c = getchar();
2791495Sbill 	}
2801495Sbill 	*lp++ = 0;
2811495Sbill 	return(&OPEND);
2821495Sbill }
2831495Sbill 
2841495Sbill long
getnum(p)2851495Sbill getnum(p)
2861495Sbill register char *p;
2871495Sbill {
2881495Sbill 	register c; int neg; register long n;
2891495Sbill 
2901495Sbill 	n = 0; neg=0; if (*p=='-') {++neg; ++p;}
2911495Sbill 	while (isdigit(c = *p++)) {
2921495Sbill 		 c -= '0'; n *= 10; if (neg) n -= c; else n += c;
2931495Sbill 	}
2941495Sbill 	if (*--p != 0)
2951495Sbill 		return(0);
2961495Sbill 	return(n);
2971495Sbill }
2981495Sbill 
locuse(p)2991495Sbill locuse(p)
3001495Sbill register char *p;
3011495Sbill {
3021495Sbill 	if (!isdigit(p[0]) || p[1] != 'f' && p[1] != 'b' || p[2]) return(0);
3031495Sbill 	return (lgensym[p[0] - '0'] - (p[1] == 'b'));
3041495Sbill }
3051495Sbill 
locdef(p)3061495Sbill locdef(p)
3071495Sbill register char *p;
3081495Sbill {
3091495Sbill 
3101495Sbill 	if (!isdigit(p[0]) || p[1]) return(0);
3111495Sbill 	return (lgensym[p[0] - '0']++);
3121495Sbill }
3131495Sbill 
output()3141495Sbill output()
3151495Sbill {
3161495Sbill 	register struct node *t;
3171495Sbill 	int casebas;
3181495Sbill 
3191495Sbill 	t = &first;
3201495Sbill 	while (t = t->forw) switch (t->op) {
3211495Sbill 
3221495Sbill 	case END:
3231495Sbill 		fflush(stdout);
3241495Sbill 		return;
3251495Sbill 
3261495Sbill 	case LABEL:
3271495Sbill 		printf("L%d:", t->labno);
3281495Sbill 		continue;
3291495Sbill 
3301495Sbill 	case DLABEL:
3311495Sbill 		printf("%s:", t->code);
3321495Sbill 		continue;
3331495Sbill 
3341495Sbill 	case CASE:
3351495Sbill 		casebas=0;
3361495Sbill 
3371495Sbill 	default: std:
3381495Sbill 		if (t->pop==0) {/* must find it */
3391495Sbill 			register struct optab *p;
3401495Sbill 			for (p=optab; p->opstring[0]; ++p)
3411495Sbill 				if (p->opcode==t->combop) {t->pop=p; break;}
3421495Sbill 		}
3431495Sbill 		printf("%s", t->pop->opstring);
3441495Sbill 		if (t->code) printf("\t%s", t->code);
3451495Sbill 		if (t->labno!=0) printf("%cL%d\n",
3461495Sbill 							(t->code ? ',' : '\t'),
3471495Sbill 							t->labno);
3481495Sbill 		else printf("\n");
3491495Sbill 		continue;
3501495Sbill 
3511495Sbill 	case MOVA:
3521495Sbill 		if (t->labno==0) goto std;
3531495Sbill 		printf("mova%c\tL%d,%s\n","bwlq"[t->subop-BYTE],t->labno,t->code);
3541495Sbill 		continue;
3551495Sbill 
3561495Sbill 	case JSW:
3571495Sbill 		if (t->subop!=0) {/* F77JSW */
3581495Sbill 			printf(".long\tL%d\n",t->labno); continue;
3591495Sbill 		}
3601495Sbill 		if (casebas==0) printf("L%d:\n",casebas=isn++);
3611495Sbill 		printf(".word	L%d-L%d\n", t->labno, casebas);
3621495Sbill 		continue;
36317719Sralph 	case MOV:
36417719Sralph 		if (!fflag) goto std;
36517719Sralph 		if (t->forw) if(t->forw->op == CBR) goto std;
36617719Sralph 		if (*t->code == '$') goto std;
36717719Sralph 		if (t->subop == FFLOAT)
36817719Sralph 			{
36917719Sralph 			printf("movl\t%s\n", t->code);
37017719Sralph 			continue;
37117719Sralph 			}
37217719Sralph 		if (t->subop == DFLOAT || t->subop == GFLOAT)
37317719Sralph 			{
37417719Sralph 			printf("movq\t%s\n", t->code);
37517719Sralph 			continue;
37617719Sralph 			}
37717719Sralph 		if (t->subop == HFLOAT)
37817719Sralph 			{
37917719Sralph 			printf("movo\t%s\n", t->code);
38017719Sralph 			continue;
38117719Sralph 			}
38217719Sralph 		goto std;
3831495Sbill 
3841495Sbill 	}
3851495Sbill }
3861495Sbill 
3871495Sbill char *
copy(ap)3881495Sbill copy(ap)
3891495Sbill char *ap;
3901495Sbill {
391*43497Sbostic 	register char *p = ap, *np;
3921495Sbill 	char *onp;
3931495Sbill 	register n;
3941495Sbill 
395*43497Sbostic 	if (*p++ == 0)
3961495Sbill 		return(0);
397*43497Sbostic 	n = 1;
3981495Sbill 	do
3991495Sbill 		n++;
4001495Sbill 	while (*p++);
40118380Sralph 	onp = np = (char *) alloc(n);
4021495Sbill 	p = ap;
4031495Sbill 	while (*np++ = *p++);
404*43497Sbostic 	return (onp);
4051495Sbill }
4061495Sbill 
4071495Sbill #define	OPHS	560
4081495Sbill struct optab *ophash[OPHS];
4091495Sbill 
opsetup()4101495Sbill opsetup()
4111495Sbill {
4121495Sbill 	register struct optab *optp, **ophp;
4131495Sbill 	register int i,t;
4141495Sbill 
41524398Smckusick 	for(i=NREG+5;--i>=0;) regs[i] = malloc(C2_ASIZE);
4161495Sbill 	for (optp = optab; optp->opstring[0]; optp++) {
4171495Sbill 		t=7; i=0; while (--t>=0) i+= i+optp->opstring[t];
4181495Sbill 		ophp = &ophash[i % OPHS];
4191495Sbill 		while (*ophp++) {
4201495Sbill /*			fprintf(stderr,"\ncollision: %d %s %s",
4211495Sbill /*				ophp-1-ophash,optp->opstring,(*(ophp-1))->opstring);
4221495Sbill */
42324398Smckusick 			if (ophp >= &ophash[OPHS])
4241495Sbill 				ophp = ophash;
4251495Sbill 		}
4261495Sbill 		*--ophp = optp;
4271495Sbill 	}
4281495Sbill }
4291495Sbill 
4301495Sbill struct optab *
oplook()4311495Sbill oplook()
4321495Sbill {
4331495Sbill 	register struct optab *optp,**ophp;
4341495Sbill 	register char *p,*p2;
4351495Sbill 	register int t;
4363933Sroot 	char tempop[20];
4371495Sbill 	static struct optab OPNULL={"",0};
4381495Sbill 
4391495Sbill 	for (p=line, p2=tempop; *p && !isspace(*p); *p2++= *p++); *p2=0; p2=p;
4401495Sbill 	while (isspace(*p2)) ++p2; curlp=p2;
4411495Sbill 	t=0; while(--p>=line) t += t+*p; ophp = &ophash[t % OPHS];
4421495Sbill 	while (optp = *ophp) {
4431495Sbill 		if (equstr(tempop,optp->opstring)) return(optp);
4441495Sbill 		if ((++ophp) >= &ophash[OPHS]) ophp = ophash;
4451495Sbill 	}
4461495Sbill 	curlp = line;
4471495Sbill 	return(&OPNULL);
4481495Sbill }
4491495Sbill 
refcount()4501495Sbill refcount()
4511495Sbill {
45218380Sralph 	register struct node *p, *lp, *tp;
4531495Sbill 	struct node *labhash[LABHS];
4541495Sbill 	register struct node **hp;
4551495Sbill 
4561495Sbill 	for (hp = labhash; hp < &labhash[LABHS];)
4571495Sbill 		*hp++ = 0;
4581495Sbill 	for (p = first.forw; p!=0; p = p->forw)
4591495Sbill 		if (p->op==LABEL) {
4601495Sbill 			labhash[p->labno % LABHS] = p;
4611495Sbill 			p->refc = 0;
4621495Sbill 		}
4631495Sbill 	for (p = first.forw; p!=0; p = p->forw) {
4641495Sbill 		if (p->combop==JBR || p->op==CBR || p->op==JSW || p->op==JMP
4651495Sbill 		  || p->op==SOBGEQ || p->op==SOBGTR || p->op==AOBLEQ || p->op==AOBLSS
4661495Sbill 		  || p->op==ACB || (p->op==MOVA && p->labno!=0)) {
4671495Sbill 			p->ref = 0;
4681495Sbill 			lp = labhash[p->labno % LABHS];
4691495Sbill 			if (lp==0 || p->labno!=lp->labno)
4701495Sbill 			for (lp = first.forw; lp!=0; lp = lp->forw) {
4711495Sbill 				if (lp->op==LABEL && p->labno==lp->labno)
4721495Sbill 					break;
4731495Sbill 			}
4741495Sbill 			if (lp) {
47518380Sralph 				tp = nonlab(lp)->back;
47618380Sralph 				if (tp!=lp) {
47718380Sralph 					p->labno = tp->labno;
47818380Sralph 					lp = tp;
4791495Sbill 				}
4801495Sbill 				p->ref = lp;
4811495Sbill 				lp->refc++;
4821495Sbill 			}
4831495Sbill 		}
4841495Sbill 	}
4851495Sbill 	for (p = first.forw; p!=0; p = p->forw)
4861495Sbill 		if (p->op==LABEL && p->refc==0
4871495Sbill 		 && (lp = nonlab(p))->op && lp->op!=JSW)
4881495Sbill 			decref(p);
4891495Sbill }
4901495Sbill 
iterate()4911495Sbill iterate()
4921495Sbill {
4931495Sbill 	register struct node *p, *rp, *p1;
4941495Sbill 
4951495Sbill 	nchange = 0;
4961495Sbill 	for (p = first.forw; p!=0; p = p->forw) {
4971495Sbill 		if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) {
4981495Sbill 			rp = nonlab(p->ref);
4991495Sbill 			if (rp->op==JBR && rp->labno && p->labno!=rp->labno) {
5001495Sbill 				nbrbr++;
5011495Sbill 				p->labno = rp->labno;
5021495Sbill 				decref(p->ref);
5031495Sbill 				rp->ref->refc++;
5041495Sbill 				p->ref = rp->ref;
5051495Sbill 				nchange++;
5061495Sbill 			}
5071495Sbill 		}
5081495Sbill #ifndef COPYCODE
5091495Sbill 		if (p->op==CBR && (p1 = p->forw)->combop==JBR) {/* combop: RET problems */
5101495Sbill #else
5111495Sbill 		if (p->op==CBR && (p1 = p->forw)->combop==JBR &&
5121495Sbill 		    p->ref) {/* combop: RET problems */
5131495Sbill #endif
5141495Sbill 			rp = p->ref;
5151495Sbill 			do
5161495Sbill 				rp = rp->back;
5171495Sbill 			while (rp->op==LABEL);
5181495Sbill 			if (rp==p1) {
5191495Sbill 				decref(p->ref);
5201495Sbill 				p->ref = p1->ref;
5211495Sbill 				p->labno = p1->labno;
5221495Sbill #ifdef COPYCODE
5231495Sbill 				if (p->labno == 0)
5241495Sbill 					p->code = p1->code;
5251495Sbill #endif
5261495Sbill 				p1->forw->back = p;
5271495Sbill 				p->forw = p1->forw;
5281495Sbill 				p->subop = revbr[p->subop];
5291495Sbill 				p->pop=0;
5301495Sbill 				nchange++;
5311495Sbill 				nskip++;
5321495Sbill 			}
5331495Sbill 		}
5341495Sbill 		if (p->op==JBR || p->op==JMP) {
5351495Sbill 			while (p->forw && p->forw->op!=LABEL && p->forw->op!=DLABEL
5361495Sbill 				&& p->forw->op!=EROU && p->forw->op!=END
5371495Sbill 				&& p->forw->op!=ALIGN
5381495Sbill 				&& p->forw->op!=0 && p->forw->op!=DATA) {
5391495Sbill 				nchange++;
5401495Sbill 				iaftbr++;
5411495Sbill 				if (p->forw->ref)
5421495Sbill 					decref(p->forw->ref);
5431495Sbill 				p->forw = p->forw->forw;
5441495Sbill 				p->forw->back = p;
5451495Sbill 			}
5461495Sbill 			rp = p->forw;
5471495Sbill 			while (rp && rp->op==LABEL) {
5481495Sbill 				if (p->ref == rp) {
5491495Sbill 					p->back->forw = p->forw;
5501495Sbill 					p->forw->back = p->back;
5511495Sbill 					p = p->back;
5521495Sbill 					decref(rp);
5531495Sbill 					nchange++;
5541495Sbill 					njp1++;
5551495Sbill 					break;
5561495Sbill 				}
5571495Sbill 				rp = rp->forw;
5581495Sbill 			}
5591495Sbill 			xjump(p);
5601495Sbill 			p = codemove(p);
5611495Sbill 		}
5621495Sbill 	}
5631495Sbill }
5641495Sbill 
5651495Sbill xjump(p1)
5661495Sbill register struct node *p1;
5671495Sbill {
5681495Sbill 	register struct node *p2, *p3;
5691495Sbill 
5701495Sbill 	if ((p2 = p1->ref)==0)
57118380Sralph 		return;
5721495Sbill 	for (;;) {
5731495Sbill 		while ((p1 = p1->back) && p1->op==LABEL);
5741495Sbill 		while ((p2 = p2->back) && p2->op==LABEL);
5751495Sbill 		if (!equop(p1, p2) || p1==p2)
57618380Sralph 			return;
5771495Sbill 		p3 = insertl(p2);
5781495Sbill 		p1->combop = JBR;
5791495Sbill 		p1->pop=0;
5801495Sbill 		p1->ref = p3;
5811495Sbill 		p1->labno = p3->labno;
5821495Sbill 		p1->code = 0;
5831495Sbill 		nxjump++;
5841495Sbill 		nchange++;
5851495Sbill 	}
5861495Sbill }
5871495Sbill 
5881495Sbill struct node *
58918380Sralph insertl(np)
59018380Sralph register struct node *np;
5911495Sbill {
5921495Sbill 	register struct node *lp;
5931495Sbill 
59418380Sralph 	if (np->op == LABEL) {
59518380Sralph 		np->refc++;
59618380Sralph 		return(np);
5971495Sbill 	}
59818380Sralph 	if (np->back->op == LABEL) {
59918380Sralph 		np = np->back;
60018380Sralph 		np->refc++;
60118380Sralph 		return(np);
6021495Sbill 	}
6031495Sbill 	lp = alloc(sizeof first);
6041495Sbill 	lp->combop = LABEL;
6051495Sbill 	lp->labno = isn++;
6061495Sbill 	lp->ref = 0;
6071495Sbill 	lp->code = 0;
6081495Sbill 	lp->refc = 1;
60918380Sralph 	lp->back = np->back;
61018380Sralph 	lp->forw = np;
61118380Sralph 	np->back->forw = lp;
61218380Sralph 	np->back = lp;
6131495Sbill 	return(lp);
6141495Sbill }
6151495Sbill 
6161495Sbill struct node *
6171495Sbill codemove(ap)
6181495Sbill struct node *ap;
6191495Sbill {
6201495Sbill 	register struct node *p1, *p2, *p3;
6211495Sbill 	struct node *t, *tl;
6221495Sbill 	int n;
6231495Sbill 
6241495Sbill 	p1 = ap;
6251495Sbill /* last clause to avoid infinite loop on partial compiler droppings:
6261495Sbill 	L183:	jbr L179
6271495Sbill 	L191:	jbr L179
6281495Sbill 			casel r0,$0,$1
6291495Sbill 	L193:	.word L183-L193
6301495Sbill 			.word L191-L193
6311495Sbill 	L179:	ret
6321495Sbill */
6331495Sbill 	if (p1->op!=JBR || (p2 = p1->ref)==0 || p2==p1->forw)
6341495Sbill 		return(p1);
6351495Sbill 	while (p2->op == LABEL)
6361495Sbill 		if ((p2 = p2->back) == 0)
6371495Sbill 			return(p1);
6381495Sbill 	if (p2->op!=JBR && p2->op!=JMP)
6391495Sbill 		goto ivloop;
6401495Sbill 	p2 = p2->forw;
6411495Sbill 	p3 = p1->ref;
6421495Sbill 	while (p3) {
6431495Sbill 		if (p3->op==JBR || p3->op==JMP) {
6441495Sbill 			if (p1==p3)
6451495Sbill 				return(p1);
6461495Sbill 			ncmot++;
6471495Sbill 			nchange++;
6481495Sbill 			p1->back->forw = p2;
6491495Sbill 			p1->forw->back = p3;
6501495Sbill 			p2->back->forw = p3->forw;
6511495Sbill 			p3->forw->back = p2->back;
6521495Sbill 			p2->back = p1->back;
6531495Sbill 			p3->forw = p1->forw;
6541495Sbill 			decref(p1->ref);
6551495Sbill 			return(p2);
6561495Sbill 		} else
6571495Sbill 			p3 = p3->forw;
6581495Sbill 	}
6591495Sbill 	return(p1);
6601495Sbill ivloop:
6611495Sbill 	if (p1->forw->op!=LABEL)
6621495Sbill 		return(p1);
6631495Sbill 	p3 = p2 = p2->forw;
6641495Sbill 	n = 16;
6651495Sbill 	do {
6661495Sbill 		if ((p3 = p3->forw) == 0 || p3==p1 || --n==0)
6671495Sbill 			return(p1);
6681495Sbill 	} while (p3->op!=CBR || p3->labno!=p1->forw->labno);
6691495Sbill 	do
6701495Sbill 		if ((p1 = p1->back) == 0)
6711495Sbill 			return(ap);
6721495Sbill 	while (p1!=p3);
6731495Sbill 	p1 = ap;
6741495Sbill 	tl = insertl(p1);
6751495Sbill 	p3->subop = revbr[p3->subop];
6761495Sbill 	p3->pop=0;
6771495Sbill 	decref(p3->ref);
6781495Sbill 	p2->back->forw = p1;
6791495Sbill 	p3->forw->back = p1;
6801495Sbill 	p1->back->forw = p2;
6811495Sbill 	p1->forw->back = p3;
6821495Sbill 	t = p1->back;
6831495Sbill 	p1->back = p2->back;
6841495Sbill 	p2->back = t;
6851495Sbill 	t = p1->forw;
6861495Sbill 	p1->forw = p3->forw;
6871495Sbill 	p3->forw = t;
6881495Sbill 	p2 = insertl(p1->forw);
6891495Sbill 	p3->labno = p2->labno;
6901495Sbill #ifdef COPYCODE
6911495Sbill 	if (p3->labno == 0)
6921495Sbill 		p3->code = p2->code;
6931495Sbill #endif
6941495Sbill 	p3->ref = p2;
6951495Sbill 	decref(tl);
6961495Sbill 	if (tl->refc<=0)
6971495Sbill 		nrlab--;
6981495Sbill 	loopiv++;
6991495Sbill 	nchange++;
7001495Sbill 	return(p3);
7011495Sbill }
7021495Sbill 
7031495Sbill comjump()
7041495Sbill {
7051495Sbill 	register struct node *p1, *p2, *p3;
7061495Sbill 
7071495Sbill 	for (p1 = first.forw; p1!=0; p1 = p1->forw)
7081495Sbill 		if (p1->op==JBR && ((p2 = p1->ref) && p2->refc > 1
7091495Sbill 				|| p1->subop==RET || p1->subop==RSB))
7101495Sbill 			for (p3 = p1->forw; p3!=0; p3 = p3->forw)
7111495Sbill 				if (p3->op==JBR && p3->ref == p2)
7121495Sbill 					backjmp(p1, p3);
7131495Sbill }
7141495Sbill 
7151495Sbill backjmp(ap1, ap2)
7161495Sbill struct node *ap1, *ap2;
7171495Sbill {
7181495Sbill 	register struct node *p1, *p2, *p3;
7191495Sbill 
7201495Sbill 	p1 = ap1;
7211495Sbill 	p2 = ap2;
7221495Sbill 	for(;;) {
7231495Sbill 		while ((p1 = p1->back) && p1->op==LABEL);
7241495Sbill 		p2 = p2->back;
7251495Sbill 		if (equop(p1, p2)) {
7261495Sbill 			p3 = insertl(p1);
7271495Sbill 			p2->back->forw = p2->forw;
7281495Sbill 			p2->forw->back = p2->back;
7291495Sbill 			p2 = p2->forw;
7301495Sbill 			decref(p2->ref);
7311495Sbill 			p2->combop = JBR; /* to handle RET */
7321495Sbill 			p2->pop=0;
7331495Sbill 			p2->labno = p3->labno;
7341495Sbill #ifdef COPYCODE
7351495Sbill 			p2->code = 0;
7361495Sbill #endif
7371495Sbill 			p2->ref = p3;
7381495Sbill 			nchange++;
7391495Sbill 			ncomj++;
7401495Sbill 		} else
7411495Sbill 			return;
7421495Sbill 	}
7431495Sbill }
744