114572Ssam #ifndef lint 2*18380Sralph static char sccsid[] = "@(#)c20.c 4.9 (Berkeley) 03/19/85"; 314572Ssam #endif 414572Ssam 51495Sbill /* 61495Sbill * C object code improver 71495Sbill */ 81495Sbill 91495Sbill #include "c2.h" 101495Sbill #include <stdio.h> 111495Sbill #include <ctype.h> 12*18380Sralph #include <sys/types.h> 131495Sbill 141495Sbill char _sibuf[BUFSIZ], _sobuf[BUFSIZ]; 15*18380Sralph caddr_t sbrk(); 161495Sbill int ioflag; 1717719Sralph int fflag; 181508Sbill long isn = 2000000; 191495Sbill struct optab *oplook(); 201495Sbill struct optab *getline(); 211508Sbill long lgensym[10] = 221508Sbill {100000L,200000L,300000L,400000L,500000L,600000L,700000L,800000L,900000L,1000000L}; 231495Sbill 24*18380Sralph #define ALLOCSIZE 4096 25*18380Sralph 261495Sbill struct node * 271495Sbill alloc(an) 281495Sbill { 291495Sbill register int n; 30*18380Sralph register struct node *p; 311495Sbill 321495Sbill n = an; 331508Sbill n+=sizeof(char *)-1; 341508Sbill n &= ~(sizeof(char *)-1); 351495Sbill if (lasta+n >= lastr) { 36*18380Sralph if ((int) sbrk(ALLOCSIZE) == -1) { 371495Sbill fprintf(stderr, "Optimizer: out of space\n"); 381495Sbill exit(1); 391495Sbill } 40*18380Sralph lastr += ALLOCSIZE; 411495Sbill } 42*18380Sralph p = (struct node *) lasta; 431495Sbill lasta += n; 441495Sbill return(p); 451495Sbill } 461495Sbill 471495Sbill main(argc, argv) 481495Sbill char **argv; 491495Sbill { 501495Sbill register int niter, maxiter, isend; 511495Sbill int nflag,infound; 521495Sbill 531495Sbill nflag = 0; infound=0; argc--; argv++; 541495Sbill while (argc>0) {/* get flags */ 551495Sbill if (**argv=='+') debug++; 561495Sbill else if (**argv=='-') { 5717719Sralph if ((*argv)[1]=='i') ioflag++; 5817719Sralph else if ((*argv)[1]=='f') fflag++; 5917719Sralph else nflag++; 601495Sbill } else if (infound==0) { 611495Sbill if (freopen(*argv, "r", stdin) ==NULL) { 621495Sbill fprintf(stderr,"C2: can't find %s\n", *argv); 631495Sbill exit(1); 641495Sbill } 6516792Sralph ++infound; 661495Sbill } else if (freopen(*argv, "w", stdout) ==NULL) { 671495Sbill fprintf(stderr,"C2: can't create %s\n", *argv); 681495Sbill exit(1); 691495Sbill } 701495Sbill argc--; argv++; 711495Sbill } 7216792Sralph setbuf(stdin, _sibuf); 7316792Sralph setbuf(stdout, _sobuf); 74*18380Sralph lasta = lastr = (char *) sbrk(2); 751495Sbill opsetup(); 76*18380Sralph lasta = firstr = lastr = (char *) alloc(0); 771495Sbill maxiter = 0; 781495Sbill do { 791495Sbill isend = input(); 801495Sbill niter = 0; 811495Sbill bmove(); 821495Sbill do { 831495Sbill refcount(); 841495Sbill do { 851495Sbill iterate(); 861495Sbill clearreg(); 871495Sbill niter++; 881495Sbill } while (nchange); 891495Sbill comjump(); 901495Sbill rmove(); 911495Sbill } while (nchange || jumpsw()); 921495Sbill addsob(); 931495Sbill output(); 941495Sbill if (niter > maxiter) 951495Sbill maxiter = niter; 961495Sbill lasta = firstr; 971495Sbill } while (isend); 981495Sbill if (nflag) { 991495Sbill fprintf(stderr,"%d iterations\n", maxiter); 1001495Sbill fprintf(stderr,"%d jumps to jumps\n", nbrbr); 1011495Sbill fprintf(stderr,"%d inst. after jumps\n", iaftbr); 1021495Sbill fprintf(stderr,"%d jumps to .+1\n", njp1); 1031495Sbill fprintf(stderr,"%d redundant labels\n", nrlab); 1041495Sbill fprintf(stderr,"%d cross-jumps\n", nxjump); 1051495Sbill fprintf(stderr,"%d code motions\n", ncmot); 1061495Sbill fprintf(stderr,"%d branches reversed\n", nrevbr); 1071495Sbill fprintf(stderr,"%d redundant moves\n", redunm); 1081495Sbill fprintf(stderr,"%d simplified addresses\n", nsaddr); 1091495Sbill fprintf(stderr,"%d loops inverted\n", loopiv); 1101495Sbill fprintf(stderr,"%d redundant jumps\n", nredunj); 1111495Sbill fprintf(stderr,"%d common seqs before jmp's\n", ncomj); 1121495Sbill fprintf(stderr,"%d skips over jumps\n", nskip); 1131495Sbill fprintf(stderr,"%d sob's added\n", nsob); 1141495Sbill fprintf(stderr,"%d redundant tst's\n", nrtst); 1151495Sbill fprintf(stderr,"%d jump on bit\n", nbj); 1161495Sbill fprintf(stderr,"%d field operations\n", nfield); 1171495Sbill fprintf(stderr,"%dK core\n", ((unsigned)lastr+01777) >> 10); 1181495Sbill } 1191495Sbill putc('\n',stdout); 1201495Sbill fflush(stdout); exit(0); 1211495Sbill } 1221495Sbill 1231495Sbill input() 1241495Sbill { 1251495Sbill register struct node *p, *lastp; 126*18380Sralph struct optab *opp; register char *cp1; 1271495Sbill static struct optab F77JSW = {".long", T(JSW,1)}; 1281495Sbill 1291495Sbill lastp = &first; 1301495Sbill for (;;) { 1311495Sbill top: 132*18380Sralph opp = getline(); 133*18380Sralph if (debug && opp==0) fprintf(stderr,"? %s\n",line); 134*18380Sralph switch (opp->opcode&0377) { 1351495Sbill 1361495Sbill case LABEL: 1371495Sbill p = alloc(sizeof first); 1381495Sbill if (isdigit(line[0]) && (p->labno=locdef(line)) || 1391495Sbill (line[0] == 'L') && (p->labno=getnum(line+1))) { 1401495Sbill p->combop = LABEL; 1411508Sbill if (p->labno<100000L && isn<=p->labno) isn=1+p->labno; 1421495Sbill p->code = 0; 1431495Sbill } else { 1441495Sbill p->combop = DLABEL; 1451495Sbill p->labno = 0; 1461495Sbill p->code = copy(line); 1471495Sbill } 1481495Sbill break; 1491495Sbill 1501495Sbill case LGEN: 1511495Sbill if (*curlp!='L' && !locuse(curlp)) goto std; 152*18380Sralph opp= &F77JSW; 1531495Sbill case JBR: 154*18380Sralph if (opp->opcode==T(JBR,RET) || opp->opcode==T(JBR,RSB)) goto std; 1551495Sbill case CBR: 1561495Sbill case JMP: 1571495Sbill case JSW: 1581495Sbill case SOBGEQ: case SOBGTR: case AOBLEQ: case AOBLSS: case ACB: 1591495Sbill p = alloc(sizeof first); 160*18380Sralph p->combop = opp->opcode; p->code=0; cp1=curlp; 1611495Sbill if ((!isdigit(*cp1) || 0==(p->labno=locuse(cp1))) && 1621495Sbill (*cp1!='L' || 0==(p->labno = getnum(cp1+1)))) {/* jbs, etc.? */ 1631495Sbill while (*cp1++); while (*--cp1!=',' && cp1!=curlp); 1641495Sbill if (cp1==curlp || 1651495Sbill (!isdigit(*++cp1) || 0==(p->labno=locuse(cp1))) && 1661495Sbill (*cp1!='L' || 0==(p->labno=getnum(cp1+1)))) 1671495Sbill p->labno = 0; 1681495Sbill else *--cp1=0; 1691495Sbill p->code = copy(curlp); 1701495Sbill } 1711495Sbill if (isn<=p->labno) isn=1+p->labno; 1721495Sbill break; 1731495Sbill 1741495Sbill case MOVA: 1751495Sbill p=alloc(sizeof first); 176*18380Sralph p->combop=opp->opcode; p->code=0; cp1=curlp+1; 1771495Sbill if (cp1[-1]=='L' || isdigit(cp1[-1])) { 1781495Sbill while (*cp1++!=','); *--cp1=0; 1791495Sbill if (0!=(p->labno=locuse(curlp)) || 1801495Sbill 0!=(p->labno=getnum(curlp+1))) p->code=copy(cp1+1); 1811495Sbill else {*cp1=','; p->code=copy(curlp);} 1821495Sbill } else {p->code=copy(--cp1); p->labno=0;} 1831495Sbill break; 1841495Sbill 1851495Sbill case SET: 1861495Sbill case COMM: 1871495Sbill case LCOMM: 1881495Sbill printf("%s\n",line); goto top; 1891495Sbill 1901495Sbill case BSS: 1911495Sbill case DATA: 1921495Sbill for (;;) { 193*18380Sralph printf("%s%c",line,(opp->opcode==LABEL ? ':' : '\n')); 194*18380Sralph if (opp->opcode==TEXT) goto top; 195*18380Sralph if (END==(opp=getline())->opcode) {/* dangling .data is bad for you */ 1961495Sbill printf(".text\n"); 1971495Sbill break; 1981495Sbill } 1991495Sbill } 2001495Sbill 2011495Sbill std: 2021495Sbill default: 2031495Sbill p = alloc(sizeof first); 204*18380Sralph p->combop = opp->opcode; 2051495Sbill p->labno = 0; 2061495Sbill p->code = copy(curlp); 2071495Sbill break; 2081495Sbill 2091495Sbill } 2101495Sbill p->forw = 0; 2111495Sbill p->back = lastp; 212*18380Sralph p->pop = opp; 2131495Sbill lastp->forw = p; 2141495Sbill lastp = p; 2151495Sbill p->ref = 0; 2161495Sbill if (p->op==CASE) { 2171495Sbill char *lp; int ncase; 2181495Sbill lp=curlp; while (*lp++); while (*--lp!='$'); ncase=getnum(lp+1); 219*18380Sralph if (LABEL!=(getline())->opcode) { 220*18380Sralph fprintf(stderr, "c2: garbled 'case' instruction\n"); 221*18380Sralph exit(-2); 222*18380Sralph } 2231495Sbill do { 224*18380Sralph if (WGEN!=(getline())->opcode) { 225*18380Sralph fprintf(stderr, "c2: garbled 'case' instruction\n"); 226*18380Sralph exit(-3); 227*18380Sralph } 2281495Sbill p = alloc(sizeof first); p->combop = JSW; p->code = 0; 2291495Sbill lp=curlp; while(*lp++!='-'); *--lp=0; p->labno=getnum(curlp+1); 2301495Sbill if (isn<=p->labno) isn=1+p->labno; 2311495Sbill p->forw = 0; p->back = lastp; lastp->forw = p; lastp = p; 2321495Sbill p->ref = 0; p->pop=0; 2331495Sbill } while (--ncase>=0); 2341495Sbill } 235*18380Sralph if (opp->opcode==EROU) 2361495Sbill return(1); 237*18380Sralph if (opp->opcode==END) 2381495Sbill return(0); 2391495Sbill } 2401495Sbill } 2411495Sbill 2421495Sbill struct optab * 2431495Sbill getline() 2441495Sbill { 2451495Sbill register char *lp; 2461495Sbill register c; 2471495Sbill static struct optab OPLABEL={"",LABEL}; 2481495Sbill static struct optab OPEND={"",END}; 2491495Sbill 2501495Sbill lp = line; 2511495Sbill while (EOF!=(c=getchar()) && isspace(c)); 2521495Sbill while (EOF!=c) { 2531495Sbill if (c==':') { 2541495Sbill *lp++ = 0; 2551495Sbill return(&OPLABEL); 2561495Sbill } 2571495Sbill if (c=='\n') { 2581495Sbill *lp++ = 0; 2591495Sbill return(oplook()); 2601495Sbill } 2611495Sbill *lp++ = c; 2621495Sbill c = getchar(); 2631495Sbill } 2641495Sbill *lp++ = 0; 2651495Sbill return(&OPEND); 2661495Sbill } 2671495Sbill 2681495Sbill long 2691495Sbill getnum(p) 2701495Sbill register char *p; 2711495Sbill { 2721495Sbill register c; int neg; register long n; 2731495Sbill 2741495Sbill n = 0; neg=0; if (*p=='-') {++neg; ++p;} 2751495Sbill while (isdigit(c = *p++)) { 2761495Sbill c -= '0'; n *= 10; if (neg) n -= c; else n += c; 2771495Sbill } 2781495Sbill if (*--p != 0) 2791495Sbill return(0); 2801495Sbill return(n); 2811495Sbill } 2821495Sbill 2831495Sbill locuse(p) 2841495Sbill register char *p; 2851495Sbill { 2861495Sbill if (!isdigit(p[0]) || p[1] != 'f' && p[1] != 'b' || p[2]) return(0); 2871495Sbill return (lgensym[p[0] - '0'] - (p[1] == 'b')); 2881495Sbill } 2891495Sbill 2901495Sbill locdef(p) 2911495Sbill register char *p; 2921495Sbill { 2931495Sbill 2941495Sbill if (!isdigit(p[0]) || p[1]) return(0); 2951495Sbill return (lgensym[p[0] - '0']++); 2961495Sbill } 2971495Sbill 2981495Sbill output() 2991495Sbill { 3001495Sbill register struct node *t; 3011495Sbill int casebas; 3021495Sbill 3031495Sbill t = &first; 3041495Sbill while (t = t->forw) switch (t->op) { 3051495Sbill 3061495Sbill case END: 3071495Sbill fflush(stdout); 3081495Sbill return; 3091495Sbill 3101495Sbill case LABEL: 3111495Sbill printf("L%d:", t->labno); 3121495Sbill continue; 3131495Sbill 3141495Sbill case DLABEL: 3151495Sbill printf("%s:", t->code); 3161495Sbill continue; 3171495Sbill 3181495Sbill case CASE: 3191495Sbill casebas=0; 3201495Sbill 3211495Sbill default: std: 3221495Sbill if (t->pop==0) {/* must find it */ 3231495Sbill register struct optab *p; 3241495Sbill for (p=optab; p->opstring[0]; ++p) 3251495Sbill if (p->opcode==t->combop) {t->pop=p; break;} 3261495Sbill } 3271495Sbill printf("%s", t->pop->opstring); 3281495Sbill if (t->code) printf("\t%s", t->code); 3291495Sbill if (t->labno!=0) printf("%cL%d\n", 3301495Sbill (t->code ? ',' : '\t'), 3311495Sbill t->labno); 3321495Sbill else printf("\n"); 3331495Sbill continue; 3341495Sbill 3351495Sbill case MOVA: 3361495Sbill if (t->labno==0) goto std; 3371495Sbill printf("mova%c\tL%d,%s\n","bwlq"[t->subop-BYTE],t->labno,t->code); 3381495Sbill continue; 3391495Sbill 3401495Sbill case JSW: 3411495Sbill if (t->subop!=0) {/* F77JSW */ 3421495Sbill printf(".long\tL%d\n",t->labno); continue; 3431495Sbill } 3441495Sbill if (casebas==0) printf("L%d:\n",casebas=isn++); 3451495Sbill printf(".word L%d-L%d\n", t->labno, casebas); 3461495Sbill continue; 34717719Sralph case MOV: 34817719Sralph if (!fflag) goto std; 34917719Sralph if (t->forw) if(t->forw->op == CBR) goto std; 35017719Sralph if (*t->code == '$') goto std; 35117719Sralph if (t->subop == FFLOAT) 35217719Sralph { 35317719Sralph printf("movl\t%s\n", t->code); 35417719Sralph continue; 35517719Sralph } 35617719Sralph if (t->subop == DFLOAT || t->subop == GFLOAT) 35717719Sralph { 35817719Sralph printf("movq\t%s\n", t->code); 35917719Sralph continue; 36017719Sralph } 36117719Sralph if (t->subop == HFLOAT) 36217719Sralph { 36317719Sralph printf("movo\t%s\n", t->code); 36417719Sralph continue; 36517719Sralph } 36617719Sralph goto std; 3671495Sbill 3681495Sbill } 3691495Sbill } 3701495Sbill 3711495Sbill char * 3721495Sbill copy(ap) 3731495Sbill char *ap; 3741495Sbill { 3751495Sbill register char *p, *np; 3761495Sbill char *onp; 3771495Sbill register n; 3781495Sbill int na; 3791495Sbill 3801495Sbill na = nargs(); 3811495Sbill p = ap; 3821495Sbill n = 0; 3831495Sbill if (*p==0) 3841495Sbill return(0); 3851495Sbill do 3861495Sbill n++; 3871495Sbill while (*p++); 3881495Sbill if (na>1) { 3891495Sbill p = (&ap)[1]; 3901495Sbill while (*p++) 3911495Sbill n++; 3921495Sbill } 393*18380Sralph onp = np = (char *) alloc(n); 3941495Sbill p = ap; 3951495Sbill while (*np++ = *p++); 3961495Sbill if (na>1) { 3971495Sbill p = (&ap)[1]; 3981495Sbill np--; 3991495Sbill while (*np++ = *p++); 4001495Sbill } 4011495Sbill return(onp); 4021495Sbill } 4031495Sbill 4041495Sbill #define OPHS 560 4051495Sbill struct optab *ophash[OPHS]; 4061495Sbill 4071495Sbill opsetup() 4081495Sbill { 4091495Sbill register struct optab *optp, **ophp; 4101495Sbill register int i,t; 4111495Sbill 412*18380Sralph for(i=NREG+5;--i>=0;) regs[i]=(char *) alloc(C2_ASIZE); 4131495Sbill for (optp = optab; optp->opstring[0]; optp++) { 4141495Sbill t=7; i=0; while (--t>=0) i+= i+optp->opstring[t]; 4151495Sbill ophp = &ophash[i % OPHS]; 4161495Sbill while (*ophp++) { 4171495Sbill /* fprintf(stderr,"\ncollision: %d %s %s", 4181495Sbill /* ophp-1-ophash,optp->opstring,(*(ophp-1))->opstring); 4191495Sbill */ 4201495Sbill if (ophp > &ophash[OPHS]) 4211495Sbill ophp = ophash; 4221495Sbill } 4231495Sbill *--ophp = optp; 4241495Sbill } 4251495Sbill } 4261495Sbill 4271495Sbill struct optab * 4281495Sbill oplook() 4291495Sbill { 4301495Sbill register struct optab *optp,**ophp; 4311495Sbill register char *p,*p2; 4321495Sbill register int t; 4333933Sroot char tempop[20]; 4341495Sbill static struct optab OPNULL={"",0}; 4351495Sbill 4361495Sbill for (p=line, p2=tempop; *p && !isspace(*p); *p2++= *p++); *p2=0; p2=p; 4371495Sbill while (isspace(*p2)) ++p2; curlp=p2; 4381495Sbill t=0; while(--p>=line) t += t+*p; ophp = &ophash[t % OPHS]; 4391495Sbill while (optp = *ophp) { 4401495Sbill if (equstr(tempop,optp->opstring)) return(optp); 4411495Sbill if ((++ophp) >= &ophash[OPHS]) ophp = ophash; 4421495Sbill } 4431495Sbill curlp = line; 4441495Sbill return(&OPNULL); 4451495Sbill } 4461495Sbill 4471495Sbill refcount() 4481495Sbill { 449*18380Sralph register struct node *p, *lp, *tp; 4501495Sbill struct node *labhash[LABHS]; 4511495Sbill register struct node **hp; 4521495Sbill 4531495Sbill for (hp = labhash; hp < &labhash[LABHS];) 4541495Sbill *hp++ = 0; 4551495Sbill for (p = first.forw; p!=0; p = p->forw) 4561495Sbill if (p->op==LABEL) { 4571495Sbill labhash[p->labno % LABHS] = p; 4581495Sbill p->refc = 0; 4591495Sbill } 4601495Sbill for (p = first.forw; p!=0; p = p->forw) { 4611495Sbill if (p->combop==JBR || p->op==CBR || p->op==JSW || p->op==JMP 4621495Sbill || p->op==SOBGEQ || p->op==SOBGTR || p->op==AOBLEQ || p->op==AOBLSS 4631495Sbill || p->op==ACB || (p->op==MOVA && p->labno!=0)) { 4641495Sbill p->ref = 0; 4651495Sbill lp = labhash[p->labno % LABHS]; 4661495Sbill if (lp==0 || p->labno!=lp->labno) 4671495Sbill for (lp = first.forw; lp!=0; lp = lp->forw) { 4681495Sbill if (lp->op==LABEL && p->labno==lp->labno) 4691495Sbill break; 4701495Sbill } 4711495Sbill if (lp) { 472*18380Sralph tp = nonlab(lp)->back; 473*18380Sralph if (tp!=lp) { 474*18380Sralph p->labno = tp->labno; 475*18380Sralph lp = tp; 4761495Sbill } 4771495Sbill p->ref = lp; 4781495Sbill lp->refc++; 4791495Sbill } 4801495Sbill } 4811495Sbill } 4821495Sbill for (p = first.forw; p!=0; p = p->forw) 4831495Sbill if (p->op==LABEL && p->refc==0 4841495Sbill && (lp = nonlab(p))->op && lp->op!=JSW) 4851495Sbill decref(p); 4861495Sbill } 4871495Sbill 4881495Sbill iterate() 4891495Sbill { 4901495Sbill register struct node *p, *rp, *p1; 4911495Sbill 4921495Sbill nchange = 0; 4931495Sbill for (p = first.forw; p!=0; p = p->forw) { 4941495Sbill if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) { 4951495Sbill rp = nonlab(p->ref); 4961495Sbill if (rp->op==JBR && rp->labno && p->labno!=rp->labno) { 4971495Sbill nbrbr++; 4981495Sbill p->labno = rp->labno; 4991495Sbill decref(p->ref); 5001495Sbill rp->ref->refc++; 5011495Sbill p->ref = rp->ref; 5021495Sbill nchange++; 5031495Sbill } 5041495Sbill } 5051495Sbill #ifndef COPYCODE 5061495Sbill if (p->op==CBR && (p1 = p->forw)->combop==JBR) {/* combop: RET problems */ 5071495Sbill #else 5081495Sbill if (p->op==CBR && (p1 = p->forw)->combop==JBR && 5091495Sbill p->ref) {/* combop: RET problems */ 5101495Sbill #endif 5111495Sbill rp = p->ref; 5121495Sbill do 5131495Sbill rp = rp->back; 5141495Sbill while (rp->op==LABEL); 5151495Sbill if (rp==p1) { 5161495Sbill decref(p->ref); 5171495Sbill p->ref = p1->ref; 5181495Sbill p->labno = p1->labno; 5191495Sbill #ifdef COPYCODE 5201495Sbill if (p->labno == 0) 5211495Sbill p->code = p1->code; 5221495Sbill #endif 5231495Sbill p1->forw->back = p; 5241495Sbill p->forw = p1->forw; 5251495Sbill p->subop = revbr[p->subop]; 5261495Sbill p->pop=0; 5271495Sbill nchange++; 5281495Sbill nskip++; 5291495Sbill } 5301495Sbill } 5311495Sbill if (p->op==JBR || p->op==JMP) { 5321495Sbill while (p->forw && p->forw->op!=LABEL && p->forw->op!=DLABEL 5331495Sbill && p->forw->op!=EROU && p->forw->op!=END 5341495Sbill && p->forw->op!=ALIGN 5351495Sbill && p->forw->op!=0 && p->forw->op!=DATA) { 5361495Sbill nchange++; 5371495Sbill iaftbr++; 5381495Sbill if (p->forw->ref) 5391495Sbill decref(p->forw->ref); 5401495Sbill p->forw = p->forw->forw; 5411495Sbill p->forw->back = p; 5421495Sbill } 5431495Sbill rp = p->forw; 5441495Sbill while (rp && rp->op==LABEL) { 5451495Sbill if (p->ref == rp) { 5461495Sbill p->back->forw = p->forw; 5471495Sbill p->forw->back = p->back; 5481495Sbill p = p->back; 5491495Sbill decref(rp); 5501495Sbill nchange++; 5511495Sbill njp1++; 5521495Sbill break; 5531495Sbill } 5541495Sbill rp = rp->forw; 5551495Sbill } 5561495Sbill xjump(p); 5571495Sbill p = codemove(p); 5581495Sbill } 5591495Sbill } 5601495Sbill } 5611495Sbill 5621495Sbill xjump(p1) 5631495Sbill register struct node *p1; 5641495Sbill { 5651495Sbill register struct node *p2, *p3; 5661495Sbill 5671495Sbill if ((p2 = p1->ref)==0) 568*18380Sralph return; 5691495Sbill for (;;) { 5701495Sbill while ((p1 = p1->back) && p1->op==LABEL); 5711495Sbill while ((p2 = p2->back) && p2->op==LABEL); 5721495Sbill if (!equop(p1, p2) || p1==p2) 573*18380Sralph return; 5741495Sbill p3 = insertl(p2); 5751495Sbill p1->combop = JBR; 5761495Sbill p1->pop=0; 5771495Sbill p1->ref = p3; 5781495Sbill p1->labno = p3->labno; 5791495Sbill p1->code = 0; 5801495Sbill nxjump++; 5811495Sbill nchange++; 5821495Sbill } 5831495Sbill } 5841495Sbill 5851495Sbill struct node * 586*18380Sralph insertl(np) 587*18380Sralph register struct node *np; 5881495Sbill { 5891495Sbill register struct node *lp; 5901495Sbill 591*18380Sralph if (np->op == LABEL) { 592*18380Sralph np->refc++; 593*18380Sralph return(np); 5941495Sbill } 595*18380Sralph if (np->back->op == LABEL) { 596*18380Sralph np = np->back; 597*18380Sralph np->refc++; 598*18380Sralph return(np); 5991495Sbill } 6001495Sbill lp = alloc(sizeof first); 6011495Sbill lp->combop = LABEL; 6021495Sbill lp->labno = isn++; 6031495Sbill lp->ref = 0; 6041495Sbill lp->code = 0; 6051495Sbill lp->refc = 1; 606*18380Sralph lp->back = np->back; 607*18380Sralph lp->forw = np; 608*18380Sralph np->back->forw = lp; 609*18380Sralph np->back = lp; 6101495Sbill return(lp); 6111495Sbill } 6121495Sbill 6131495Sbill struct node * 6141495Sbill codemove(ap) 6151495Sbill struct node *ap; 6161495Sbill { 6171495Sbill register struct node *p1, *p2, *p3; 6181495Sbill struct node *t, *tl; 6191495Sbill int n; 6201495Sbill 6211495Sbill p1 = ap; 6221495Sbill /* last clause to avoid infinite loop on partial compiler droppings: 6231495Sbill L183: jbr L179 6241495Sbill L191: jbr L179 6251495Sbill casel r0,$0,$1 6261495Sbill L193: .word L183-L193 6271495Sbill .word L191-L193 6281495Sbill L179: ret 6291495Sbill */ 6301495Sbill if (p1->op!=JBR || (p2 = p1->ref)==0 || p2==p1->forw) 6311495Sbill return(p1); 6321495Sbill while (p2->op == LABEL) 6331495Sbill if ((p2 = p2->back) == 0) 6341495Sbill return(p1); 6351495Sbill if (p2->op!=JBR && p2->op!=JMP) 6361495Sbill goto ivloop; 6371495Sbill p2 = p2->forw; 6381495Sbill p3 = p1->ref; 6391495Sbill while (p3) { 6401495Sbill if (p3->op==JBR || p3->op==JMP) { 6411495Sbill if (p1==p3) 6421495Sbill return(p1); 6431495Sbill ncmot++; 6441495Sbill nchange++; 6451495Sbill p1->back->forw = p2; 6461495Sbill p1->forw->back = p3; 6471495Sbill p2->back->forw = p3->forw; 6481495Sbill p3->forw->back = p2->back; 6491495Sbill p2->back = p1->back; 6501495Sbill p3->forw = p1->forw; 6511495Sbill decref(p1->ref); 6521495Sbill return(p2); 6531495Sbill } else 6541495Sbill p3 = p3->forw; 6551495Sbill } 6561495Sbill return(p1); 6571495Sbill ivloop: 6581495Sbill if (p1->forw->op!=LABEL) 6591495Sbill return(p1); 6601495Sbill p3 = p2 = p2->forw; 6611495Sbill n = 16; 6621495Sbill do { 6631495Sbill if ((p3 = p3->forw) == 0 || p3==p1 || --n==0) 6641495Sbill return(p1); 6651495Sbill } while (p3->op!=CBR || p3->labno!=p1->forw->labno); 6661495Sbill do 6671495Sbill if ((p1 = p1->back) == 0) 6681495Sbill return(ap); 6691495Sbill while (p1!=p3); 6701495Sbill p1 = ap; 6711495Sbill tl = insertl(p1); 6721495Sbill p3->subop = revbr[p3->subop]; 6731495Sbill p3->pop=0; 6741495Sbill decref(p3->ref); 6751495Sbill p2->back->forw = p1; 6761495Sbill p3->forw->back = p1; 6771495Sbill p1->back->forw = p2; 6781495Sbill p1->forw->back = p3; 6791495Sbill t = p1->back; 6801495Sbill p1->back = p2->back; 6811495Sbill p2->back = t; 6821495Sbill t = p1->forw; 6831495Sbill p1->forw = p3->forw; 6841495Sbill p3->forw = t; 6851495Sbill p2 = insertl(p1->forw); 6861495Sbill p3->labno = p2->labno; 6871495Sbill #ifdef COPYCODE 6881495Sbill if (p3->labno == 0) 6891495Sbill p3->code = p2->code; 6901495Sbill #endif 6911495Sbill p3->ref = p2; 6921495Sbill decref(tl); 6931495Sbill if (tl->refc<=0) 6941495Sbill nrlab--; 6951495Sbill loopiv++; 6961495Sbill nchange++; 6971495Sbill return(p3); 6981495Sbill } 6991495Sbill 7001495Sbill comjump() 7011495Sbill { 7021495Sbill register struct node *p1, *p2, *p3; 7031495Sbill 7041495Sbill for (p1 = first.forw; p1!=0; p1 = p1->forw) 7051495Sbill if (p1->op==JBR && ((p2 = p1->ref) && p2->refc > 1 7061495Sbill || p1->subop==RET || p1->subop==RSB)) 7071495Sbill for (p3 = p1->forw; p3!=0; p3 = p3->forw) 7081495Sbill if (p3->op==JBR && p3->ref == p2) 7091495Sbill backjmp(p1, p3); 7101495Sbill } 7111495Sbill 7121495Sbill backjmp(ap1, ap2) 7131495Sbill struct node *ap1, *ap2; 7141495Sbill { 7151495Sbill register struct node *p1, *p2, *p3; 7161495Sbill 7171495Sbill p1 = ap1; 7181495Sbill p2 = ap2; 7191495Sbill for(;;) { 7201495Sbill while ((p1 = p1->back) && p1->op==LABEL); 7211495Sbill p2 = p2->back; 7221495Sbill if (equop(p1, p2)) { 7231495Sbill p3 = insertl(p1); 7241495Sbill p2->back->forw = p2->forw; 7251495Sbill p2->forw->back = p2->back; 7261495Sbill p2 = p2->forw; 7271495Sbill decref(p2->ref); 7281495Sbill p2->combop = JBR; /* to handle RET */ 7291495Sbill p2->pop=0; 7301495Sbill p2->labno = p3->labno; 7311495Sbill #ifdef COPYCODE 7321495Sbill p2->code = 0; 7331495Sbill #endif 7341495Sbill p2->ref = p3; 7351495Sbill nchange++; 7361495Sbill ncomj++; 7371495Sbill } else 7381495Sbill return; 7391495Sbill } 7401495Sbill } 741