114572Ssam #ifndef lint 2*17719Sralph static char sccsid[] = "@(#)c20.c 4.8 (Berkeley) 01/16/85"; 314572Ssam #endif 414572Ssam 51495Sbill /* 61495Sbill * C object code improver 71495Sbill */ 81495Sbill 91495Sbill #include "c2.h" 101495Sbill #include <stdio.h> 111495Sbill #include <ctype.h> 121495Sbill 131495Sbill char _sibuf[BUFSIZ], _sobuf[BUFSIZ]; 141495Sbill int ioflag; 15*17719Sralph int fflag; 161508Sbill long isn = 2000000; 171495Sbill struct optab *oplook(); 181495Sbill struct optab *getline(); 191508Sbill long lgensym[10] = 201508Sbill {100000L,200000L,300000L,400000L,500000L,600000L,700000L,800000L,900000L,1000000L}; 211495Sbill 221495Sbill struct node * 231495Sbill alloc(an) 241495Sbill { 251495Sbill register int n; 261495Sbill register char *p; 271495Sbill 281495Sbill n = an; 291508Sbill n+=sizeof(char *)-1; 301508Sbill n &= ~(sizeof(char *)-1); 311495Sbill if (lasta+n >= lastr) { 321495Sbill if (sbrk(2000) == -1) { 331495Sbill fprintf(stderr, "Optimizer: out of space\n"); 341495Sbill exit(1); 351495Sbill } 361495Sbill lastr += 2000; 371495Sbill } 381495Sbill p = lasta; 391495Sbill lasta += n; 401495Sbill return(p); 411495Sbill } 421495Sbill 431495Sbill main(argc, argv) 441495Sbill char **argv; 451495Sbill { 461495Sbill register int niter, maxiter, isend; 471495Sbill int nflag,infound; 481495Sbill 491495Sbill nflag = 0; infound=0; argc--; argv++; 501495Sbill while (argc>0) {/* get flags */ 511495Sbill if (**argv=='+') debug++; 521495Sbill else if (**argv=='-') { 53*17719Sralph if ((*argv)[1]=='i') ioflag++; 54*17719Sralph else if ((*argv)[1]=='f') fflag++; 55*17719Sralph else nflag++; 561495Sbill } else if (infound==0) { 571495Sbill if (freopen(*argv, "r", stdin) ==NULL) { 581495Sbill fprintf(stderr,"C2: can't find %s\n", *argv); 591495Sbill exit(1); 601495Sbill } 6116792Sralph ++infound; 621495Sbill } else if (freopen(*argv, "w", stdout) ==NULL) { 631495Sbill fprintf(stderr,"C2: can't create %s\n", *argv); 641495Sbill exit(1); 651495Sbill } 661495Sbill argc--; argv++; 671495Sbill } 6816792Sralph setbuf(stdin, _sibuf); 6916792Sralph setbuf(stdout, _sobuf); 701495Sbill lasta = lastr = sbrk(2); 711495Sbill opsetup(); 721495Sbill lasta = firstr = lastr = alloc(0); 731495Sbill maxiter = 0; 741495Sbill do { 751495Sbill isend = input(); 761495Sbill niter = 0; 771495Sbill bmove(); 781495Sbill do { 791495Sbill refcount(); 801495Sbill do { 811495Sbill iterate(); 821495Sbill clearreg(); 831495Sbill niter++; 841495Sbill } while (nchange); 851495Sbill comjump(); 861495Sbill rmove(); 871495Sbill } while (nchange || jumpsw()); 881495Sbill addsob(); 891495Sbill output(); 901495Sbill if (niter > maxiter) 911495Sbill maxiter = niter; 921495Sbill lasta = firstr; 931495Sbill } while (isend); 941495Sbill if (nflag) { 951495Sbill fprintf(stderr,"%d iterations\n", maxiter); 961495Sbill fprintf(stderr,"%d jumps to jumps\n", nbrbr); 971495Sbill fprintf(stderr,"%d inst. after jumps\n", iaftbr); 981495Sbill fprintf(stderr,"%d jumps to .+1\n", njp1); 991495Sbill fprintf(stderr,"%d redundant labels\n", nrlab); 1001495Sbill fprintf(stderr,"%d cross-jumps\n", nxjump); 1011495Sbill fprintf(stderr,"%d code motions\n", ncmot); 1021495Sbill fprintf(stderr,"%d branches reversed\n", nrevbr); 1031495Sbill fprintf(stderr,"%d redundant moves\n", redunm); 1041495Sbill fprintf(stderr,"%d simplified addresses\n", nsaddr); 1051495Sbill fprintf(stderr,"%d loops inverted\n", loopiv); 1061495Sbill fprintf(stderr,"%d redundant jumps\n", nredunj); 1071495Sbill fprintf(stderr,"%d common seqs before jmp's\n", ncomj); 1081495Sbill fprintf(stderr,"%d skips over jumps\n", nskip); 1091495Sbill fprintf(stderr,"%d sob's added\n", nsob); 1101495Sbill fprintf(stderr,"%d redundant tst's\n", nrtst); 1111495Sbill fprintf(stderr,"%d jump on bit\n", nbj); 1121495Sbill fprintf(stderr,"%d field operations\n", nfield); 1131495Sbill fprintf(stderr,"%dK core\n", ((unsigned)lastr+01777) >> 10); 1141495Sbill } 1151495Sbill putc('\n',stdout); 1161495Sbill fflush(stdout); exit(0); 1171495Sbill } 1181495Sbill 1191495Sbill input() 1201495Sbill { 1211495Sbill register struct node *p, *lastp; 1221495Sbill struct optab *op; register char *cp1; 1231495Sbill static struct optab F77JSW = {".long", T(JSW,1)}; 1241495Sbill 1251495Sbill lastp = &first; 1261495Sbill for (;;) { 1271495Sbill top: 1281495Sbill op = getline(); 1291495Sbill if (debug && op==0) fprintf(stderr,"? %s\n",line); 1301495Sbill switch (op->opcode&0377) { 1311495Sbill 1321495Sbill case LABEL: 1331495Sbill p = alloc(sizeof first); 1341495Sbill if (isdigit(line[0]) && (p->labno=locdef(line)) || 1351495Sbill (line[0] == 'L') && (p->labno=getnum(line+1))) { 1361495Sbill p->combop = LABEL; 1371508Sbill if (p->labno<100000L && isn<=p->labno) isn=1+p->labno; 1381495Sbill p->code = 0; 1391495Sbill } else { 1401495Sbill p->combop = DLABEL; 1411495Sbill p->labno = 0; 1421495Sbill p->code = copy(line); 1431495Sbill } 1441495Sbill break; 1451495Sbill 1461495Sbill case LGEN: 1471495Sbill if (*curlp!='L' && !locuse(curlp)) goto std; 1481495Sbill op= &F77JSW; 1491495Sbill case JBR: 1501495Sbill if (op->opcode==T(JBR,RET) || op->opcode==T(JBR,RSB)) goto std; 1511495Sbill case CBR: 1521495Sbill case JMP: 1531495Sbill case JSW: 1541495Sbill case SOBGEQ: case SOBGTR: case AOBLEQ: case AOBLSS: case ACB: 1551495Sbill p = alloc(sizeof first); 1561495Sbill p->combop = op->opcode; p->code=0; cp1=curlp; 1571495Sbill if ((!isdigit(*cp1) || 0==(p->labno=locuse(cp1))) && 1581495Sbill (*cp1!='L' || 0==(p->labno = getnum(cp1+1)))) {/* jbs, etc.? */ 1591495Sbill while (*cp1++); while (*--cp1!=',' && cp1!=curlp); 1601495Sbill if (cp1==curlp || 1611495Sbill (!isdigit(*++cp1) || 0==(p->labno=locuse(cp1))) && 1621495Sbill (*cp1!='L' || 0==(p->labno=getnum(cp1+1)))) 1631495Sbill p->labno = 0; 1641495Sbill else *--cp1=0; 1651495Sbill p->code = copy(curlp); 1661495Sbill } 1671495Sbill if (isn<=p->labno) isn=1+p->labno; 1681495Sbill break; 1691495Sbill 1701495Sbill case MOVA: 1711495Sbill p=alloc(sizeof first); 1721495Sbill p->combop=op->opcode; p->code=0; cp1=curlp+1; 1731495Sbill if (cp1[-1]=='L' || isdigit(cp1[-1])) { 1741495Sbill while (*cp1++!=','); *--cp1=0; 1751495Sbill if (0!=(p->labno=locuse(curlp)) || 1761495Sbill 0!=(p->labno=getnum(curlp+1))) p->code=copy(cp1+1); 1771495Sbill else {*cp1=','; p->code=copy(curlp);} 1781495Sbill } else {p->code=copy(--cp1); p->labno=0;} 1791495Sbill break; 1801495Sbill 1811495Sbill case SET: 1821495Sbill case COMM: 1831495Sbill case LCOMM: 1841495Sbill printf("%s\n",line); goto top; 1851495Sbill 1861495Sbill case BSS: 1871495Sbill case DATA: 1881495Sbill for (;;) { 1891495Sbill printf("%s%c",line,(op->opcode==LABEL ? ':' : '\n')); 1901495Sbill if (op->opcode==TEXT) goto top; 1911495Sbill if (END==(op=getline())->opcode) {/* dangling .data is bad for you */ 1921495Sbill printf(".text\n"); 1931495Sbill break; 1941495Sbill } 1951495Sbill } 1961495Sbill 1971495Sbill std: 1981495Sbill default: 1991495Sbill p = alloc(sizeof first); 2001495Sbill p->combop = op->opcode; 2011495Sbill p->labno = 0; 2021495Sbill p->code = copy(curlp); 2031495Sbill break; 2041495Sbill 2051495Sbill } 2061495Sbill p->forw = 0; 2071495Sbill p->back = lastp; 2081495Sbill p->pop = op; 2091495Sbill lastp->forw = p; 2101495Sbill lastp = p; 2111495Sbill p->ref = 0; 2121495Sbill if (p->op==CASE) { 2131495Sbill char *lp; int ncase; 2141495Sbill lp=curlp; while (*lp++); while (*--lp!='$'); ncase=getnum(lp+1); 2151495Sbill if (LABEL!=(getline())->opcode) abort(-2); 2161495Sbill do { 2171495Sbill if (WGEN!=(getline())->opcode) abort(-3); 2181495Sbill p = alloc(sizeof first); p->combop = JSW; p->code = 0; 2191495Sbill lp=curlp; while(*lp++!='-'); *--lp=0; p->labno=getnum(curlp+1); 2201495Sbill if (isn<=p->labno) isn=1+p->labno; 2211495Sbill p->forw = 0; p->back = lastp; lastp->forw = p; lastp = p; 2221495Sbill p->ref = 0; p->pop=0; 2231495Sbill } while (--ncase>=0); 2241495Sbill } 2251495Sbill if (op->opcode==EROU) 2261495Sbill return(1); 2271495Sbill if (op->opcode==END) 2281495Sbill return(0); 2291495Sbill } 2301495Sbill } 2311495Sbill 2321495Sbill struct optab * 2331495Sbill getline() 2341495Sbill { 2351495Sbill register char *lp; 2361495Sbill register c; 2371495Sbill static struct optab OPLABEL={"",LABEL}; 2381495Sbill static struct optab OPEND={"",END}; 2391495Sbill 2401495Sbill lp = line; 2411495Sbill while (EOF!=(c=getchar()) && isspace(c)); 2421495Sbill while (EOF!=c) { 2431495Sbill if (c==':') { 2441495Sbill *lp++ = 0; 2451495Sbill return(&OPLABEL); 2461495Sbill } 2471495Sbill if (c=='\n') { 2481495Sbill *lp++ = 0; 2491495Sbill return(oplook()); 2501495Sbill } 2511495Sbill *lp++ = c; 2521495Sbill c = getchar(); 2531495Sbill } 2541495Sbill *lp++ = 0; 2551495Sbill return(&OPEND); 2561495Sbill } 2571495Sbill 2581495Sbill long 2591495Sbill getnum(p) 2601495Sbill register char *p; 2611495Sbill { 2621495Sbill register c; int neg; register long n; 2631495Sbill 2641495Sbill n = 0; neg=0; if (*p=='-') {++neg; ++p;} 2651495Sbill while (isdigit(c = *p++)) { 2661495Sbill c -= '0'; n *= 10; if (neg) n -= c; else n += c; 2671495Sbill } 2681495Sbill if (*--p != 0) 2691495Sbill return(0); 2701495Sbill return(n); 2711495Sbill } 2721495Sbill 2731495Sbill locuse(p) 2741495Sbill register char *p; 2751495Sbill { 2761495Sbill register c; int neg; register long n; 2771495Sbill 2781495Sbill if (!isdigit(p[0]) || p[1] != 'f' && p[1] != 'b' || p[2]) return(0); 2791495Sbill return (lgensym[p[0] - '0'] - (p[1] == 'b')); 2801495Sbill } 2811495Sbill 2821495Sbill locdef(p) 2831495Sbill register char *p; 2841495Sbill { 2851495Sbill 2861495Sbill if (!isdigit(p[0]) || p[1]) return(0); 2871495Sbill return (lgensym[p[0] - '0']++); 2881495Sbill } 2891495Sbill 2901495Sbill output() 2911495Sbill { 2921495Sbill register struct node *t; 2931495Sbill int casebas; 2941495Sbill 2951495Sbill t = &first; 2961495Sbill while (t = t->forw) switch (t->op) { 2971495Sbill 2981495Sbill case END: 2991495Sbill fflush(stdout); 3001495Sbill return; 3011495Sbill 3021495Sbill case LABEL: 3031495Sbill printf("L%d:", t->labno); 3041495Sbill continue; 3051495Sbill 3061495Sbill case DLABEL: 3071495Sbill printf("%s:", t->code); 3081495Sbill continue; 3091495Sbill 3101495Sbill case CASE: 3111495Sbill casebas=0; 3121495Sbill 3131495Sbill default: std: 3141495Sbill if (t->pop==0) {/* must find it */ 3151495Sbill register struct optab *p; 3161495Sbill for (p=optab; p->opstring[0]; ++p) 3171495Sbill if (p->opcode==t->combop) {t->pop=p; break;} 3181495Sbill } 3191495Sbill printf("%s", t->pop->opstring); 3201495Sbill if (t->code) printf("\t%s", t->code); 3211495Sbill if (t->labno!=0) printf("%cL%d\n", 3221495Sbill (t->code ? ',' : '\t'), 3231495Sbill t->labno); 3241495Sbill else printf("\n"); 3251495Sbill continue; 3261495Sbill 3271495Sbill case MOVA: 3281495Sbill if (t->labno==0) goto std; 3291495Sbill printf("mova%c\tL%d,%s\n","bwlq"[t->subop-BYTE],t->labno,t->code); 3301495Sbill continue; 3311495Sbill 3321495Sbill case JSW: 3331495Sbill if (t->subop!=0) {/* F77JSW */ 3341495Sbill printf(".long\tL%d\n",t->labno); continue; 3351495Sbill } 3361495Sbill if (casebas==0) printf("L%d:\n",casebas=isn++); 3371495Sbill printf(".word L%d-L%d\n", t->labno, casebas); 3381495Sbill continue; 339*17719Sralph case MOV: 340*17719Sralph if (!fflag) goto std; 341*17719Sralph if (t->forw) if(t->forw->op == CBR) goto std; 342*17719Sralph if (*t->code == '$') goto std; 343*17719Sralph if (t->subop == FFLOAT) 344*17719Sralph { 345*17719Sralph printf("movl\t%s\n", t->code); 346*17719Sralph continue; 347*17719Sralph } 348*17719Sralph if (t->subop == DFLOAT || t->subop == GFLOAT) 349*17719Sralph { 350*17719Sralph printf("movq\t%s\n", t->code); 351*17719Sralph continue; 352*17719Sralph } 353*17719Sralph if (t->subop == HFLOAT) 354*17719Sralph { 355*17719Sralph printf("movo\t%s\n", t->code); 356*17719Sralph continue; 357*17719Sralph } 358*17719Sralph goto std; 3591495Sbill 3601495Sbill } 3611495Sbill } 3621495Sbill 3631495Sbill char * 3641495Sbill copy(ap) 3651495Sbill char *ap; 3661495Sbill { 3671495Sbill register char *p, *np; 3681495Sbill char *onp; 3691495Sbill register n; 3701495Sbill int na; 3711495Sbill 3721495Sbill na = nargs(); 3731495Sbill p = ap; 3741495Sbill n = 0; 3751495Sbill if (*p==0) 3761495Sbill return(0); 3771495Sbill do 3781495Sbill n++; 3791495Sbill while (*p++); 3801495Sbill if (na>1) { 3811495Sbill p = (&ap)[1]; 3821495Sbill while (*p++) 3831495Sbill n++; 3841495Sbill } 3851495Sbill onp = np = alloc(n); 3861495Sbill p = ap; 3871495Sbill while (*np++ = *p++); 3881495Sbill if (na>1) { 3891495Sbill p = (&ap)[1]; 3901495Sbill np--; 3911495Sbill while (*np++ = *p++); 3921495Sbill } 3931495Sbill return(onp); 3941495Sbill } 3951495Sbill 3961495Sbill #define OPHS 560 3971495Sbill struct optab *ophash[OPHS]; 3981495Sbill 3991495Sbill opsetup() 4001495Sbill { 4011495Sbill register struct optab *optp, **ophp; 4021495Sbill register int i,t; 4031495Sbill 4042830Stoy for(i=NREG+5;--i>=0;) regs[i]=alloc(C2_ASIZE); 4051495Sbill for (optp = optab; optp->opstring[0]; optp++) { 4061495Sbill t=7; i=0; while (--t>=0) i+= i+optp->opstring[t]; 4071495Sbill ophp = &ophash[i % OPHS]; 4081495Sbill while (*ophp++) { 4091495Sbill /* fprintf(stderr,"\ncollision: %d %s %s", 4101495Sbill /* ophp-1-ophash,optp->opstring,(*(ophp-1))->opstring); 4111495Sbill */ 4121495Sbill if (ophp > &ophash[OPHS]) 4131495Sbill ophp = ophash; 4141495Sbill } 4151495Sbill *--ophp = optp; 4161495Sbill } 4171495Sbill } 4181495Sbill 4191495Sbill struct optab * 4201495Sbill oplook() 4211495Sbill { 4221495Sbill register struct optab *optp,**ophp; 4231495Sbill register char *p,*p2; 4241495Sbill register int t; 4253933Sroot char tempop[20]; 4261495Sbill static struct optab OPNULL={"",0}; 4271495Sbill 4281495Sbill for (p=line, p2=tempop; *p && !isspace(*p); *p2++= *p++); *p2=0; p2=p; 4291495Sbill while (isspace(*p2)) ++p2; curlp=p2; 4301495Sbill t=0; while(--p>=line) t += t+*p; ophp = &ophash[t % OPHS]; 4311495Sbill while (optp = *ophp) { 4321495Sbill if (equstr(tempop,optp->opstring)) return(optp); 4331495Sbill if ((++ophp) >= &ophash[OPHS]) ophp = ophash; 4341495Sbill } 4351495Sbill curlp = line; 4361495Sbill return(&OPNULL); 4371495Sbill } 4381495Sbill 4391495Sbill refcount() 4401495Sbill { 4411495Sbill register struct node *p, *lp; 4421495Sbill struct node *labhash[LABHS]; 4431495Sbill register struct node **hp; 4441495Sbill 4451495Sbill for (hp = labhash; hp < &labhash[LABHS];) 4461495Sbill *hp++ = 0; 4471495Sbill for (p = first.forw; p!=0; p = p->forw) 4481495Sbill if (p->op==LABEL) { 4491495Sbill labhash[p->labno % LABHS] = p; 4501495Sbill p->refc = 0; 4511495Sbill } 4521495Sbill for (p = first.forw; p!=0; p = p->forw) { 4531495Sbill if (p->combop==JBR || p->op==CBR || p->op==JSW || p->op==JMP 4541495Sbill || p->op==SOBGEQ || p->op==SOBGTR || p->op==AOBLEQ || p->op==AOBLSS 4551495Sbill || p->op==ACB || (p->op==MOVA && p->labno!=0)) { 4561495Sbill p->ref = 0; 4571495Sbill lp = labhash[p->labno % LABHS]; 4581495Sbill if (lp==0 || p->labno!=lp->labno) 4591495Sbill for (lp = first.forw; lp!=0; lp = lp->forw) { 4601495Sbill if (lp->op==LABEL && p->labno==lp->labno) 4611495Sbill break; 4621495Sbill } 4631495Sbill if (lp) { 4641495Sbill hp = nonlab(lp)->back; 4651495Sbill if (hp!=lp) { 4661495Sbill p->labno = hp->labno; 4671495Sbill lp = hp; 4681495Sbill } 4691495Sbill p->ref = lp; 4701495Sbill lp->refc++; 4711495Sbill } 4721495Sbill } 4731495Sbill } 4741495Sbill for (p = first.forw; p!=0; p = p->forw) 4751495Sbill if (p->op==LABEL && p->refc==0 4761495Sbill && (lp = nonlab(p))->op && lp->op!=JSW) 4771495Sbill decref(p); 4781495Sbill } 4791495Sbill 4801495Sbill iterate() 4811495Sbill { 4821495Sbill register struct node *p, *rp, *p1; 4831495Sbill 4841495Sbill nchange = 0; 4851495Sbill for (p = first.forw; p!=0; p = p->forw) { 4861495Sbill if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) { 4871495Sbill rp = nonlab(p->ref); 4881495Sbill if (rp->op==JBR && rp->labno && p->labno!=rp->labno) { 4891495Sbill nbrbr++; 4901495Sbill p->labno = rp->labno; 4911495Sbill decref(p->ref); 4921495Sbill rp->ref->refc++; 4931495Sbill p->ref = rp->ref; 4941495Sbill nchange++; 4951495Sbill } 4961495Sbill } 4971495Sbill #ifndef COPYCODE 4981495Sbill if (p->op==CBR && (p1 = p->forw)->combop==JBR) {/* combop: RET problems */ 4991495Sbill #else 5001495Sbill if (p->op==CBR && (p1 = p->forw)->combop==JBR && 5011495Sbill p->ref) {/* combop: RET problems */ 5021495Sbill #endif 5031495Sbill rp = p->ref; 5041495Sbill do 5051495Sbill rp = rp->back; 5061495Sbill while (rp->op==LABEL); 5071495Sbill if (rp==p1) { 5081495Sbill decref(p->ref); 5091495Sbill p->ref = p1->ref; 5101495Sbill p->labno = p1->labno; 5111495Sbill #ifdef COPYCODE 5121495Sbill if (p->labno == 0) 5131495Sbill p->code = p1->code; 5141495Sbill #endif 5151495Sbill p1->forw->back = p; 5161495Sbill p->forw = p1->forw; 5171495Sbill p->subop = revbr[p->subop]; 5181495Sbill p->pop=0; 5191495Sbill nchange++; 5201495Sbill nskip++; 5211495Sbill } 5221495Sbill } 5231495Sbill if (p->op==JBR || p->op==JMP) { 5241495Sbill while (p->forw && p->forw->op!=LABEL && p->forw->op!=DLABEL 5251495Sbill && p->forw->op!=EROU && p->forw->op!=END 5261495Sbill && p->forw->op!=ALIGN 5271495Sbill && p->forw->op!=0 && p->forw->op!=DATA) { 5281495Sbill nchange++; 5291495Sbill iaftbr++; 5301495Sbill if (p->forw->ref) 5311495Sbill decref(p->forw->ref); 5321495Sbill p->forw = p->forw->forw; 5331495Sbill p->forw->back = p; 5341495Sbill } 5351495Sbill rp = p->forw; 5361495Sbill while (rp && rp->op==LABEL) { 5371495Sbill if (p->ref == rp) { 5381495Sbill p->back->forw = p->forw; 5391495Sbill p->forw->back = p->back; 5401495Sbill p = p->back; 5411495Sbill decref(rp); 5421495Sbill nchange++; 5431495Sbill njp1++; 5441495Sbill break; 5451495Sbill } 5461495Sbill rp = rp->forw; 5471495Sbill } 5481495Sbill xjump(p); 5491495Sbill p = codemove(p); 5501495Sbill } 5511495Sbill } 5521495Sbill } 5531495Sbill 5541495Sbill xjump(p1) 5551495Sbill register struct node *p1; 5561495Sbill { 5571495Sbill register struct node *p2, *p3; 5581495Sbill int nxj; 5591495Sbill 5601495Sbill nxj = 0; 5611495Sbill if ((p2 = p1->ref)==0) 5621495Sbill return(0); 5631495Sbill for (;;) { 5641495Sbill while ((p1 = p1->back) && p1->op==LABEL); 5651495Sbill while ((p2 = p2->back) && p2->op==LABEL); 5661495Sbill if (!equop(p1, p2) || p1==p2) 5671495Sbill return(nxj); 5681495Sbill p3 = insertl(p2); 5691495Sbill p1->combop = JBR; 5701495Sbill p1->pop=0; 5711495Sbill p1->ref = p3; 5721495Sbill p1->labno = p3->labno; 5731495Sbill p1->code = 0; 5741495Sbill nxj++; 5751495Sbill nxjump++; 5761495Sbill nchange++; 5771495Sbill } 5781495Sbill } 5791495Sbill 5801495Sbill struct node * 5811495Sbill insertl(op) 5821495Sbill register struct node *op; 5831495Sbill { 5841495Sbill register struct node *lp; 5851495Sbill 5861495Sbill if (op->op == LABEL) { 5871495Sbill op->refc++; 5881495Sbill return(op); 5891495Sbill } 5901495Sbill if (op->back->op == LABEL) { 5911495Sbill op = op->back; 5921495Sbill op->refc++; 5931495Sbill return(op); 5941495Sbill } 5951495Sbill lp = alloc(sizeof first); 5961495Sbill lp->combop = LABEL; 5971495Sbill lp->labno = isn++; 5981495Sbill lp->ref = 0; 5991495Sbill lp->code = 0; 6001495Sbill lp->refc = 1; 6011495Sbill lp->back = op->back; 6021495Sbill lp->forw = op; 6031495Sbill op->back->forw = lp; 6041495Sbill op->back = lp; 6051495Sbill return(lp); 6061495Sbill } 6071495Sbill 6081495Sbill struct node * 6091495Sbill codemove(ap) 6101495Sbill struct node *ap; 6111495Sbill { 6121495Sbill register struct node *p1, *p2, *p3; 6131495Sbill struct node *t, *tl; 6141495Sbill int n; 6151495Sbill 6161495Sbill p1 = ap; 6171495Sbill /* last clause to avoid infinite loop on partial compiler droppings: 6181495Sbill L183: jbr L179 6191495Sbill L191: jbr L179 6201495Sbill casel r0,$0,$1 6211495Sbill L193: .word L183-L193 6221495Sbill .word L191-L193 6231495Sbill L179: ret 6241495Sbill */ 6251495Sbill if (p1->op!=JBR || (p2 = p1->ref)==0 || p2==p1->forw) 6261495Sbill return(p1); 6271495Sbill while (p2->op == LABEL) 6281495Sbill if ((p2 = p2->back) == 0) 6291495Sbill return(p1); 6301495Sbill if (p2->op!=JBR && p2->op!=JMP) 6311495Sbill goto ivloop; 6321495Sbill p2 = p2->forw; 6331495Sbill p3 = p1->ref; 6341495Sbill while (p3) { 6351495Sbill if (p3->op==JBR || p3->op==JMP) { 6361495Sbill if (p1==p3) 6371495Sbill return(p1); 6381495Sbill ncmot++; 6391495Sbill nchange++; 6401495Sbill p1->back->forw = p2; 6411495Sbill p1->forw->back = p3; 6421495Sbill p2->back->forw = p3->forw; 6431495Sbill p3->forw->back = p2->back; 6441495Sbill p2->back = p1->back; 6451495Sbill p3->forw = p1->forw; 6461495Sbill decref(p1->ref); 6471495Sbill return(p2); 6481495Sbill } else 6491495Sbill p3 = p3->forw; 6501495Sbill } 6511495Sbill return(p1); 6521495Sbill ivloop: 6531495Sbill if (p1->forw->op!=LABEL) 6541495Sbill return(p1); 6551495Sbill p3 = p2 = p2->forw; 6561495Sbill n = 16; 6571495Sbill do { 6581495Sbill if ((p3 = p3->forw) == 0 || p3==p1 || --n==0) 6591495Sbill return(p1); 6601495Sbill } while (p3->op!=CBR || p3->labno!=p1->forw->labno); 6611495Sbill do 6621495Sbill if ((p1 = p1->back) == 0) 6631495Sbill return(ap); 6641495Sbill while (p1!=p3); 6651495Sbill p1 = ap; 6661495Sbill tl = insertl(p1); 6671495Sbill p3->subop = revbr[p3->subop]; 6681495Sbill p3->pop=0; 6691495Sbill decref(p3->ref); 6701495Sbill p2->back->forw = p1; 6711495Sbill p3->forw->back = p1; 6721495Sbill p1->back->forw = p2; 6731495Sbill p1->forw->back = p3; 6741495Sbill t = p1->back; 6751495Sbill p1->back = p2->back; 6761495Sbill p2->back = t; 6771495Sbill t = p1->forw; 6781495Sbill p1->forw = p3->forw; 6791495Sbill p3->forw = t; 6801495Sbill p2 = insertl(p1->forw); 6811495Sbill p3->labno = p2->labno; 6821495Sbill #ifdef COPYCODE 6831495Sbill if (p3->labno == 0) 6841495Sbill p3->code = p2->code; 6851495Sbill #endif 6861495Sbill p3->ref = p2; 6871495Sbill decref(tl); 6881495Sbill if (tl->refc<=0) 6891495Sbill nrlab--; 6901495Sbill loopiv++; 6911495Sbill nchange++; 6921495Sbill return(p3); 6931495Sbill } 6941495Sbill 6951495Sbill comjump() 6961495Sbill { 6971495Sbill register struct node *p1, *p2, *p3; 6981495Sbill 6991495Sbill for (p1 = first.forw; p1!=0; p1 = p1->forw) 7001495Sbill if (p1->op==JBR && ((p2 = p1->ref) && p2->refc > 1 7011495Sbill || p1->subop==RET || p1->subop==RSB)) 7021495Sbill for (p3 = p1->forw; p3!=0; p3 = p3->forw) 7031495Sbill if (p3->op==JBR && p3->ref == p2) 7041495Sbill backjmp(p1, p3); 7051495Sbill } 7061495Sbill 7071495Sbill backjmp(ap1, ap2) 7081495Sbill struct node *ap1, *ap2; 7091495Sbill { 7101495Sbill register struct node *p1, *p2, *p3; 7111495Sbill 7121495Sbill p1 = ap1; 7131495Sbill p2 = ap2; 7141495Sbill for(;;) { 7151495Sbill while ((p1 = p1->back) && p1->op==LABEL); 7161495Sbill p2 = p2->back; 7171495Sbill if (equop(p1, p2)) { 7181495Sbill p3 = insertl(p1); 7191495Sbill p2->back->forw = p2->forw; 7201495Sbill p2->forw->back = p2->back; 7211495Sbill p2 = p2->forw; 7221495Sbill decref(p2->ref); 7231495Sbill p2->combop = JBR; /* to handle RET */ 7241495Sbill p2->pop=0; 7251495Sbill p2->labno = p3->labno; 7261495Sbill #ifdef COPYCODE 7271495Sbill p2->code = 0; 7281495Sbill #endif 7291495Sbill p2->ref = p3; 7301495Sbill nchange++; 7311495Sbill ncomj++; 7321495Sbill } else 7331495Sbill return; 7341495Sbill } 7351495Sbill } 736