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