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