xref: /original-bsd/old/pcc/c2.tahoe/c22.c (revision 576c43b3)
1 #ifndef lint
2 static char sccsid[] = "@(#)c22.c	1.2 (Berkeley) 03/03/86";
3 #endif
4 
5 /*
6  * C object code improver-- third part
7  */
8 
9 #include "c2.h"
10 #include <stdio.h>
11 #include <ctype.h>
12 
13 rmove()
14 {
15 	register struct node *p;
16 	register int r, r1;
17 
18 	clearreg();
19 	for (p=first.forw; p!=0; p = p->forw) {
20 	if (debug) {
21 		printf("Regs: ");
22 		for (r=0; r<=NREG; r++)
23 			if (regs[r][0]) {
24 				r1=regs[r][0];
25 				printf("%d: %d%d %s\n", r, r1&0xF, r1>>4, regs[r]+1);
26 			}
27 		printf("-\n");
28 	}
29 	switch (p->op) {
30 
31 	case CVT:
32 	case MOVZ:
33 		splitrand(p);
34 		repladdr(p);
35 		r = isreg(regs[RT1]);
36 		r1 = isreg(regs[RT2]);
37 		dest(regs[RT2],p->subop, 1);
38 		if (r>=0 && r1>=0) {
39 			p->op = MOV; p->subop = LONG;
40 			p->pop = 0;
41 			nchange++;
42 			goto case_mov;
43 		}
44 		if(p->op == CVT) {
45 			if (r1>=0) savereg(r1, regs[RT1], p->subop);
46 		} else
47 			ccloc[0] = 0;
48 		break;
49 
50 	case MOV:
51 	case_mov:
52 		splitrand(p);
53 		if ((r = findrand(regs[RT1],p->subop)) >= 0) {
54 			if (r == isreg(regs[RT2]))
55 				if(p->forw->op!=CBR) {
56 					delnode(p); redunm++; nchange++; break;
57 				} else {
58 					p->op=TST; p->pop=0;
59 					while(*p->code++ != ',');
60 					redunm++; nchange++;
61 					goto case_tst;
62 				}
63 		}
64 		repladdr(p);
65 		r = isreg(regs[RT1]);
66 		r1 = isreg(regs[RT2]);
67 		dest(regs[RT2],p->subop, 1);
68 		if ((regs[ACC][0]) && equstr(regs[RT2],regs[ACC]+1)) {
69                 *(short *)(regs[ACC]) = 0;}
70 
71 		if (r>=0) {
72 			if (r1>=0) {
73 				if (r == r1 && p->forw->op!=CBR) {
74 					delnode(p); redunm++; nchange++; break;
75 				}
76 				if(regs[r][0])
77 					savereg(r1, regs[r]+1, p->subop);
78 			} else savereg(r, regs[RT2], p->subop);
79 		} else if (r1>=0) savereg(r1, regs[RT1], p->subop);
80 		else setcon(regs[RT1], regs[RT2], p->subop);
81 		break;
82 
83 /* .rx,.wx or .rx,.rx,.wx */
84 	case ADD:
85 	case SUB:
86 	case AND:
87 	case OR:
88 	case XOR:
89 	case MUL:
90 	case DIV:
91 #ifdef EMOD
92 	case EDIV:
93 	case EMOD:
94 #endif EMOD
95 	case SHAL:
96 	case SHAR:
97 	case SHL:
98 	case SHR:
99 	case ADDA:
100 	case SUBA:
101 /* .rx,.wx */
102 	case MFPR:
103 	case COM:
104 	case NEG:
105 		splitrand(p);
106 		repladdr(p);
107 		dest(lastrand,p->subop, p->op!=ADDA && p->op!=SUBA);
108 		break;
109 
110 /* .mx or .wx */
111 	case STF:
112 		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
113 			delnode(p);
114 			nst++; nchange++; break;
115 		}
116 		savereg(ACC, p->code, p->subop);
117 	case CLR:
118 	case INC:
119 	case DEC:
120 	case CVFL:
121 		dest(p->code,p->subop, 1);
122 		if (p->op==CLR)
123 			if ((r = isreg(p->code)) >= 0)
124 				savereg(r, "$0", p->subop);
125 			else
126 				setcon("$0", p->code, p->subop);
127 		break;
128 
129 /* .rx */
130 	case LDF:
131 		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
132 			delnode(p);
133 			nld++; nchange++; break;
134 		}
135 		savereg(ACC, p->code, p->subop);
136 		goto case_tst;
137 	case LNF:
138 		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
139 			p->op = NEGF; p->pop = 0; p->code = 0;
140 			regs[ACC][0] = 0;
141 			break;
142 		}
143 	case CVLF:
144 	case LDFD:
145 	case ADDF:
146 	case SUBF:
147 	case MULF:
148 	case DIVF:
149 		regs[ACC][0] = 0;
150 	case TST:
151 	case_tst:
152 	case PUSH:
153 		splitrand(p);
154 		lastrand=regs[RT1+1]; /* fool repladdr into doing 1 operand */
155 		repladdr(p);
156 		lastrand=regs[RT1];
157 		if (p->op==TST && equstr(lastrand, ccloc+1)
158 		  && ((0xf&(ccloc[0]>>4))==p->subop || equtype(ccloc[0],p->subop))) {
159 			delnode(p); nrtst++; nchange++; break;
160 		}
161 		if (p->op==PUSH && p->subop!=LONG &&
162 		 (isreg(lastrand)>=0 || *lastrand=='$')) {
163 			p->subop = LONG;
164 			p->pop = 0;
165 			nchange++;
166 		}
167 		if (p->op==TST || p->op==PUSH)
168 			setcc(lastrand,p->subop);
169 		break;
170 
171 /* .rx,.rx,.rx */
172 	case PROBE:
173 	case CASE:
174 /* .rx,.rx */
175 	case MTPR:
176 	case CALLS:
177 	case CALLF:
178 	case CMP:
179 	case BIT:
180 	case CMPF:
181 	case CMPF2:
182 		splitrand(p);
183 		/* fool repladdr into doing right number of operands */
184 		lastrand=byondrd(p);
185 		if (p->op==CALLF || p->op==CALLS) clearreg();
186 		else repladdr(p);
187 	case TSTF:
188 		ccloc[0]=0;
189 	case PUSHD:
190 		break;
191 
192 /* acc only */
193 	case CVDF:
194 	case NEGF:
195 	case SINF:
196 	case COSF:
197 	case ATANF:
198 	case LOGF:
199 	case SQRTF:
200 	case EXPF:
201 		regs[ACC][0] = 0;
202 		break;
203 
204 #ifndef EMOD
205 /* .rx,.rx,.wx,.wx */
206 	case EDIV:
207 		splitrand(p);
208 		lastrand = regs[RT3];
209 		repladdr(p);
210 		dest(regs[RT3], p->subop, 1);
211 		dest(regs[RT4], p->subop, 0);
212 		break;
213 #endif EMOD
214 
215 /* .rx,.rx,.rx,wx */
216 	case EMUL:
217 		splitrand(p);
218 		lastrand = regs[RT4];
219 		repladdr(p);
220 		dest(regs[RT4],QUAD, 1); /* fourth operand is a quad */
221 		break;
222 	case CBR:
223 		if (p->subop>=JBC) {
224 			splitrand(p);
225 			lastrand=regs[RT3]; /* 2 operands can be optimized */
226 			repladdr(p);
227 			ccloc[0] = 0;
228 		} else
229 			reduncbr(p);
230 		break;
231 
232 	case JBR:
233 		redunbr(p);
234 
235 	default:
236 		clearreg();
237 	}
238 	}
239 }
240 
241 jumpsw()
242 {
243 	register struct node *p, *p1, *pt;
244 	register int t, nj;
245 
246 	t = 0;
247 	nj = 0;
248 	for (p=first.forw; p!=0; p = p->forw)
249 		p->seq = ++t;
250 	for (p=first.forw; p!=0; p = p1) {
251 		p1 = p->forw;
252 		if (p->op == CBR && p1->op==JBR && p->ref && p1->ref
253 		 && abs(p->seq - p->ref->seq) > abs(p1->seq - p1->ref->seq)) {
254 			if (p->ref==p1->ref)
255 				continue;
256 			p->subop = revbr[p->subop];
257 			p->pop=0;
258 			pt = p1->ref;
259 			p1->ref = p->ref;
260 			p->ref = pt;
261 			t = p1->labno;
262 			p1->labno = p->labno;
263 			p->labno = t;
264 #ifdef COPYCODE
265 			if (p->labno == 0) {
266 				pt = (struct node *)p1->code; p1->code = p->code; p->code = (char *)pt;
267 			}
268 #endif
269 			nrevbr++;
270 			nj++;
271 		}
272 	}
273 	return(nj);
274 }
275 
276 addaob()
277 {
278 	register struct node *p, *p1, *p2, *p3;
279 
280 	for (p = &first; (p1 = p->forw)!=0; p = p1) {
281 	if (p->op==INC && p->subop==LONG) {
282 		if (p1->op==LABEL && p1->refc==1 && p1->forw->op==CMP && p1->forw->subop==LONG
283 		  && (p2=p1->forw->forw)->op==CBR && p2->subop==JLE
284 		  && (p3=p2->ref->back)->op==JBR && p3->subop==0 && p3->ref==p1
285 		  && p3->forw->op==LABEL && p3->forw==p2->ref) {
286 			/* change	INC LAB: CMP	to	LAB: INC CMP */
287 			p->back->forw=p1; p1->back=p->back;
288 			p->forw=p1->forw; p1->forw->back=p;
289 			p->back=p1; p1->forw=p;
290 			p1=p->forw;
291 			/* adjust beginning value by 1 */
292 			p2=alloc(sizeof first); p2->op = DEC; p2->subop = LONG;
293 			p2->pop=0;
294 			p2->forw=p3; p2->back=p3->back; p3->back->forw=p2;
295 			p3->back=p2; p2->code=p->code; p2->labno=0;
296 		}
297 		if (p1->op==CMP && p1->subop==LONG &&
298 		  (p2=p1->forw)->op==CBR && p2->forw->op!=CBR) {
299 			register char *cp1,*cp2;
300 			splitrand(p1); if (!equstr(p->code,regs[RT1])) continue;
301 			if (p2->subop==JLE || p2->subop==JLT) {
302 				if (p2->subop==JLE) p->op = AOBLEQ; else p->op = AOBLSS; p->subop = 0;
303 				cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); /* limit */
304 				cp2=regs[RT2]; cp1=p->code; while (*cp2++= *cp1++); /* index */
305 				p->pop=0; newcode(p);
306 				p->labno = p2->labno; delnode(p2); delnode(p1); naob++;
307 			}
308 		}
309 	}
310 	}
311 }
312 
313 ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */
314 	register int log;
315 	if (n==0 || n&(n-1)) return(-1); log=0;
316 	for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);}
317 }
318 
319 equop(p1, p2)
320 register struct node *p1, *p2;
321 {
322 	register char *cp1, *cp2;
323 
324 	if (p1->op != p2->op || p1->subop != p2->subop)
325 		return(0);
326 	if (p1->op>0 && p1->op<MOV)
327 		return(0);
328 	if (p1->op==MOVA && p1->labno!=p2->labno) return(0);
329 	cp1 = p1->code;
330 	cp2 = p2->code;
331 	if (cp1==0 && cp2==0)
332 		return(1);
333 	if (cp1==0 || cp2==0)
334 		return(0);
335 	while (*cp1 == *cp2++)
336 		if (*cp1++ == 0)
337 			return(1);
338 	return(0);
339 }
340 
341 delnode(p) register struct node *p; {
342 	p->back->forw = p->forw;
343 	p->forw->back = p->back;
344 }
345 
346 decref(p)
347 register struct node *p;
348 {
349 	if (p && --p->refc <= 0) {
350 		nrlab++; nchange++;
351 		delnode(p);
352 	}
353 }
354 
355 struct node *
356 nonlab(ap)
357 struct node *ap;
358 {
359 	register struct node *p;
360 
361 	p = ap;
362 	while (p && p->op==LABEL)
363 		p = p->forw;
364 	return(p);
365 }
366 
367 clearuse() {
368 	register struct node **i;
369 	for (i=uses+NUSE; i>uses;) *--i=0;
370 	useacc = 0;
371 }
372 
373 clearreg() {
374 	register char **i;
375 	for (i=regs+NREG+1; i>regs;){ **--i=0; **i=0; }
376 	conloc[0] = 0; ccloc[0] = 0;
377 }
378 
379 savereg(ai, s, type)
380 register char *s;
381 {
382 	register char *p, *sp;
383 
384 	sp = p = regs[ai];
385 	/* if any indexing, must be parameter or local */
386 	/* indirection (as in "*-4(fp)") is ok, however */
387 	*p++ = type;
388 	if (*s=='*' || *s=='$')
389 		*p++ = *s++;
390 	if (natural(s))
391 		strcpy(p, s);
392 	else {*sp = 0; return;}
393 }
394 
395 dest(s,type, ccflg)
396 register char *s;
397 {
398 	register int i;
399 
400 	if ((i = isreg(s)) >= 0) {
401 		*(short *)(regs[i]) = 0; /* if register destination, that reg is a goner */
402 		if (DOUBLE==(type&0xF) || DOUBLE==((type>>4)&0xF) || type==QUAD)
403 			*(short *)(regs[i+1]) = 0;
404 	}
405 	for (i=NREG; --i>=0;)
406 		if (regs[i][1]=='*' && equstr(s, regs[i]+2))
407 			*(short *)(regs[i]) = 0; /* previous indirection through destination is invalid */
408 	while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */
409 		*(short *)(regs[i]) = 0;
410 
411 	if (!natural(s)) {/* wild store, everything except constants vanishes */
412 		for (i=NREG; --i>=0;) if (regs[i][1] != '$') *(short *)(regs[i]) = 0;
413 		conloc[0] = 0; ccloc[0] = 0;
414 	} else {
415 		if(ccflg)setcc(s,type); /* natural destinations set condition codes */
416 		if (equstr(s, conloc))
417 			conloc[0] = 0;
418 	}
419 }
420 
421 splitrand(p) struct node *p; {
422 /* separate operands at commas, set up 'regs' and 'lastrand' */
423 register char *p1, *p2; register char **preg;
424 
425 	preg=regs+RT1;
426 	if (p1=p->code) while (*p1) {
427 		lastrand=p2= *preg++;
428 		while (*p1) if (','==(*p2++= *p1++)) {--p2; break;}
429 		*p2=0;
430 	}
431 	while (preg<(regs+RT1+5)) *(*preg++)=0;
432 }
433 
434 compat(have, want)
435 register int have, want;
436 {
437 	register int hsrc, hdst;
438 	extern int bitsize[];
439 
440 	if (0==(want &= 0xF)) return(1); /* anything satisfies a wildcard want */
441 	hsrc=have&0xF; if (0==(hdst=((have>>4)&0xF)) || hdst>=OP2) hdst=hsrc;
442 	if (want>=QUAD)
443 		return(bitsize[hdst]==bitsize[want] && bitsize[hsrc]==bitsize[want]);
444 	return(hsrc==want && hdst>=want && hdst<QUAD);
445 }
446 
447 equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));}
448 
449 findrand(as, type)
450 char *as;
451 {
452 	register char **i;
453 	for (i = regs+NREG; --i>=regs;) {
454 		if (**i && equstr(*i+1, as) && compat(**i,type))
455 			return(i-regs);
456 	}
457 	return(-1);
458 }
459 
460 isreg(s)
461 register char *s;
462 {
463 	if (*s++!='r' || !isdigit(*s++)) return(-1);
464 	if (*s==0) return(*--s-'0');
465 	if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'0');
466 	return(-1);
467 }
468 
469 /*
470 check()
471 {
472 	register struct node *p, *lp;
473 
474 	lp = &first;
475 	for (p=first.forw; p!=0; p = p->forw) {
476 		if (p->back != lp)
477 			abort(-1);
478 		lp = p;
479 	}
480 }
481 */
482 
483 newcode(p) struct node *p; {
484 	register char *p1,*p2,**preg;
485 
486 	preg=regs+RT1; p2=line;
487 	while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';}
488 	*--p2=0;
489 	p->code=copy(line);
490 }
491 
492 repladdr(p)
493 struct node *p;
494 {
495 	register int r;
496 	register char *p1;
497 	register char **preg;
498 	register int nrepl;
499 
500 	preg=regs+RT1; nrepl=0;
501 	while (lastrand!=(p1= *preg++))
502 		if (0<=(r=findrand(p1,p->subop))) {
503 			*p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0;
504 			nchange++; nrepl++; nsaddr++;
505 		}
506 	if (nrepl) newcode(p);
507 }
508 
509 /* conditional branches which are never/always taken */
510 reduncbr(p)
511 register struct node *p;
512 {
513 	register struct node *p1;
514 	register char *ap1, *ap2;
515 
516 	p1 = p->back;
517 	if (p1->op==CMP) {
518 		splitrand(p1);
519 		ap1 = findcon(regs[RT1], p1->subop);
520 		ap2 = findcon(regs[RT2], p1->subop);
521 	} else {
522 		if(!ccloc[0])
523 			return;
524 		ap1 = findcon(ccloc+1, ccloc[0]);
525 		ap2 = "$0";
526 	}
527 	switch (compare(p->subop, ap1, ap2)) {
528 	case 0:		/* branch never taken */
529 		delnode(p);
530 		nredunj++;
531 		nchange++;
532 		decref(p->ref);
533 		if(p->forw->op!=CBR && (p1->op==TST || p1->op==CMP)) {
534 			delnode(p1);
535 			nrtst++;
536 		}
537 		break;
538 	case 1:		/* branch always taken */
539 		p->op = JBR;
540 		p->subop = 0;
541 		p->pop = 0;
542 		nchange++;
543 		if(nonlab(p->ref)->op!=CBR && (p1->op==TST || p1->op==CMP)) {
544 			delnode(p1);
545 			nrtst++;
546 		}
547 	}
548 }
549 
550 /* a jump to a redundant compare (start of a 'for') */
551 redunbr(p)
552 register struct node *p;
553 {
554 	register struct node *p1;
555 	register char *ap1, *ap2;
556 
557 	if ((p1 = p->ref) == 0)
558 		return;
559 	p1 = nonlab(p1);
560 	if (p1->op==TST || p1->op==CMP)
561 		splitrand(p1);
562 	else
563 		return;
564 	if (p1->forw->op==CBR) {
565 		ap1 = findcon(regs[RT1], p1->subop);
566 		if (p1->op==TST)
567 			ap2 = "$0";
568 		else
569 			ap2 = findcon(regs[RT2], p1->subop);
570 		p1 = p1->forw;
571 		if (compare(p1->subop, ap1, ap2) > 0) {
572 			nredunj++;
573 			nchange++;
574 			decref(p->ref);
575 			p->ref = p1->ref;
576 			p->labno = p1->labno;
577 #ifdef COPYCODE
578 			if (p->labno == 0)
579 				p->code = p1->code;
580 			if (p->ref)
581 #endif
582 				p->ref->refc++;
583 		}
584 	} else if (p1->op==TST && equstr(regs[RT1],ccloc+1) &&
585 			equtype(ccloc[0],p1->subop)) {
586 		p1=insertl(p1->forw); decref(p->ref); p->ref=p1;
587 		nrtst++; nchange++;
588 	}
589 }
590 
591 char *
592 findcon(p, type)
593 	register char *p;
594 {
595 	register int r;
596 
597 	if (*p=='$')
598 		return(p);
599 	if ((r = isreg(p)) >= 0 && compat(regs[r][0],type))
600 		return(regs[r]+1);
601 	if (equstr(p, conloc) && conval[0] == type)
602 		return(conval+1);
603 	return(p);
604 }
605 
606 /* compare constants: 0 - branch taken; 1 - not taken; -1 - don't know */
607 compare(op, acp1, acp2)
608 char *acp1, *acp2;
609 {
610 	register char *cp1, *cp2;
611 	register int n1, n2, sign;
612 
613 	cp1 = acp1;
614 	cp2 = acp2;
615 	if (*cp1++ != '$' || *cp2++ != '$')
616 		return(-1);
617 	n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;}
618 	while (isdigit(*cp1)) {n1 *= 10; n1 += *cp1++ - '0';}
619 	n1 *= sign;
620 	n2 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;}
621 	while (isdigit(*cp2)) {n2 *= 10; n2 += *cp2++ - '0';}
622 	n2 *= sign;
623 	if (*cp1=='+')
624 		cp1++;
625 	if (*cp2=='+')
626 		cp2++;
627 	do {
628 		if (*cp1++ != *cp2)
629 			return(-1);
630 	} while (*cp2++);
631 	switch(op) {
632 
633 	case JEQ:
634 		return(n1 == n2);
635 	case JNE:
636 		return(n1 != n2);
637 	case JLE:
638 		return(n1 <= n2);
639 	case JGE:
640 		return(n1 >= n2);
641 	case JLT:
642 		return(n1 < n2);
643 	case JGT:
644 		return(n1 > n2);
645 	case JLO:
646 		return((unsigned)n1 < (unsigned)n2);
647 	case JHI:
648 		return((unsigned)n1 > (unsigned)n2);
649 	case JLOS:
650 		return((unsigned)n1 <= (unsigned)n2);
651 	case JHIS:
652 		return((unsigned)n1 >= (unsigned)n2);
653 	}
654 	return(-1);
655 }
656 
657 setcon(cv, cl, type)
658 register char *cv, *cl;
659 {
660 	register char *p;
661 
662 	if (*cv != '$')
663 		return;
664 	if (!natural(cl))
665 		return;
666 	p = conloc;
667 	while (*p++ = *cl++);
668 	p = conval;
669 	*p++ = type;
670 	while (*p++ = *cv++);
671 }
672 
673 setcc(ap,type)
674 char *ap;
675 {
676 	register char *p, *p1;
677 
678 	p = ap;
679 	if (!natural(p)) {
680 		ccloc[0] = 0;
681 		return;
682 	}
683 	p1 = ccloc;
684 	*p1++ = type;
685 	while (*p1++ = *p++);
686 }
687 
688 indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */
689 	while (*p) if (*p++=='[') return(1);
690 	return(0);
691 }
692 
693 natural(p)
694 register char *p;
695 {/* 1->simple local, parameter, global, or register; 0->otherwise */
696 
697 	if (*p=='*' || *p=='(' || *p=='$')
698 		return(0);
699 	while (*p++);
700 	p--;
701 	if (*--p==']' || *p==')' &&
702 	 !(*(p-2)=='f' || fortflg && (*--p=='1' || *p=='2') && *--p=='1'))
703 		return(0);
704 	return(1);
705 }
706 
707 /*
708 ** Tell if an argument is most likely static.
709 */
710 
711 isstatic(cp)
712 register char	*cp;
713 {
714 	if (*cp == '_' || *cp == 'L')
715 		return (1);
716 	return (0);
717 }
718