126440Ssam #ifndef lint 2*29670Ssam static char sccsid[] = "@(#)c20.c 1.2 (Berkeley) 07/27/86"; 326440Ssam #endif 426440Ssam 526440Ssam /* 626440Ssam * C object code improver 726440Ssam */ 826440Ssam 926440Ssam #include "c2.h" 1026440Ssam #include <stdio.h> 1126440Ssam #include <ctype.h> 1226440Ssam 1326440Ssam char _sibuf[BUFSIZ], _sobuf[BUFSIZ]; 1426440Ssam int ioflag; 1526440Ssam int isn = 2000000; 1626440Ssam struct optab *oplook(); 1726440Ssam struct optab *getline(); 1826440Ssam long lgensym[10] = 1926440Ssam {100000L,200000L,300000L,400000L,500000L,600000L,700000L,800000L,900000L,1000000L}; 2026440Ssam 2126440Ssam /* VARARGS1 */ 2226440Ssam error(s1, s2) 2326440Ssam char *s1, *s2; 2426440Ssam { 2526440Ssam fprintf(stderr, s1, s2); 2626440Ssam exit(1); 2726440Ssam } 2826440Ssam 2926440Ssam struct node * 3026440Ssam alloc(an) 3126440Ssam { 3226440Ssam register int n; 3326440Ssam register char *p; 3426440Ssam 3526440Ssam n = an; 3626440Ssam n+=sizeof(char *)-1; 3726440Ssam n &= ~(sizeof(char *)-1); 3826440Ssam if (lasta+n >= lastr) { 3926440Ssam if (sbrk(2000) == -1) 4026440Ssam error("Optimizer: out of space\n"); 4126440Ssam lastr += 2000; 4226440Ssam } 4326440Ssam p = lasta; 4426440Ssam lasta += n; 4526440Ssam return((struct node *)p); 4626440Ssam } 4726440Ssam 4826440Ssam main(argc, argv) 4926440Ssam char **argv; 5026440Ssam { 5126440Ssam register int niter, maxiter, isend; 5226440Ssam int nflag,infound; 5326440Ssam 5426440Ssam nflag = 0; infound=0; argc--; argv++; 5526440Ssam while (argc>0) {/* get flags */ 5626440Ssam if (**argv=='-') { 5726440Ssam switch ((*argv)[1]) { 58*29670Ssam case 'a': aobflag++; break; 5926440Ssam case 'n': nflag++; break; 6026440Ssam case 'd': debug++; break; 6126440Ssam case 'f': fortflg++; break; 6226440Ssam } 6326440Ssam } else if (infound==0) { 6426440Ssam if (freopen(*argv, "r", stdin) ==NULL) 6526440Ssam error("C2: can't find %s\n", *argv); 6626440Ssam setbuf(stdin,_sibuf); ++infound; 6726440Ssam } else if (freopen(*argv, "w", stdout) ==NULL) 6826440Ssam error("C2: can't create %s\n", *argv); 6926440Ssam setbuf(stdout,_sobuf); 7026440Ssam argc--; argv++; 7126440Ssam } 7226440Ssam lasta = lastr = (char *)sbrk(2); 7326440Ssam opsetup(); 7426440Ssam lasta = firstr = lastr = (char *)alloc(0); 7526440Ssam maxiter = 0; 7626440Ssam do { 7726440Ssam isend = input(); 7826440Ssam niter = 0; 7926440Ssam bmove(); 8026440Ssam do { 8126440Ssam refcount(); 8226440Ssam do { 8326440Ssam iterate(); 8426440Ssam clearreg(); 8526440Ssam niter++; 8626440Ssam } while (nchange); 8726440Ssam comjump(); 8826440Ssam rmove(); 8926440Ssam } while (nchange || jumpsw()); 9026440Ssam addaob(); 91*29670Ssam interleave(); 9226440Ssam output(); 9326440Ssam if (niter > maxiter) 9426440Ssam maxiter = niter; 9526440Ssam lasta = firstr; 9626440Ssam } while (isend); 9726440Ssam if (nflag) { 9826440Ssam score("iterations", maxiter); 9926440Ssam score("jumps to jumps", nbrbr); 10026440Ssam score("inst. after jumps", iaftbr); 10126440Ssam score("jumps to .+1", njp1); 10226440Ssam score("redundant labels", nrlab); 10326440Ssam score("cross-jumps", nxjump); 10426440Ssam score("code motions", ncmot); 10526440Ssam score("branches reversed", nrevbr); 10626440Ssam score("redundant moves", redunm); 10726440Ssam score("simplified addresses", nsaddr); 10826440Ssam score("loops inverted", loopiv); 10926440Ssam score("redundant jumps", nredunj); 11026440Ssam score("common seqs before jmp's", ncomj); 11126440Ssam score("skips over jumps", nskip); 11226440Ssam score("aob's added", naob); 11326440Ssam score("redundant tst's", nrtst); 11426440Ssam score("jump on bit", nbj); 11526440Ssam score("redundant accumulator stores", nst); 11626440Ssam score("redundant accumulator loads", nld); 11726440Ssam score("K core", ((unsigned)lastr+01777) >> 10); 11826440Ssam } 11926440Ssam putc('\n',stdout); 12026440Ssam fflush(stdout); exit(0); 12126440Ssam } 12226440Ssam 12326440Ssam score(s, n) 12426440Ssam char *s; 12526440Ssam { 12626440Ssam if(n > 0) 12726440Ssam fprintf(stderr, "%d %s\n", n, s); 12826440Ssam } 12926440Ssam 13026440Ssam input() 13126440Ssam { 13226440Ssam register struct node *p, *lastp; 13326440Ssam register struct optab *op; register char *cp1; 13426440Ssam static struct optab F77JSW = {".long", JSW, 1}; 13526440Ssam 13626440Ssam lastp = &first; 13726440Ssam for (;;) { 13826440Ssam top: 13926440Ssam op = getline(); 14026440Ssam if (debug && op==0) fprintf(stderr,"? %s\n",line); 14126440Ssam switch (op->opcod) { 14226440Ssam 14326440Ssam case LABEL: 14426440Ssam p = alloc(sizeof first); 14526440Ssam if (isdigit(line[0]) && (p->labno=locdef(line)) || 14626440Ssam (line[0] == 'L') && (p->labno=getnum(line+1))) { 14726440Ssam p->op = LABEL; p->subop = 0; 14826440Ssam if (p->labno<100000L && isn<=p->labno) isn=1+p->labno; 14926440Ssam p->code = 0; 15026440Ssam } else { 15126440Ssam p->op = DLABEL; p->subop = 0; 15226440Ssam p->labno = 0; 15326440Ssam p->code = copy(line); 15426440Ssam } 15526440Ssam break; 15626440Ssam 15726440Ssam case LGEN: 15826440Ssam if (*curlp!='L' && !locuse(curlp)) goto std; 15926440Ssam op= &F77JSW; 16026440Ssam case JBR: 16126440Ssam if (op->opcod==JBR && (op->subopcod&0xF)==RET) goto std; 16226440Ssam case CBR: 16326440Ssam case JMP: 16426440Ssam case JSW: 16526440Ssam case AOBLEQ: case AOBLSS: 16626440Ssam p = alloc(sizeof first); 16726440Ssam p->op = op->opcod; p->subop = op->subopcod; 16826440Ssam p->code=0; cp1=curlp; 16926440Ssam if ((!isdigit(*cp1) || 0==(p->labno=locuse(cp1))) && 17026440Ssam (*cp1!='L' || 0==(p->labno = getnum(cp1+1)))) {/* jbs, etc.? */ 17126440Ssam while (*cp1++); while (*--cp1!=',' && cp1!=curlp); 17226440Ssam if (cp1==curlp || 17326440Ssam (!isdigit(*++cp1) || 0==(p->labno=locuse(cp1))) && 17426440Ssam (*cp1!='L' || 0==(p->labno=getnum(cp1+1)))) 17526440Ssam p->labno = 0; 17626440Ssam else *--cp1=0; 17726440Ssam p->code = copy(curlp); 17826440Ssam } 17926440Ssam if (isn<=p->labno) isn=1+p->labno; 18026440Ssam break; 18126440Ssam 18226440Ssam case MOVA: 18326440Ssam p=alloc(sizeof first); 18426440Ssam p->op = op->opcod; p->subop = op->subopcod; 18526440Ssam p->code=0; cp1=curlp+1; 18626440Ssam if (cp1[-1]=='L' || isdigit(cp1[-1])) { 18726440Ssam while (*cp1++!=','); *--cp1=0; 18826440Ssam if (0!=(p->labno=locuse(curlp)) || 18926440Ssam 0!=(p->labno=getnum(curlp+1))) p->code=copy(cp1+1); 19026440Ssam else {*cp1=','; p->code=copy(curlp);} 19126440Ssam } else {p->code=copy(--cp1); p->labno=0;} 19226440Ssam break; 19326440Ssam 19426440Ssam case MOV: 19526440Ssam p=alloc(sizeof first); 19626440Ssam p->op = op->opcod; p->subop = op->subopcod; 19726440Ssam p->code = copy(curlp); 19826440Ssam p->labno = 0; 19926440Ssam cp1=curlp+1; 20026440Ssam if ((cp1[-1]=='$') && (cp1[0] == 'L')) { 20126440Ssam while (*cp1++!=','); *--cp1 =0; 20226440Ssam p->labno = getnum(curlp+2); 20326440Ssam } 20426440Ssam break; 20526440Ssam case MOVBLK: /* used implicitly */ 20626440Ssam curlp = "(r0),(r1),(r2)"; 20726440Ssam goto std; 20826440Ssam 20926440Ssam case SET: 21026440Ssam case COMM: 21126440Ssam case LCOMM: 21226440Ssam printf("%s\n",line); goto top; 21326440Ssam 21426440Ssam case BSS: 21526440Ssam case DATA: 21626440Ssam for (;;) { 21726440Ssam printf("%s%c",line,(op->opcod==LABEL ? ':' : '\n')); 21826440Ssam if (op->opcod==TEXT) goto top; 21926440Ssam if (END==(op=getline())->opcod) {/* dangling .data is bad for you */ 22026440Ssam printf(".text\n"); 22126440Ssam break; 22226440Ssam } 22326440Ssam } 22426440Ssam 22526440Ssam std: 22626440Ssam default: 22726440Ssam p = alloc(sizeof first); 22826440Ssam p->op = op->opcod; p->subop = op->subopcod; 22926440Ssam p->labno = 0; 23026440Ssam p->code = copy(curlp); 23126440Ssam break; 23226440Ssam 23326440Ssam } 23426440Ssam p->forw = 0; 23526440Ssam p->back = lastp; 23626440Ssam p->pop = op; 23726440Ssam lastp->forw = p; 23826440Ssam lastp = p; 23926440Ssam p->ref = 0; 24026440Ssam if (p->op==CASE) { 24126440Ssam char *lp; int ncase; 24226440Ssam lp=curlp; while (*lp++); while (*--lp!='$'); ncase=getnum(lp+1); 24326440Ssam if (ALIGN!=(getline())->opcod || LABEL!=(getline())->opcod) caserr(); 24426440Ssam do { 24526440Ssam if (WGEN!=(getline())->opcod) caserr(); 24626440Ssam p = alloc(sizeof first); 24726440Ssam p->op = JSW; p->subop = 0; 24826440Ssam p->code = 0; 24926440Ssam lp=curlp; while(*lp++!='-'); *--lp=0; p->labno=getnum(curlp+1); 25026440Ssam if (isn<=p->labno) isn=1+p->labno; 25126440Ssam p->forw = 0; p->back = lastp; lastp->forw = p; lastp = p; 25226440Ssam p->ref = 0; p->pop=0; 25326440Ssam } while (--ncase>=0); 25426440Ssam } 25526440Ssam if (op->opcod==EROU) 25626440Ssam return(1); 25726440Ssam if (op->opcod==END) 25826440Ssam return(0); 25926440Ssam } 26026440Ssam } 26126440Ssam 26226440Ssam caserr() 26326440Ssam { 26426440Ssam error("C2: improper casel instruction\n"); 26526440Ssam } 26626440Ssam 26726440Ssam struct optab * 26826440Ssam getline() 26926440Ssam { 27026440Ssam register char *lp; 27126440Ssam register int c; 27226440Ssam static struct optab OPLABEL={"",LABEL,0}; 27326440Ssam static struct optab OPEND={"",END,0}; 27426440Ssam 27526440Ssam lp = line; 27626440Ssam again: 27726440Ssam while (EOF!=(c=getchar()) && isspace(c)); 27826440Ssam if (c=='#') { 27926440Ssam while((c=getchar()) != '\n'); 28026440Ssam goto again; 28126440Ssam } 28226440Ssam while (EOF!=c) { 28326440Ssam if (c==':') { 28426440Ssam *lp++ = 0; 28526440Ssam return(&OPLABEL); 28626440Ssam } 28726440Ssam if (c=='\n') { 28826440Ssam *lp++ = 0; 28926440Ssam return(oplook()); 29026440Ssam } 29126440Ssam if (c=='"') 29226440Ssam do { 29326440Ssam if (c=='\\') { 29426440Ssam *lp++ = c; 29526440Ssam c = getchar(); 29626440Ssam } 29726440Ssam *lp++ = c; 29826440Ssam c = getchar(); 29926440Ssam } while(c!='"'); 30026440Ssam *lp++ = c; 30126440Ssam c = getchar(); 30226440Ssam } 30326440Ssam *lp++ = 0; 30426440Ssam return(&OPEND); 30526440Ssam } 30626440Ssam 30726440Ssam long 30826440Ssam getnum(p) 30926440Ssam register char *p; 31026440Ssam { 31126440Ssam register int c, neg, n; 31226440Ssam 31326440Ssam n = 0; neg=0; if (*p=='-') {++neg; ++p;} 31426440Ssam while (isdigit(c = *p++)) { 31526440Ssam c -= '0'; n *= 10; if (neg) n -= c; else n += c; 31626440Ssam } 31726440Ssam if (*--p != 0) 31826440Ssam return(0); 31926440Ssam return(n); 32026440Ssam } 32126440Ssam 32226440Ssam locuse(p) 32326440Ssam register char *p; 32426440Ssam { 32526440Ssam 32626440Ssam if (!isdigit(p[0]) || p[1] != 'f' && p[1] != 'b' || p[2]) return(0); 32726440Ssam return (lgensym[p[0] - '0'] - (p[1] == 'b')); 32826440Ssam } 32926440Ssam 33026440Ssam locdef(p) 33126440Ssam register char *p; 33226440Ssam { 33326440Ssam 33426440Ssam if (!isdigit(p[0]) || p[1]) return(0); 33526440Ssam return (lgensym[p[0] - '0']++); 33626440Ssam } 33726440Ssam 33826440Ssam output() 33926440Ssam { 34026440Ssam register struct node *t; 34126440Ssam int casebas; 34226440Ssam 34326440Ssam t = &first; 34426440Ssam while (t = t->forw) switch (t->op) { 34526440Ssam 34626440Ssam case END: 34726440Ssam fflush(stdout); 34826440Ssam return; 34926440Ssam 35026440Ssam case LABEL: 35126440Ssam printf("L%d:", t->labno); 35226440Ssam continue; 35326440Ssam 35426440Ssam case DLABEL: 35526440Ssam printf("%s:", t->code); 35626440Ssam continue; 35726440Ssam 35826440Ssam case CASE: 35926440Ssam casebas=0; 36026440Ssam 36126440Ssam default: std: 36226440Ssam if (t->pop==0) {/* must find it */ 36326440Ssam register struct optab *p; 36426440Ssam for (p=optab; p->opstring[0]; ++p) 36526440Ssam if (p->opcod==t->op && p->subopcod==t->subop) { 36626440Ssam t->pop=p; break;} 36726440Ssam } 36826440Ssam printf("%s", t->pop->opstring); 36926440Ssam if (t->code) printf("\t%s", t->code); 37026440Ssam if (t->op != MOV ) { 37126440Ssam if (t->labno!=0) printf("%cL%d\n", 37226440Ssam (t->code ? ',' : '\t'), 37326440Ssam t->labno); 37426440Ssam 37526440Ssam else printf("\n"); 37626440Ssam } 37726440Ssam else printf("\n"); 37826440Ssam continue; 37926440Ssam 38026440Ssam case MOVA: 38126440Ssam if (t->labno==0) goto std; 38226440Ssam printf("mova%c\tL%d,%s\n","bwlq"[t->subop-BYTE],t->labno,t->code); 38326440Ssam continue; 38426440Ssam 38526440Ssam case MOVBLK: 38626440Ssam t->code = 0; 38726440Ssam goto std; 38826440Ssam 38926440Ssam case JSW: 39026440Ssam if (t->subop!=0) {/* F77JSW */ 39126440Ssam printf(".long\tL%d\n",t->labno); continue; 39226440Ssam } 39326440Ssam if (casebas==0) printf(".align 1\nL%d:\n",casebas=isn++); 39426440Ssam printf(".word L%d-L%d\n", t->labno, casebas); 39526440Ssam continue; 39626440Ssam 39726440Ssam } 39826440Ssam } 39926440Ssam 40026440Ssam char * 40126440Ssam copy(ap) 40226440Ssam char *ap; 40326440Ssam { 40426440Ssam register char *p, *np, *onp; 40526440Ssam register int n; 40626440Ssam 40726440Ssam p = ap; 40826440Ssam n = 0; 40926440Ssam if (*p==0) 41026440Ssam return(0); 41126440Ssam do 41226440Ssam n++; 41326440Ssam while (*p++); 41426440Ssam onp = np = (char *)alloc(n); 41526440Ssam p = ap; 41626440Ssam while (*np++ = *p++); 41726440Ssam return(onp); 41826440Ssam } 41926440Ssam 42026440Ssam #define OPHS 560 42126440Ssam struct optab *ophash[OPHS]; 42226440Ssam 42326440Ssam opsetup() 42426440Ssam { 42526440Ssam register struct optab *optp, **ophp; 42626440Ssam register int i,t; 42726440Ssam 42826440Ssam for(i=RT1+5;--i>=0;) regs[i]=(char *)alloc(C2_ASIZE); 42926440Ssam for (optp = optab; optp->opstring[0]; optp++) { 43026440Ssam t=7; i=0; while (--t>=0) i+= i+optp->opstring[t]; 43126440Ssam ophp = &ophash[i % OPHS]; 43226440Ssam while (*ophp++) { 43326440Ssam /* fprintf(stderr,"\ncollision: %d %s %s", 43426440Ssam /* ophp-1-ophash,optp->opstring,(*(ophp-1))->opstring); 43526440Ssam */ 43626440Ssam if (ophp > &ophash[OPHS]) 43726440Ssam ophp = ophash; 43826440Ssam } 43926440Ssam *--ophp = optp; 44026440Ssam } 44126440Ssam } 44226440Ssam 44326440Ssam struct optab * 44426440Ssam oplook() 44526440Ssam { 44626440Ssam register struct optab *optp,**ophp; 44726440Ssam register char *p,*p2; 44826440Ssam register int t; 44926440Ssam char tempop[20]; 45026440Ssam static struct optab OPNULL={"",0,0}; 45126440Ssam 45226440Ssam for (p=line, p2=tempop; *p && !isspace(*p); *p2++= *p++); *p2=0; p2=p; 45326440Ssam while (isspace(*p2)) ++p2; curlp=p2; 45426440Ssam t=0; while(--p>=line) t += t+*p; ophp = &ophash[t % OPHS]; 45526440Ssam while (optp = *ophp) { 45626440Ssam if (equstr(tempop,optp->opstring)) return(optp); 45726440Ssam if ((++ophp) >= &ophash[OPHS]) ophp = ophash; 45826440Ssam } 45926440Ssam curlp = line; 46026440Ssam return(&OPNULL); 46126440Ssam } 46226440Ssam 46326440Ssam refcount() 46426440Ssam { 46526440Ssam register struct node *p, *lp, *np; 46626440Ssam struct node *labhash[LABHS]; 46726440Ssam register struct node **hp; 46826440Ssam 46926440Ssam for (hp = labhash; hp < &labhash[LABHS];) 47026440Ssam *hp++ = 0; 47126440Ssam for (p = first.forw; p!=0; p = p->forw) 47226440Ssam if (p->op==LABEL) { 47326440Ssam labhash[p->labno % LABHS] = p; 47426440Ssam p->refc = 0; 47526440Ssam } 47626440Ssam for (p = first.forw; p!=0; p = p->forw) { 47726440Ssam if (p->op==JBR && p->subop==0 || p->op==CBR || p->op==JSW || p->op==JMP 47826440Ssam || p->op==AOBLEQ || p->op==AOBLSS 47926440Ssam || (p->op==MOVA && p->labno!=0) 48026440Ssam || (p->op==MOV && p->labno!=0)){ 48126440Ssam p->ref = 0; 48226440Ssam lp = labhash[p->labno % LABHS]; 48326440Ssam if (lp==0 || p->labno!=lp->labno) 48426440Ssam for (lp = first.forw; lp!=0; lp = lp->forw) { 48526440Ssam if (lp->op==LABEL && p->labno==lp->labno) 48626440Ssam break; 48726440Ssam } 48826440Ssam if (lp) { 48926440Ssam np = nonlab(lp)->back; 49026440Ssam if (np!=lp) { 49126440Ssam p->labno = np->labno; 49226440Ssam lp = np; 49326440Ssam } 49426440Ssam p->ref = lp; 49526440Ssam lp->refc++; 49626440Ssam } 49726440Ssam } 49826440Ssam } 49926440Ssam for (p = first.forw; p!=0; p = p->forw) 50026440Ssam if (p->op==LABEL && p->refc==0 50126440Ssam && (lp = nonlab(p))->op && lp->op!=JSW) 50226440Ssam decref(p); 50326440Ssam } 50426440Ssam 50526440Ssam iterate() 50626440Ssam { 50726440Ssam register struct node *p, *rp, *p1; 50826440Ssam 50926440Ssam nchange = 0; 51026440Ssam for (p = first.forw; p!=0; p = p->forw) { 51126440Ssam if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) { 51226440Ssam rp = nonlab(p->ref); 51326440Ssam if (rp->op==JBR && rp->labno && p->labno!=rp->labno) { 51426440Ssam nbrbr++; 51526440Ssam p->labno = rp->labno; 51626440Ssam decref(p->ref); 51726440Ssam rp->ref->refc++; 51826440Ssam p->ref = rp->ref; 51926440Ssam nchange++; 52026440Ssam } 52126440Ssam } 52226440Ssam if (p->op==CBR && (p1 = p->forw)->op==JBR && p1->subop==0 52326440Ssam #ifdef COPYCODE 52426440Ssam && p->ref 52526440Ssam #endif 52626440Ssam ) {/* RET problems */ 52726440Ssam rp = p->ref; 52826440Ssam do 52926440Ssam rp = rp->back; 53026440Ssam while (rp->op==LABEL); 53126440Ssam if (rp==p1) { 53226440Ssam decref(p->ref); 53326440Ssam p->ref = p1->ref; 53426440Ssam p->labno = p1->labno; 53526440Ssam #ifdef COPYCODE 53626440Ssam if (p->labno == 0) 53726440Ssam p->code = p1->code; 53826440Ssam #endif 53926440Ssam p1->forw->back = p; 54026440Ssam p->forw = p1->forw; 54126440Ssam p->subop = revbr[p->subop]; 54226440Ssam p->pop=0; 54326440Ssam nchange++; 54426440Ssam nskip++; 54526440Ssam } 54626440Ssam } 54726440Ssam if (p->op==JBR || p->op==JMP) { 54826440Ssam while ((p1=p->forw)!=0 && p1->op!=LABEL && p1->op!=DLABEL 54926440Ssam && p1->op!=EROU && p1->op!=END 55026440Ssam && p1->op!=ALIGN 55126440Ssam && p1->op!=0 && p1->op!=DATA) { 55226440Ssam nchange++; 55326440Ssam iaftbr++; 55426440Ssam if (p1->ref) 55526440Ssam decref(p1->ref); 55626440Ssam p->forw = p1->forw; 55726440Ssam p->forw->back = p; 55826440Ssam } 55926440Ssam rp = p->forw; 56026440Ssam while (rp && rp->op==LABEL) { 56126440Ssam if (p->ref == rp) { 56226440Ssam p->back->forw = p->forw; 56326440Ssam p->forw->back = p->back; 56426440Ssam p = p->back; 56526440Ssam decref(rp); 56626440Ssam nchange++; 56726440Ssam njp1++; 56826440Ssam break; 56926440Ssam } 57026440Ssam rp = rp->forw; 57126440Ssam } 57226440Ssam xjump(p); 57326440Ssam p = codemove(p); 57426440Ssam } 57526440Ssam } 57626440Ssam } 57726440Ssam 57826440Ssam xjump(p1) 57926440Ssam register struct node *p1; 58026440Ssam { 58126440Ssam register struct node *p2, *p3; 58226440Ssam 58326440Ssam if ((p2 = p1->ref)==0) 58426440Ssam return; 58526440Ssam for (;;) { 58626440Ssam while ((p1 = p1->back) && p1->op==LABEL); 58726440Ssam while ((p2 = p2->back) && p2->op==LABEL); 58826440Ssam if (!equop(p1, p2) || p1==p2) 58926440Ssam return; 59026440Ssam p3 = insertl(p2); 59126440Ssam p1->op = JBR; p1->subop = 0; 59226440Ssam p1->pop=0; 59326440Ssam p1->ref = p3; 59426440Ssam p1->labno = p3->labno; 59526440Ssam p1->code = 0; 59626440Ssam nxjump++; 59726440Ssam nchange++; 59826440Ssam } 59926440Ssam } 60026440Ssam 60126440Ssam struct node * 60226440Ssam insertl(op) 60326440Ssam register struct node *op; 60426440Ssam { 60526440Ssam register struct node *lp; 60626440Ssam 60726440Ssam if (op->op == LABEL) { 60826440Ssam op->refc++; 60926440Ssam return(op); 61026440Ssam } 61126440Ssam if (op->back->op == LABEL) { 61226440Ssam op = op->back; 61326440Ssam op->refc++; 61426440Ssam return(op); 61526440Ssam } 61626440Ssam lp = alloc(sizeof first); 61726440Ssam lp->op = LABEL; lp->subop = 0; 61826440Ssam lp->labno = isn++; 61926440Ssam lp->ref = 0; 62026440Ssam lp->code = 0; 62126440Ssam lp->refc = 1; 62226440Ssam lp->back = op->back; 62326440Ssam lp->forw = op; 62426440Ssam op->back->forw = lp; 62526440Ssam op->back = lp; 62626440Ssam return(lp); 62726440Ssam } 62826440Ssam 62926440Ssam struct node * 63026440Ssam codemove(ap) 63126440Ssam struct node *ap; 63226440Ssam { 63326440Ssam register struct node *p1, *p2, *p3; 63426440Ssam register struct node *t, *tl; 63526440Ssam register int n; 63626440Ssam 63726440Ssam p1 = ap; 63826440Ssam if (p1->op!=JBR || (p2 = p1->ref)==0 || p2==p1->forw) 63926440Ssam return(p1); 64026440Ssam while (p2->op == LABEL) 64126440Ssam if ((p2 = p2->back) == 0) 64226440Ssam return(p1); 64326440Ssam if (p2->op!=JBR && p2->op!=JMP) 64426440Ssam goto ivloop; 64526440Ssam p2 = p2->forw; 64626440Ssam p3 = p1->ref; 64726440Ssam while (p3) { 64826440Ssam if (p3->op==JBR || p3->op==JMP) { 64926440Ssam if (p1==p3) 65026440Ssam return(p1); 65126440Ssam ncmot++; 65226440Ssam nchange++; 65326440Ssam p1->back->forw = p2; 65426440Ssam p1->forw->back = p3; 65526440Ssam p2->back->forw = p3->forw; 65626440Ssam p3->forw->back = p2->back; 65726440Ssam p2->back = p1->back; 65826440Ssam p3->forw = p1->forw; 65926440Ssam decref(p1->ref); 66026440Ssam return(p2); 66126440Ssam } else 66226440Ssam p3 = p3->forw; 66326440Ssam } 66426440Ssam return(p1); 66526440Ssam ivloop: 66626440Ssam if (p1->forw->op!=LABEL) 66726440Ssam return(p1); 66826440Ssam p3 = p2 = p2->forw; 66926440Ssam n = 16; 67026440Ssam do { 67126440Ssam if ((p3 = p3->forw) == 0 || p3==p1 || --n==0) 67226440Ssam return(p1); 67326440Ssam } while (p3->op!=CBR || p3->labno!=p1->forw->labno); 67426440Ssam do 67526440Ssam if ((p1 = p1->back) == 0) 67626440Ssam return(ap); 67726440Ssam while (p1!=p3); 67826440Ssam p1 = ap; 67926440Ssam tl = insertl(p1); 68026440Ssam p3->subop = revbr[p3->subop]; 68126440Ssam p3->pop=0; 68226440Ssam decref(p3->ref); 68326440Ssam p2->back->forw = p1; 68426440Ssam p3->forw->back = p1; 68526440Ssam p1->back->forw = p2; 68626440Ssam p1->forw->back = p3; 68726440Ssam t = p1->back; 68826440Ssam p1->back = p2->back; 68926440Ssam p2->back = t; 69026440Ssam t = p1->forw; 69126440Ssam p1->forw = p3->forw; 69226440Ssam p3->forw = t; 69326440Ssam p2 = insertl(p1->forw); 69426440Ssam p3->labno = p2->labno; 69526440Ssam #ifdef COPYCODE 69626440Ssam if (p3->labno == 0) 69726440Ssam p3->code = p2->code; 69826440Ssam #endif 69926440Ssam p3->ref = p2; 70026440Ssam decref(tl); 70126440Ssam if (tl->refc<=0) 70226440Ssam nrlab--; 70326440Ssam loopiv++; 70426440Ssam nchange++; 70526440Ssam return(p3); 70626440Ssam } 70726440Ssam 70826440Ssam comjump() 70926440Ssam { 71026440Ssam register struct node *p1, *p2, *p3; 71126440Ssam 71226440Ssam for (p1 = first.forw; p1!=0; p1 = p1->forw) 71326440Ssam if (p1->op==JBR && ((p2 = p1->ref) && p2->refc > 1 71426440Ssam || (p1->subop&0xF)==RET)) 71526440Ssam for (p3 = p1->forw; p3!=0; p3 = p3->forw) 71626440Ssam if (p3->op==JBR && p3->ref == p2) 71726440Ssam backjmp(p1, p3); 71826440Ssam } 71926440Ssam 72026440Ssam backjmp(ap1, ap2) 72126440Ssam struct node *ap1, *ap2; 72226440Ssam { 72326440Ssam register struct node *p1, *p2, *p3; 72426440Ssam 72526440Ssam p1 = ap1; 72626440Ssam p2 = ap2; 72726440Ssam for(;;) { 72826440Ssam while ((p1 = p1->back) && p1->op==LABEL); 72926440Ssam p2 = p2->back; 73026440Ssam if (equop(p1, p2)) { 73126440Ssam p3 = insertl(p1); 73226440Ssam p2->back->forw = p2->forw; 73326440Ssam p2->forw->back = p2->back; 73426440Ssam p2 = p2->forw; 73526440Ssam decref(p2->ref); 73626440Ssam p2->op = JBR; p2->subop = 0; /* to handle RET */ 73726440Ssam p2->pop=0; 73826440Ssam p2->labno = p3->labno; 73926440Ssam #ifdef COPYCODE 74026440Ssam p2->code = 0; 74126440Ssam #endif 74226440Ssam p2->ref = p3; 74326440Ssam nchange++; 74426440Ssam ncomj++; 74526440Ssam } else 74626440Ssam return; 74726440Ssam } 74826440Ssam } 749