1*26440Ssam #ifndef lint 2*26440Ssam static char sccsid[] = "@(#)c20.c 1.1 (Berkeley) 03/02/86"; 3*26440Ssam #endif 4*26440Ssam 5*26440Ssam /* 6*26440Ssam * C object code improver 7*26440Ssam */ 8*26440Ssam 9*26440Ssam #include "c2.h" 10*26440Ssam #include <stdio.h> 11*26440Ssam #include <ctype.h> 12*26440Ssam 13*26440Ssam char _sibuf[BUFSIZ], _sobuf[BUFSIZ]; 14*26440Ssam int ioflag; 15*26440Ssam int isn = 2000000; 16*26440Ssam struct optab *oplook(); 17*26440Ssam struct optab *getline(); 18*26440Ssam long lgensym[10] = 19*26440Ssam {100000L,200000L,300000L,400000L,500000L,600000L,700000L,800000L,900000L,1000000L}; 20*26440Ssam 21*26440Ssam /* VARARGS1 */ 22*26440Ssam error(s1, s2) 23*26440Ssam char *s1, *s2; 24*26440Ssam { 25*26440Ssam fprintf(stderr, s1, s2); 26*26440Ssam exit(1); 27*26440Ssam } 28*26440Ssam 29*26440Ssam struct node * 30*26440Ssam alloc(an) 31*26440Ssam { 32*26440Ssam register int n; 33*26440Ssam register char *p; 34*26440Ssam 35*26440Ssam n = an; 36*26440Ssam n+=sizeof(char *)-1; 37*26440Ssam n &= ~(sizeof(char *)-1); 38*26440Ssam if (lasta+n >= lastr) { 39*26440Ssam if (sbrk(2000) == -1) 40*26440Ssam error("Optimizer: out of space\n"); 41*26440Ssam lastr += 2000; 42*26440Ssam } 43*26440Ssam p = lasta; 44*26440Ssam lasta += n; 45*26440Ssam return((struct node *)p); 46*26440Ssam } 47*26440Ssam 48*26440Ssam main(argc, argv) 49*26440Ssam char **argv; 50*26440Ssam { 51*26440Ssam register int niter, maxiter, isend; 52*26440Ssam int nflag,infound; 53*26440Ssam 54*26440Ssam nflag = 0; infound=0; argc--; argv++; 55*26440Ssam while (argc>0) {/* get flags */ 56*26440Ssam if (**argv=='-') { 57*26440Ssam switch ((*argv)[1]) { 58*26440Ssam case 'n': nflag++; break; 59*26440Ssam case 'd': debug++; break; 60*26440Ssam case 'f': fortflg++; break; 61*26440Ssam } 62*26440Ssam } else if (infound==0) { 63*26440Ssam if (freopen(*argv, "r", stdin) ==NULL) 64*26440Ssam error("C2: can't find %s\n", *argv); 65*26440Ssam setbuf(stdin,_sibuf); ++infound; 66*26440Ssam } else if (freopen(*argv, "w", stdout) ==NULL) 67*26440Ssam error("C2: can't create %s\n", *argv); 68*26440Ssam setbuf(stdout,_sobuf); 69*26440Ssam argc--; argv++; 70*26440Ssam } 71*26440Ssam lasta = lastr = (char *)sbrk(2); 72*26440Ssam opsetup(); 73*26440Ssam lasta = firstr = lastr = (char *)alloc(0); 74*26440Ssam maxiter = 0; 75*26440Ssam do { 76*26440Ssam isend = input(); 77*26440Ssam niter = 0; 78*26440Ssam bmove(); 79*26440Ssam do { 80*26440Ssam refcount(); 81*26440Ssam do { 82*26440Ssam iterate(); 83*26440Ssam clearreg(); 84*26440Ssam niter++; 85*26440Ssam } while (nchange); 86*26440Ssam comjump(); 87*26440Ssam rmove(); 88*26440Ssam } while (nchange || jumpsw()); 89*26440Ssam addaob(); 90*26440Ssam output(); 91*26440Ssam if (niter > maxiter) 92*26440Ssam maxiter = niter; 93*26440Ssam lasta = firstr; 94*26440Ssam } while (isend); 95*26440Ssam if (nflag) { 96*26440Ssam score("iterations", maxiter); 97*26440Ssam score("jumps to jumps", nbrbr); 98*26440Ssam score("inst. after jumps", iaftbr); 99*26440Ssam score("jumps to .+1", njp1); 100*26440Ssam score("redundant labels", nrlab); 101*26440Ssam score("cross-jumps", nxjump); 102*26440Ssam score("code motions", ncmot); 103*26440Ssam score("branches reversed", nrevbr); 104*26440Ssam score("redundant moves", redunm); 105*26440Ssam score("simplified addresses", nsaddr); 106*26440Ssam score("loops inverted", loopiv); 107*26440Ssam score("redundant jumps", nredunj); 108*26440Ssam score("common seqs before jmp's", ncomj); 109*26440Ssam score("skips over jumps", nskip); 110*26440Ssam score("aob's added", naob); 111*26440Ssam score("redundant tst's", nrtst); 112*26440Ssam score("jump on bit", nbj); 113*26440Ssam score("redundant accumulator stores", nst); 114*26440Ssam score("redundant accumulator loads", nld); 115*26440Ssam score("K core", ((unsigned)lastr+01777) >> 10); 116*26440Ssam } 117*26440Ssam putc('\n',stdout); 118*26440Ssam fflush(stdout); exit(0); 119*26440Ssam } 120*26440Ssam 121*26440Ssam score(s, n) 122*26440Ssam char *s; 123*26440Ssam { 124*26440Ssam if(n > 0) 125*26440Ssam fprintf(stderr, "%d %s\n", n, s); 126*26440Ssam } 127*26440Ssam 128*26440Ssam input() 129*26440Ssam { 130*26440Ssam register struct node *p, *lastp; 131*26440Ssam register struct optab *op; register char *cp1; 132*26440Ssam static struct optab F77JSW = {".long", JSW, 1}; 133*26440Ssam 134*26440Ssam lastp = &first; 135*26440Ssam for (;;) { 136*26440Ssam top: 137*26440Ssam op = getline(); 138*26440Ssam if (debug && op==0) fprintf(stderr,"? %s\n",line); 139*26440Ssam switch (op->opcod) { 140*26440Ssam 141*26440Ssam case LABEL: 142*26440Ssam p = alloc(sizeof first); 143*26440Ssam if (isdigit(line[0]) && (p->labno=locdef(line)) || 144*26440Ssam (line[0] == 'L') && (p->labno=getnum(line+1))) { 145*26440Ssam p->op = LABEL; p->subop = 0; 146*26440Ssam if (p->labno<100000L && isn<=p->labno) isn=1+p->labno; 147*26440Ssam p->code = 0; 148*26440Ssam } else { 149*26440Ssam p->op = DLABEL; p->subop = 0; 150*26440Ssam p->labno = 0; 151*26440Ssam p->code = copy(line); 152*26440Ssam } 153*26440Ssam break; 154*26440Ssam 155*26440Ssam case LGEN: 156*26440Ssam if (*curlp!='L' && !locuse(curlp)) goto std; 157*26440Ssam op= &F77JSW; 158*26440Ssam case JBR: 159*26440Ssam if (op->opcod==JBR && (op->subopcod&0xF)==RET) goto std; 160*26440Ssam case CBR: 161*26440Ssam case JMP: 162*26440Ssam case JSW: 163*26440Ssam case AOBLEQ: case AOBLSS: 164*26440Ssam p = alloc(sizeof first); 165*26440Ssam p->op = op->opcod; p->subop = op->subopcod; 166*26440Ssam p->code=0; cp1=curlp; 167*26440Ssam if ((!isdigit(*cp1) || 0==(p->labno=locuse(cp1))) && 168*26440Ssam (*cp1!='L' || 0==(p->labno = getnum(cp1+1)))) {/* jbs, etc.? */ 169*26440Ssam while (*cp1++); while (*--cp1!=',' && cp1!=curlp); 170*26440Ssam if (cp1==curlp || 171*26440Ssam (!isdigit(*++cp1) || 0==(p->labno=locuse(cp1))) && 172*26440Ssam (*cp1!='L' || 0==(p->labno=getnum(cp1+1)))) 173*26440Ssam p->labno = 0; 174*26440Ssam else *--cp1=0; 175*26440Ssam p->code = copy(curlp); 176*26440Ssam } 177*26440Ssam if (isn<=p->labno) isn=1+p->labno; 178*26440Ssam break; 179*26440Ssam 180*26440Ssam case MOVA: 181*26440Ssam p=alloc(sizeof first); 182*26440Ssam p->op = op->opcod; p->subop = op->subopcod; 183*26440Ssam p->code=0; cp1=curlp+1; 184*26440Ssam if (cp1[-1]=='L' || isdigit(cp1[-1])) { 185*26440Ssam while (*cp1++!=','); *--cp1=0; 186*26440Ssam if (0!=(p->labno=locuse(curlp)) || 187*26440Ssam 0!=(p->labno=getnum(curlp+1))) p->code=copy(cp1+1); 188*26440Ssam else {*cp1=','; p->code=copy(curlp);} 189*26440Ssam } else {p->code=copy(--cp1); p->labno=0;} 190*26440Ssam break; 191*26440Ssam 192*26440Ssam case MOV: 193*26440Ssam p=alloc(sizeof first); 194*26440Ssam p->op = op->opcod; p->subop = op->subopcod; 195*26440Ssam p->code = copy(curlp); 196*26440Ssam p->labno = 0; 197*26440Ssam cp1=curlp+1; 198*26440Ssam if ((cp1[-1]=='$') && (cp1[0] == 'L')) { 199*26440Ssam while (*cp1++!=','); *--cp1 =0; 200*26440Ssam p->labno = getnum(curlp+2); 201*26440Ssam } 202*26440Ssam break; 203*26440Ssam case MOVBLK: /* used implicitly */ 204*26440Ssam curlp = "(r0),(r1),(r2)"; 205*26440Ssam goto std; 206*26440Ssam 207*26440Ssam case SET: 208*26440Ssam case COMM: 209*26440Ssam case LCOMM: 210*26440Ssam printf("%s\n",line); goto top; 211*26440Ssam 212*26440Ssam case BSS: 213*26440Ssam case DATA: 214*26440Ssam for (;;) { 215*26440Ssam printf("%s%c",line,(op->opcod==LABEL ? ':' : '\n')); 216*26440Ssam if (op->opcod==TEXT) goto top; 217*26440Ssam if (END==(op=getline())->opcod) {/* dangling .data is bad for you */ 218*26440Ssam printf(".text\n"); 219*26440Ssam break; 220*26440Ssam } 221*26440Ssam } 222*26440Ssam 223*26440Ssam std: 224*26440Ssam default: 225*26440Ssam p = alloc(sizeof first); 226*26440Ssam p->op = op->opcod; p->subop = op->subopcod; 227*26440Ssam p->labno = 0; 228*26440Ssam p->code = copy(curlp); 229*26440Ssam break; 230*26440Ssam 231*26440Ssam } 232*26440Ssam p->forw = 0; 233*26440Ssam p->back = lastp; 234*26440Ssam p->pop = op; 235*26440Ssam lastp->forw = p; 236*26440Ssam lastp = p; 237*26440Ssam p->ref = 0; 238*26440Ssam if (p->op==CASE) { 239*26440Ssam char *lp; int ncase; 240*26440Ssam lp=curlp; while (*lp++); while (*--lp!='$'); ncase=getnum(lp+1); 241*26440Ssam if (ALIGN!=(getline())->opcod || LABEL!=(getline())->opcod) caserr(); 242*26440Ssam do { 243*26440Ssam if (WGEN!=(getline())->opcod) caserr(); 244*26440Ssam p = alloc(sizeof first); 245*26440Ssam p->op = JSW; p->subop = 0; 246*26440Ssam p->code = 0; 247*26440Ssam lp=curlp; while(*lp++!='-'); *--lp=0; p->labno=getnum(curlp+1); 248*26440Ssam if (isn<=p->labno) isn=1+p->labno; 249*26440Ssam p->forw = 0; p->back = lastp; lastp->forw = p; lastp = p; 250*26440Ssam p->ref = 0; p->pop=0; 251*26440Ssam } while (--ncase>=0); 252*26440Ssam } 253*26440Ssam if (op->opcod==EROU) 254*26440Ssam return(1); 255*26440Ssam if (op->opcod==END) 256*26440Ssam return(0); 257*26440Ssam } 258*26440Ssam } 259*26440Ssam 260*26440Ssam caserr() 261*26440Ssam { 262*26440Ssam error("C2: improper casel instruction\n"); 263*26440Ssam } 264*26440Ssam 265*26440Ssam struct optab * 266*26440Ssam getline() 267*26440Ssam { 268*26440Ssam register char *lp; 269*26440Ssam register int c; 270*26440Ssam static struct optab OPLABEL={"",LABEL,0}; 271*26440Ssam static struct optab OPEND={"",END,0}; 272*26440Ssam 273*26440Ssam lp = line; 274*26440Ssam again: 275*26440Ssam while (EOF!=(c=getchar()) && isspace(c)); 276*26440Ssam if (c=='#') { 277*26440Ssam while((c=getchar()) != '\n'); 278*26440Ssam goto again; 279*26440Ssam } 280*26440Ssam while (EOF!=c) { 281*26440Ssam if (c==':') { 282*26440Ssam *lp++ = 0; 283*26440Ssam return(&OPLABEL); 284*26440Ssam } 285*26440Ssam if (c=='\n') { 286*26440Ssam *lp++ = 0; 287*26440Ssam return(oplook()); 288*26440Ssam } 289*26440Ssam if (c=='"') 290*26440Ssam do { 291*26440Ssam if (c=='\\') { 292*26440Ssam *lp++ = c; 293*26440Ssam c = getchar(); 294*26440Ssam } 295*26440Ssam *lp++ = c; 296*26440Ssam c = getchar(); 297*26440Ssam } while(c!='"'); 298*26440Ssam *lp++ = c; 299*26440Ssam c = getchar(); 300*26440Ssam } 301*26440Ssam *lp++ = 0; 302*26440Ssam return(&OPEND); 303*26440Ssam } 304*26440Ssam 305*26440Ssam long 306*26440Ssam getnum(p) 307*26440Ssam register char *p; 308*26440Ssam { 309*26440Ssam register int c, neg, n; 310*26440Ssam 311*26440Ssam n = 0; neg=0; if (*p=='-') {++neg; ++p;} 312*26440Ssam while (isdigit(c = *p++)) { 313*26440Ssam c -= '0'; n *= 10; if (neg) n -= c; else n += c; 314*26440Ssam } 315*26440Ssam if (*--p != 0) 316*26440Ssam return(0); 317*26440Ssam return(n); 318*26440Ssam } 319*26440Ssam 320*26440Ssam locuse(p) 321*26440Ssam register char *p; 322*26440Ssam { 323*26440Ssam 324*26440Ssam if (!isdigit(p[0]) || p[1] != 'f' && p[1] != 'b' || p[2]) return(0); 325*26440Ssam return (lgensym[p[0] - '0'] - (p[1] == 'b')); 326*26440Ssam } 327*26440Ssam 328*26440Ssam locdef(p) 329*26440Ssam register char *p; 330*26440Ssam { 331*26440Ssam 332*26440Ssam if (!isdigit(p[0]) || p[1]) return(0); 333*26440Ssam return (lgensym[p[0] - '0']++); 334*26440Ssam } 335*26440Ssam 336*26440Ssam output() 337*26440Ssam { 338*26440Ssam register struct node *t; 339*26440Ssam int casebas; 340*26440Ssam 341*26440Ssam t = &first; 342*26440Ssam while (t = t->forw) switch (t->op) { 343*26440Ssam 344*26440Ssam case END: 345*26440Ssam fflush(stdout); 346*26440Ssam return; 347*26440Ssam 348*26440Ssam case LABEL: 349*26440Ssam printf("L%d:", t->labno); 350*26440Ssam continue; 351*26440Ssam 352*26440Ssam case DLABEL: 353*26440Ssam printf("%s:", t->code); 354*26440Ssam continue; 355*26440Ssam 356*26440Ssam case CASE: 357*26440Ssam casebas=0; 358*26440Ssam 359*26440Ssam default: std: 360*26440Ssam if (t->pop==0) {/* must find it */ 361*26440Ssam register struct optab *p; 362*26440Ssam for (p=optab; p->opstring[0]; ++p) 363*26440Ssam if (p->opcod==t->op && p->subopcod==t->subop) { 364*26440Ssam t->pop=p; break;} 365*26440Ssam } 366*26440Ssam printf("%s", t->pop->opstring); 367*26440Ssam if (t->code) printf("\t%s", t->code); 368*26440Ssam if (t->op != MOV ) { 369*26440Ssam if (t->labno!=0) printf("%cL%d\n", 370*26440Ssam (t->code ? ',' : '\t'), 371*26440Ssam t->labno); 372*26440Ssam 373*26440Ssam else printf("\n"); 374*26440Ssam } 375*26440Ssam else printf("\n"); 376*26440Ssam continue; 377*26440Ssam 378*26440Ssam case MOVA: 379*26440Ssam if (t->labno==0) goto std; 380*26440Ssam printf("mova%c\tL%d,%s\n","bwlq"[t->subop-BYTE],t->labno,t->code); 381*26440Ssam continue; 382*26440Ssam 383*26440Ssam case MOVBLK: 384*26440Ssam t->code = 0; 385*26440Ssam goto std; 386*26440Ssam 387*26440Ssam case JSW: 388*26440Ssam if (t->subop!=0) {/* F77JSW */ 389*26440Ssam printf(".long\tL%d\n",t->labno); continue; 390*26440Ssam } 391*26440Ssam if (casebas==0) printf(".align 1\nL%d:\n",casebas=isn++); 392*26440Ssam printf(".word L%d-L%d\n", t->labno, casebas); 393*26440Ssam continue; 394*26440Ssam 395*26440Ssam } 396*26440Ssam } 397*26440Ssam 398*26440Ssam char * 399*26440Ssam copy(ap) 400*26440Ssam char *ap; 401*26440Ssam { 402*26440Ssam register char *p, *np, *onp; 403*26440Ssam register int n; 404*26440Ssam 405*26440Ssam p = ap; 406*26440Ssam n = 0; 407*26440Ssam if (*p==0) 408*26440Ssam return(0); 409*26440Ssam do 410*26440Ssam n++; 411*26440Ssam while (*p++); 412*26440Ssam onp = np = (char *)alloc(n); 413*26440Ssam p = ap; 414*26440Ssam while (*np++ = *p++); 415*26440Ssam return(onp); 416*26440Ssam } 417*26440Ssam 418*26440Ssam #define OPHS 560 419*26440Ssam struct optab *ophash[OPHS]; 420*26440Ssam 421*26440Ssam opsetup() 422*26440Ssam { 423*26440Ssam register struct optab *optp, **ophp; 424*26440Ssam register int i,t; 425*26440Ssam 426*26440Ssam for(i=RT1+5;--i>=0;) regs[i]=(char *)alloc(C2_ASIZE); 427*26440Ssam for (optp = optab; optp->opstring[0]; optp++) { 428*26440Ssam t=7; i=0; while (--t>=0) i+= i+optp->opstring[t]; 429*26440Ssam ophp = &ophash[i % OPHS]; 430*26440Ssam while (*ophp++) { 431*26440Ssam /* fprintf(stderr,"\ncollision: %d %s %s", 432*26440Ssam /* ophp-1-ophash,optp->opstring,(*(ophp-1))->opstring); 433*26440Ssam */ 434*26440Ssam if (ophp > &ophash[OPHS]) 435*26440Ssam ophp = ophash; 436*26440Ssam } 437*26440Ssam *--ophp = optp; 438*26440Ssam } 439*26440Ssam } 440*26440Ssam 441*26440Ssam struct optab * 442*26440Ssam oplook() 443*26440Ssam { 444*26440Ssam register struct optab *optp,**ophp; 445*26440Ssam register char *p,*p2; 446*26440Ssam register int t; 447*26440Ssam char tempop[20]; 448*26440Ssam static struct optab OPNULL={"",0,0}; 449*26440Ssam 450*26440Ssam for (p=line, p2=tempop; *p && !isspace(*p); *p2++= *p++); *p2=0; p2=p; 451*26440Ssam while (isspace(*p2)) ++p2; curlp=p2; 452*26440Ssam t=0; while(--p>=line) t += t+*p; ophp = &ophash[t % OPHS]; 453*26440Ssam while (optp = *ophp) { 454*26440Ssam if (equstr(tempop,optp->opstring)) return(optp); 455*26440Ssam if ((++ophp) >= &ophash[OPHS]) ophp = ophash; 456*26440Ssam } 457*26440Ssam curlp = line; 458*26440Ssam return(&OPNULL); 459*26440Ssam } 460*26440Ssam 461*26440Ssam refcount() 462*26440Ssam { 463*26440Ssam register struct node *p, *lp, *np; 464*26440Ssam struct node *labhash[LABHS]; 465*26440Ssam register struct node **hp; 466*26440Ssam 467*26440Ssam for (hp = labhash; hp < &labhash[LABHS];) 468*26440Ssam *hp++ = 0; 469*26440Ssam for (p = first.forw; p!=0; p = p->forw) 470*26440Ssam if (p->op==LABEL) { 471*26440Ssam labhash[p->labno % LABHS] = p; 472*26440Ssam p->refc = 0; 473*26440Ssam } 474*26440Ssam for (p = first.forw; p!=0; p = p->forw) { 475*26440Ssam if (p->op==JBR && p->subop==0 || p->op==CBR || p->op==JSW || p->op==JMP 476*26440Ssam || p->op==AOBLEQ || p->op==AOBLSS 477*26440Ssam || (p->op==MOVA && p->labno!=0) 478*26440Ssam || (p->op==MOV && p->labno!=0)){ 479*26440Ssam p->ref = 0; 480*26440Ssam lp = labhash[p->labno % LABHS]; 481*26440Ssam if (lp==0 || p->labno!=lp->labno) 482*26440Ssam for (lp = first.forw; lp!=0; lp = lp->forw) { 483*26440Ssam if (lp->op==LABEL && p->labno==lp->labno) 484*26440Ssam break; 485*26440Ssam } 486*26440Ssam if (lp) { 487*26440Ssam np = nonlab(lp)->back; 488*26440Ssam if (np!=lp) { 489*26440Ssam p->labno = np->labno; 490*26440Ssam lp = np; 491*26440Ssam } 492*26440Ssam p->ref = lp; 493*26440Ssam lp->refc++; 494*26440Ssam } 495*26440Ssam } 496*26440Ssam } 497*26440Ssam for (p = first.forw; p!=0; p = p->forw) 498*26440Ssam if (p->op==LABEL && p->refc==0 499*26440Ssam && (lp = nonlab(p))->op && lp->op!=JSW) 500*26440Ssam decref(p); 501*26440Ssam } 502*26440Ssam 503*26440Ssam iterate() 504*26440Ssam { 505*26440Ssam register struct node *p, *rp, *p1; 506*26440Ssam 507*26440Ssam nchange = 0; 508*26440Ssam for (p = first.forw; p!=0; p = p->forw) { 509*26440Ssam if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) { 510*26440Ssam rp = nonlab(p->ref); 511*26440Ssam if (rp->op==JBR && rp->labno && p->labno!=rp->labno) { 512*26440Ssam nbrbr++; 513*26440Ssam p->labno = rp->labno; 514*26440Ssam decref(p->ref); 515*26440Ssam rp->ref->refc++; 516*26440Ssam p->ref = rp->ref; 517*26440Ssam nchange++; 518*26440Ssam } 519*26440Ssam } 520*26440Ssam if (p->op==CBR && (p1 = p->forw)->op==JBR && p1->subop==0 521*26440Ssam #ifdef COPYCODE 522*26440Ssam && p->ref 523*26440Ssam #endif 524*26440Ssam ) {/* RET problems */ 525*26440Ssam rp = p->ref; 526*26440Ssam do 527*26440Ssam rp = rp->back; 528*26440Ssam while (rp->op==LABEL); 529*26440Ssam if (rp==p1) { 530*26440Ssam decref(p->ref); 531*26440Ssam p->ref = p1->ref; 532*26440Ssam p->labno = p1->labno; 533*26440Ssam #ifdef COPYCODE 534*26440Ssam if (p->labno == 0) 535*26440Ssam p->code = p1->code; 536*26440Ssam #endif 537*26440Ssam p1->forw->back = p; 538*26440Ssam p->forw = p1->forw; 539*26440Ssam p->subop = revbr[p->subop]; 540*26440Ssam p->pop=0; 541*26440Ssam nchange++; 542*26440Ssam nskip++; 543*26440Ssam } 544*26440Ssam } 545*26440Ssam if (p->op==JBR || p->op==JMP) { 546*26440Ssam while ((p1=p->forw)!=0 && p1->op!=LABEL && p1->op!=DLABEL 547*26440Ssam && p1->op!=EROU && p1->op!=END 548*26440Ssam && p1->op!=ALIGN 549*26440Ssam && p1->op!=0 && p1->op!=DATA) { 550*26440Ssam nchange++; 551*26440Ssam iaftbr++; 552*26440Ssam if (p1->ref) 553*26440Ssam decref(p1->ref); 554*26440Ssam p->forw = p1->forw; 555*26440Ssam p->forw->back = p; 556*26440Ssam } 557*26440Ssam rp = p->forw; 558*26440Ssam while (rp && rp->op==LABEL) { 559*26440Ssam if (p->ref == rp) { 560*26440Ssam p->back->forw = p->forw; 561*26440Ssam p->forw->back = p->back; 562*26440Ssam p = p->back; 563*26440Ssam decref(rp); 564*26440Ssam nchange++; 565*26440Ssam njp1++; 566*26440Ssam break; 567*26440Ssam } 568*26440Ssam rp = rp->forw; 569*26440Ssam } 570*26440Ssam xjump(p); 571*26440Ssam p = codemove(p); 572*26440Ssam } 573*26440Ssam } 574*26440Ssam } 575*26440Ssam 576*26440Ssam xjump(p1) 577*26440Ssam register struct node *p1; 578*26440Ssam { 579*26440Ssam register struct node *p2, *p3; 580*26440Ssam 581*26440Ssam if ((p2 = p1->ref)==0) 582*26440Ssam return; 583*26440Ssam for (;;) { 584*26440Ssam while ((p1 = p1->back) && p1->op==LABEL); 585*26440Ssam while ((p2 = p2->back) && p2->op==LABEL); 586*26440Ssam if (!equop(p1, p2) || p1==p2) 587*26440Ssam return; 588*26440Ssam p3 = insertl(p2); 589*26440Ssam p1->op = JBR; p1->subop = 0; 590*26440Ssam p1->pop=0; 591*26440Ssam p1->ref = p3; 592*26440Ssam p1->labno = p3->labno; 593*26440Ssam p1->code = 0; 594*26440Ssam nxjump++; 595*26440Ssam nchange++; 596*26440Ssam } 597*26440Ssam } 598*26440Ssam 599*26440Ssam struct node * 600*26440Ssam insertl(op) 601*26440Ssam register struct node *op; 602*26440Ssam { 603*26440Ssam register struct node *lp; 604*26440Ssam 605*26440Ssam if (op->op == LABEL) { 606*26440Ssam op->refc++; 607*26440Ssam return(op); 608*26440Ssam } 609*26440Ssam if (op->back->op == LABEL) { 610*26440Ssam op = op->back; 611*26440Ssam op->refc++; 612*26440Ssam return(op); 613*26440Ssam } 614*26440Ssam lp = alloc(sizeof first); 615*26440Ssam lp->op = LABEL; lp->subop = 0; 616*26440Ssam lp->labno = isn++; 617*26440Ssam lp->ref = 0; 618*26440Ssam lp->code = 0; 619*26440Ssam lp->refc = 1; 620*26440Ssam lp->back = op->back; 621*26440Ssam lp->forw = op; 622*26440Ssam op->back->forw = lp; 623*26440Ssam op->back = lp; 624*26440Ssam return(lp); 625*26440Ssam } 626*26440Ssam 627*26440Ssam struct node * 628*26440Ssam codemove(ap) 629*26440Ssam struct node *ap; 630*26440Ssam { 631*26440Ssam register struct node *p1, *p2, *p3; 632*26440Ssam register struct node *t, *tl; 633*26440Ssam register int n; 634*26440Ssam 635*26440Ssam p1 = ap; 636*26440Ssam if (p1->op!=JBR || (p2 = p1->ref)==0 || p2==p1->forw) 637*26440Ssam return(p1); 638*26440Ssam while (p2->op == LABEL) 639*26440Ssam if ((p2 = p2->back) == 0) 640*26440Ssam return(p1); 641*26440Ssam if (p2->op!=JBR && p2->op!=JMP) 642*26440Ssam goto ivloop; 643*26440Ssam p2 = p2->forw; 644*26440Ssam p3 = p1->ref; 645*26440Ssam while (p3) { 646*26440Ssam if (p3->op==JBR || p3->op==JMP) { 647*26440Ssam if (p1==p3) 648*26440Ssam return(p1); 649*26440Ssam ncmot++; 650*26440Ssam nchange++; 651*26440Ssam p1->back->forw = p2; 652*26440Ssam p1->forw->back = p3; 653*26440Ssam p2->back->forw = p3->forw; 654*26440Ssam p3->forw->back = p2->back; 655*26440Ssam p2->back = p1->back; 656*26440Ssam p3->forw = p1->forw; 657*26440Ssam decref(p1->ref); 658*26440Ssam return(p2); 659*26440Ssam } else 660*26440Ssam p3 = p3->forw; 661*26440Ssam } 662*26440Ssam return(p1); 663*26440Ssam ivloop: 664*26440Ssam if (p1->forw->op!=LABEL) 665*26440Ssam return(p1); 666*26440Ssam p3 = p2 = p2->forw; 667*26440Ssam n = 16; 668*26440Ssam do { 669*26440Ssam if ((p3 = p3->forw) == 0 || p3==p1 || --n==0) 670*26440Ssam return(p1); 671*26440Ssam } while (p3->op!=CBR || p3->labno!=p1->forw->labno); 672*26440Ssam do 673*26440Ssam if ((p1 = p1->back) == 0) 674*26440Ssam return(ap); 675*26440Ssam while (p1!=p3); 676*26440Ssam p1 = ap; 677*26440Ssam tl = insertl(p1); 678*26440Ssam p3->subop = revbr[p3->subop]; 679*26440Ssam p3->pop=0; 680*26440Ssam decref(p3->ref); 681*26440Ssam p2->back->forw = p1; 682*26440Ssam p3->forw->back = p1; 683*26440Ssam p1->back->forw = p2; 684*26440Ssam p1->forw->back = p3; 685*26440Ssam t = p1->back; 686*26440Ssam p1->back = p2->back; 687*26440Ssam p2->back = t; 688*26440Ssam t = p1->forw; 689*26440Ssam p1->forw = p3->forw; 690*26440Ssam p3->forw = t; 691*26440Ssam p2 = insertl(p1->forw); 692*26440Ssam p3->labno = p2->labno; 693*26440Ssam #ifdef COPYCODE 694*26440Ssam if (p3->labno == 0) 695*26440Ssam p3->code = p2->code; 696*26440Ssam #endif 697*26440Ssam p3->ref = p2; 698*26440Ssam decref(tl); 699*26440Ssam if (tl->refc<=0) 700*26440Ssam nrlab--; 701*26440Ssam loopiv++; 702*26440Ssam nchange++; 703*26440Ssam return(p3); 704*26440Ssam } 705*26440Ssam 706*26440Ssam comjump() 707*26440Ssam { 708*26440Ssam register struct node *p1, *p2, *p3; 709*26440Ssam 710*26440Ssam for (p1 = first.forw; p1!=0; p1 = p1->forw) 711*26440Ssam if (p1->op==JBR && ((p2 = p1->ref) && p2->refc > 1 712*26440Ssam || (p1->subop&0xF)==RET)) 713*26440Ssam for (p3 = p1->forw; p3!=0; p3 = p3->forw) 714*26440Ssam if (p3->op==JBR && p3->ref == p2) 715*26440Ssam backjmp(p1, p3); 716*26440Ssam } 717*26440Ssam 718*26440Ssam backjmp(ap1, ap2) 719*26440Ssam struct node *ap1, *ap2; 720*26440Ssam { 721*26440Ssam register struct node *p1, *p2, *p3; 722*26440Ssam 723*26440Ssam p1 = ap1; 724*26440Ssam p2 = ap2; 725*26440Ssam for(;;) { 726*26440Ssam while ((p1 = p1->back) && p1->op==LABEL); 727*26440Ssam p2 = p2->back; 728*26440Ssam if (equop(p1, p2)) { 729*26440Ssam p3 = insertl(p1); 730*26440Ssam p2->back->forw = p2->forw; 731*26440Ssam p2->forw->back = p2->back; 732*26440Ssam p2 = p2->forw; 733*26440Ssam decref(p2->ref); 734*26440Ssam p2->op = JBR; p2->subop = 0; /* to handle RET */ 735*26440Ssam p2->pop=0; 736*26440Ssam p2->labno = p3->labno; 737*26440Ssam #ifdef COPYCODE 738*26440Ssam p2->code = 0; 739*26440Ssam #endif 740*26440Ssam p2->ref = p3; 741*26440Ssam nchange++; 742*26440Ssam ncomj++; 743*26440Ssam } else 744*26440Ssam return; 745*26440Ssam } 746*26440Ssam } 747