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