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