114572Ssam #ifndef lint 2*24398Smckusick static char sccsid[] = "@(#)c20.c 4.10 (Berkeley) 08/22/85"; 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 14*24398Smckusick char *malloc(); 15*24398Smckusick char firstr[sizeof (char *)]; 16*24398Smckusick char *currentb; 17*24398Smckusick char *newa; 18*24398Smckusick char *lasta; 19*24398Smckusick char *lastr; 20*24398Smckusick int ncore; 21*24398Smckusick 221495Sbill int ioflag; 2317719Sralph int fflag; 24*24398Smckusick 251508Sbill long isn = 2000000; 26*24398Smckusick 271495Sbill struct optab *oplook(); 281495Sbill struct optab *getline(); 29*24398Smckusick 301508Sbill long lgensym[10] = 311508Sbill {100000L,200000L,300000L,400000L,500000L,600000L,700000L,800000L,900000L,1000000L}; 321495Sbill 3318380Sralph #define ALLOCSIZE 4096 3418380Sralph 35*24398Smckusick /* 36*24398Smckusick * Cheapo space allocator. Works much like the old one but uses malloc() 37*24398Smckusick * and doesn't clash with stdio. Assumes that no one requests more than 38*24398Smckusick * ALLOCSIZE bytes at a time. 39*24398Smckusick */ 40*24398Smckusick char * 41*24398Smckusick xalloc(n) 42*24398Smckusick int n; 431495Sbill { 44*24398Smckusick register char *nextb = * (char **) currentb; 451495Sbill 46*24398Smckusick if (n == 0) { /* Free everything */ 47*24398Smckusick currentb = firstr; 48*24398Smckusick nextb = * (char **) currentb; 49*24398Smckusick } 50*24398Smckusick if (nextb == NULL) { 51*24398Smckusick if ((nextb = malloc(ALLOCSIZE)) == NULL) { 521495Sbill fprintf(stderr, "Optimizer: out of space\n"); 531495Sbill exit(1); 541495Sbill } 55*24398Smckusick ncore += (ALLOCSIZE/1024); 56*24398Smckusick * (char **) currentb = nextb; 57*24398Smckusick * (char **) nextb = NULL; 581495Sbill } 59*24398Smckusick lasta = nextb + sizeof nextb; 60*24398Smckusick lastr = nextb + ALLOCSIZE; 61*24398Smckusick currentb = nextb; 62*24398Smckusick newa = lasta; 63*24398Smckusick lasta += XALIGN(n); 64*24398Smckusick return(newa); 651495Sbill } 661495Sbill 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 { 95*24398Smckusick (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); 133*24398Smckusick fprintf(stderr,"%dK core\n", ncore); 1341495Sbill } 1351495Sbill putc('\n',stdout); 1361495Sbill fflush(stdout); exit(0); 1371495Sbill } 1381495Sbill 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 * 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 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 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 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 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 * 3881495Sbill copy(ap) 3891495Sbill char *ap; 3901495Sbill { 3911495Sbill register char *p, *np; 3921495Sbill char *onp; 3931495Sbill register n; 3941495Sbill int na; 3951495Sbill 3961495Sbill na = nargs(); 3971495Sbill p = ap; 3981495Sbill n = 0; 3991495Sbill if (*p==0) 4001495Sbill return(0); 4011495Sbill do 4021495Sbill n++; 4031495Sbill while (*p++); 4041495Sbill if (na>1) { 4051495Sbill p = (&ap)[1]; 4061495Sbill while (*p++) 4071495Sbill n++; 4081495Sbill } 40918380Sralph onp = np = (char *) alloc(n); 4101495Sbill p = ap; 4111495Sbill while (*np++ = *p++); 4121495Sbill if (na>1) { 4131495Sbill p = (&ap)[1]; 4141495Sbill np--; 4151495Sbill while (*np++ = *p++); 4161495Sbill } 4171495Sbill return(onp); 4181495Sbill } 4191495Sbill 4201495Sbill #define OPHS 560 4211495Sbill struct optab *ophash[OPHS]; 4221495Sbill 4231495Sbill opsetup() 4241495Sbill { 4251495Sbill register struct optab *optp, **ophp; 4261495Sbill register int i,t; 4271495Sbill 428*24398Smckusick for(i=NREG+5;--i>=0;) regs[i] = malloc(C2_ASIZE); 4291495Sbill for (optp = optab; optp->opstring[0]; optp++) { 4301495Sbill t=7; i=0; while (--t>=0) i+= i+optp->opstring[t]; 4311495Sbill ophp = &ophash[i % OPHS]; 4321495Sbill while (*ophp++) { 4331495Sbill /* fprintf(stderr,"\ncollision: %d %s %s", 4341495Sbill /* ophp-1-ophash,optp->opstring,(*(ophp-1))->opstring); 4351495Sbill */ 436*24398Smckusick if (ophp >= &ophash[OPHS]) 4371495Sbill ophp = ophash; 4381495Sbill } 4391495Sbill *--ophp = optp; 4401495Sbill } 4411495Sbill } 4421495Sbill 4431495Sbill struct optab * 4441495Sbill oplook() 4451495Sbill { 4461495Sbill register struct optab *optp,**ophp; 4471495Sbill register char *p,*p2; 4481495Sbill register int t; 4493933Sroot char tempop[20]; 4501495Sbill static struct optab OPNULL={"",0}; 4511495Sbill 4521495Sbill for (p=line, p2=tempop; *p && !isspace(*p); *p2++= *p++); *p2=0; p2=p; 4531495Sbill while (isspace(*p2)) ++p2; curlp=p2; 4541495Sbill t=0; while(--p>=line) t += t+*p; ophp = &ophash[t % OPHS]; 4551495Sbill while (optp = *ophp) { 4561495Sbill if (equstr(tempop,optp->opstring)) return(optp); 4571495Sbill if ((++ophp) >= &ophash[OPHS]) ophp = ophash; 4581495Sbill } 4591495Sbill curlp = line; 4601495Sbill return(&OPNULL); 4611495Sbill } 4621495Sbill 4631495Sbill refcount() 4641495Sbill { 46518380Sralph register struct node *p, *lp, *tp; 4661495Sbill struct node *labhash[LABHS]; 4671495Sbill register struct node **hp; 4681495Sbill 4691495Sbill for (hp = labhash; hp < &labhash[LABHS];) 4701495Sbill *hp++ = 0; 4711495Sbill for (p = first.forw; p!=0; p = p->forw) 4721495Sbill if (p->op==LABEL) { 4731495Sbill labhash[p->labno % LABHS] = p; 4741495Sbill p->refc = 0; 4751495Sbill } 4761495Sbill for (p = first.forw; p!=0; p = p->forw) { 4771495Sbill if (p->combop==JBR || p->op==CBR || p->op==JSW || p->op==JMP 4781495Sbill || p->op==SOBGEQ || p->op==SOBGTR || p->op==AOBLEQ || p->op==AOBLSS 4791495Sbill || p->op==ACB || (p->op==MOVA && p->labno!=0)) { 4801495Sbill p->ref = 0; 4811495Sbill lp = labhash[p->labno % LABHS]; 4821495Sbill if (lp==0 || p->labno!=lp->labno) 4831495Sbill for (lp = first.forw; lp!=0; lp = lp->forw) { 4841495Sbill if (lp->op==LABEL && p->labno==lp->labno) 4851495Sbill break; 4861495Sbill } 4871495Sbill if (lp) { 48818380Sralph tp = nonlab(lp)->back; 48918380Sralph if (tp!=lp) { 49018380Sralph p->labno = tp->labno; 49118380Sralph lp = tp; 4921495Sbill } 4931495Sbill p->ref = lp; 4941495Sbill lp->refc++; 4951495Sbill } 4961495Sbill } 4971495Sbill } 4981495Sbill for (p = first.forw; p!=0; p = p->forw) 4991495Sbill if (p->op==LABEL && p->refc==0 5001495Sbill && (lp = nonlab(p))->op && lp->op!=JSW) 5011495Sbill decref(p); 5021495Sbill } 5031495Sbill 5041495Sbill iterate() 5051495Sbill { 5061495Sbill register struct node *p, *rp, *p1; 5071495Sbill 5081495Sbill nchange = 0; 5091495Sbill for (p = first.forw; p!=0; p = p->forw) { 5101495Sbill if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) { 5111495Sbill rp = nonlab(p->ref); 5121495Sbill if (rp->op==JBR && rp->labno && p->labno!=rp->labno) { 5131495Sbill nbrbr++; 5141495Sbill p->labno = rp->labno; 5151495Sbill decref(p->ref); 5161495Sbill rp->ref->refc++; 5171495Sbill p->ref = rp->ref; 5181495Sbill nchange++; 5191495Sbill } 5201495Sbill } 5211495Sbill #ifndef COPYCODE 5221495Sbill if (p->op==CBR && (p1 = p->forw)->combop==JBR) {/* combop: RET problems */ 5231495Sbill #else 5241495Sbill if (p->op==CBR && (p1 = p->forw)->combop==JBR && 5251495Sbill p->ref) {/* combop: RET problems */ 5261495Sbill #endif 5271495Sbill rp = p->ref; 5281495Sbill do 5291495Sbill rp = rp->back; 5301495Sbill while (rp->op==LABEL); 5311495Sbill if (rp==p1) { 5321495Sbill decref(p->ref); 5331495Sbill p->ref = p1->ref; 5341495Sbill p->labno = p1->labno; 5351495Sbill #ifdef COPYCODE 5361495Sbill if (p->labno == 0) 5371495Sbill p->code = p1->code; 5381495Sbill #endif 5391495Sbill p1->forw->back = p; 5401495Sbill p->forw = p1->forw; 5411495Sbill p->subop = revbr[p->subop]; 5421495Sbill p->pop=0; 5431495Sbill nchange++; 5441495Sbill nskip++; 5451495Sbill } 5461495Sbill } 5471495Sbill if (p->op==JBR || p->op==JMP) { 5481495Sbill while (p->forw && p->forw->op!=LABEL && p->forw->op!=DLABEL 5491495Sbill && p->forw->op!=EROU && p->forw->op!=END 5501495Sbill && p->forw->op!=ALIGN 5511495Sbill && p->forw->op!=0 && p->forw->op!=DATA) { 5521495Sbill nchange++; 5531495Sbill iaftbr++; 5541495Sbill if (p->forw->ref) 5551495Sbill decref(p->forw->ref); 5561495Sbill p->forw = p->forw->forw; 5571495Sbill p->forw->back = p; 5581495Sbill } 5591495Sbill rp = p->forw; 5601495Sbill while (rp && rp->op==LABEL) { 5611495Sbill if (p->ref == rp) { 5621495Sbill p->back->forw = p->forw; 5631495Sbill p->forw->back = p->back; 5641495Sbill p = p->back; 5651495Sbill decref(rp); 5661495Sbill nchange++; 5671495Sbill njp1++; 5681495Sbill break; 5691495Sbill } 5701495Sbill rp = rp->forw; 5711495Sbill } 5721495Sbill xjump(p); 5731495Sbill p = codemove(p); 5741495Sbill } 5751495Sbill } 5761495Sbill } 5771495Sbill 5781495Sbill xjump(p1) 5791495Sbill register struct node *p1; 5801495Sbill { 5811495Sbill register struct node *p2, *p3; 5821495Sbill 5831495Sbill if ((p2 = p1->ref)==0) 58418380Sralph return; 5851495Sbill for (;;) { 5861495Sbill while ((p1 = p1->back) && p1->op==LABEL); 5871495Sbill while ((p2 = p2->back) && p2->op==LABEL); 5881495Sbill if (!equop(p1, p2) || p1==p2) 58918380Sralph return; 5901495Sbill p3 = insertl(p2); 5911495Sbill p1->combop = JBR; 5921495Sbill p1->pop=0; 5931495Sbill p1->ref = p3; 5941495Sbill p1->labno = p3->labno; 5951495Sbill p1->code = 0; 5961495Sbill nxjump++; 5971495Sbill nchange++; 5981495Sbill } 5991495Sbill } 6001495Sbill 6011495Sbill struct node * 60218380Sralph insertl(np) 60318380Sralph register struct node *np; 6041495Sbill { 6051495Sbill register struct node *lp; 6061495Sbill 60718380Sralph if (np->op == LABEL) { 60818380Sralph np->refc++; 60918380Sralph return(np); 6101495Sbill } 61118380Sralph if (np->back->op == LABEL) { 61218380Sralph np = np->back; 61318380Sralph np->refc++; 61418380Sralph return(np); 6151495Sbill } 6161495Sbill lp = alloc(sizeof first); 6171495Sbill lp->combop = LABEL; 6181495Sbill lp->labno = isn++; 6191495Sbill lp->ref = 0; 6201495Sbill lp->code = 0; 6211495Sbill lp->refc = 1; 62218380Sralph lp->back = np->back; 62318380Sralph lp->forw = np; 62418380Sralph np->back->forw = lp; 62518380Sralph np->back = lp; 6261495Sbill return(lp); 6271495Sbill } 6281495Sbill 6291495Sbill struct node * 6301495Sbill codemove(ap) 6311495Sbill struct node *ap; 6321495Sbill { 6331495Sbill register struct node *p1, *p2, *p3; 6341495Sbill struct node *t, *tl; 6351495Sbill int n; 6361495Sbill 6371495Sbill p1 = ap; 6381495Sbill /* last clause to avoid infinite loop on partial compiler droppings: 6391495Sbill L183: jbr L179 6401495Sbill L191: jbr L179 6411495Sbill casel r0,$0,$1 6421495Sbill L193: .word L183-L193 6431495Sbill .word L191-L193 6441495Sbill L179: ret 6451495Sbill */ 6461495Sbill if (p1->op!=JBR || (p2 = p1->ref)==0 || p2==p1->forw) 6471495Sbill return(p1); 6481495Sbill while (p2->op == LABEL) 6491495Sbill if ((p2 = p2->back) == 0) 6501495Sbill return(p1); 6511495Sbill if (p2->op!=JBR && p2->op!=JMP) 6521495Sbill goto ivloop; 6531495Sbill p2 = p2->forw; 6541495Sbill p3 = p1->ref; 6551495Sbill while (p3) { 6561495Sbill if (p3->op==JBR || p3->op==JMP) { 6571495Sbill if (p1==p3) 6581495Sbill return(p1); 6591495Sbill ncmot++; 6601495Sbill nchange++; 6611495Sbill p1->back->forw = p2; 6621495Sbill p1->forw->back = p3; 6631495Sbill p2->back->forw = p3->forw; 6641495Sbill p3->forw->back = p2->back; 6651495Sbill p2->back = p1->back; 6661495Sbill p3->forw = p1->forw; 6671495Sbill decref(p1->ref); 6681495Sbill return(p2); 6691495Sbill } else 6701495Sbill p3 = p3->forw; 6711495Sbill } 6721495Sbill return(p1); 6731495Sbill ivloop: 6741495Sbill if (p1->forw->op!=LABEL) 6751495Sbill return(p1); 6761495Sbill p3 = p2 = p2->forw; 6771495Sbill n = 16; 6781495Sbill do { 6791495Sbill if ((p3 = p3->forw) == 0 || p3==p1 || --n==0) 6801495Sbill return(p1); 6811495Sbill } while (p3->op!=CBR || p3->labno!=p1->forw->labno); 6821495Sbill do 6831495Sbill if ((p1 = p1->back) == 0) 6841495Sbill return(ap); 6851495Sbill while (p1!=p3); 6861495Sbill p1 = ap; 6871495Sbill tl = insertl(p1); 6881495Sbill p3->subop = revbr[p3->subop]; 6891495Sbill p3->pop=0; 6901495Sbill decref(p3->ref); 6911495Sbill p2->back->forw = p1; 6921495Sbill p3->forw->back = p1; 6931495Sbill p1->back->forw = p2; 6941495Sbill p1->forw->back = p3; 6951495Sbill t = p1->back; 6961495Sbill p1->back = p2->back; 6971495Sbill p2->back = t; 6981495Sbill t = p1->forw; 6991495Sbill p1->forw = p3->forw; 7001495Sbill p3->forw = t; 7011495Sbill p2 = insertl(p1->forw); 7021495Sbill p3->labno = p2->labno; 7031495Sbill #ifdef COPYCODE 7041495Sbill if (p3->labno == 0) 7051495Sbill p3->code = p2->code; 7061495Sbill #endif 7071495Sbill p3->ref = p2; 7081495Sbill decref(tl); 7091495Sbill if (tl->refc<=0) 7101495Sbill nrlab--; 7111495Sbill loopiv++; 7121495Sbill nchange++; 7131495Sbill return(p3); 7141495Sbill } 7151495Sbill 7161495Sbill comjump() 7171495Sbill { 7181495Sbill register struct node *p1, *p2, *p3; 7191495Sbill 7201495Sbill for (p1 = first.forw; p1!=0; p1 = p1->forw) 7211495Sbill if (p1->op==JBR && ((p2 = p1->ref) && p2->refc > 1 7221495Sbill || p1->subop==RET || p1->subop==RSB)) 7231495Sbill for (p3 = p1->forw; p3!=0; p3 = p3->forw) 7241495Sbill if (p3->op==JBR && p3->ref == p2) 7251495Sbill backjmp(p1, p3); 7261495Sbill } 7271495Sbill 7281495Sbill backjmp(ap1, ap2) 7291495Sbill struct node *ap1, *ap2; 7301495Sbill { 7311495Sbill register struct node *p1, *p2, *p3; 7321495Sbill 7331495Sbill p1 = ap1; 7341495Sbill p2 = ap2; 7351495Sbill for(;;) { 7361495Sbill while ((p1 = p1->back) && p1->op==LABEL); 7371495Sbill p2 = p2->back; 7381495Sbill if (equop(p1, p2)) { 7391495Sbill p3 = insertl(p1); 7401495Sbill p2->back->forw = p2->forw; 7411495Sbill p2->forw->back = p2->back; 7421495Sbill p2 = p2->forw; 7431495Sbill decref(p2->ref); 7441495Sbill p2->combop = JBR; /* to handle RET */ 7451495Sbill p2->pop=0; 7461495Sbill p2->labno = p3->labno; 7471495Sbill #ifdef COPYCODE 7481495Sbill p2->code = 0; 7491495Sbill #endif 7501495Sbill p2->ref = p3; 7511495Sbill nchange++; 7521495Sbill ncomj++; 7531495Sbill } else 7541495Sbill return; 7551495Sbill } 7561495Sbill } 757