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