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