xref: /csrg-svn/old/pcc/c2.tahoe/c22.c (revision 33300)
1 #ifndef lint
2 static char sccsid[] = "@(#)c22.c	1.7 (Berkeley/CCI) 01/10/88";
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 		if (r>=0) {
71 			if (r1>=0) {
72 				if (r == r1 && p->forw->op!=CBR) {
73 					delnode(p); redunm++; nchange++;
74 					break;
75 				}
76 				if(regs[r][0])
77 					savereg(r1, regs[r]+1, p->subop);
78 			} else
79 				savereg(r, regs[RT2], p->subop);
80 		} else if (r1>=0)
81 			savereg(r1, regs[RT1], p->subop);
82 		else
83 			setcon(regs[RT1], regs[RT2], p->subop);
84 		break;
85 
86 /* .rx,.wx or .rx,.rx,.wx */
87 	case ADD:
88 	case SUB:
89 	case AND:
90 	case OR:
91 	case XOR:
92 	case MUL:
93 	case DIV:
94 #ifdef EMOD
95 	case EDIV:
96 	case EMOD:
97 #endif EMOD
98 	case SHAL:
99 	case SHAR:
100 	case SHL:
101 	case SHR:
102 	case ADDA:
103 	case SUBA:
104 /* .rx,.wx */
105 	case MFPR:
106 	case COM:
107 	case NEG:
108 		splitrand(p);
109 		repladdr(p);
110 		dest(lastrand,p->subop, p->op!=ADDA && p->op!=SUBA);
111 		break;
112 
113 /* .mx or .wx */
114 	case STF:
115 		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
116 			delnode(p);
117 			nst++; nchange++; break;
118 		}
119 		savereg(ACC, p->code, p->subop);
120 	case INC:
121 	case DEC:
122 	case CVFL:
123 		dest(p->code,p->subop, 1);
124 		break;
125 
126 	case CLR:
127 		dest(p->code,p->subop, 1);
128 		if ((regs[ACC][0]) && equstr(p->code,regs[ACC]+1))
129 			*(short *)(regs[ACC]) = 0;
130 		if ((r = isreg(p->code)) < 0)
131 			setcon("$0", p->code, p->subop);
132 		else
133 			savereg(r, "$0", p->subop);
134 		break;
135 
136 /* .rx */
137 	case LDF:
138 		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
139 			delnode(p);
140 			nld++; nchange++; break;
141 		}
142 		savereg(ACC, p->code, p->subop);
143 		goto case_tst;
144 	case LNF:
145 		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
146 			p->op = NEGF; p->pop = 0; p->code = 0;
147 			regs[ACC][0] = 0;
148 			break;
149 		}
150 	case CVLF:
151 	case LDFD:
152 	case ADDF:
153 	case SUBF:
154 	case MULF:
155 	case DIVF:
156 		regs[ACC][0] = 0;
157 	case TST:
158 	case_tst:
159 	case PUSH:
160 		splitrand(p);
161 		lastrand=regs[RT1+1]; /* fool repladdr into doing 1 operand */
162 		repladdr(p);
163 		lastrand=regs[RT1];
164 		if (p->op==TST && equstr(lastrand, ccloc+1)
165 		  && ((0xf&(ccloc[0]>>4))==p->subop || equtype(ccloc[0],p->subop))) {
166 			delnode(p); nrtst++; nchange++; break;
167 		}
168 		if (p->op==PUSH && p->subop!=LONG &&
169 		 (isreg(lastrand)>=0 || *lastrand=='$')) {
170 			p->subop = LONG;
171 			p->pop = 0;
172 			nchange++;
173 		}
174 		if (p->op==TST || p->op==PUSH)
175 			setcc(lastrand,p->subop);
176 		break;
177 
178 /* .rx,.rx,.rx */
179 	case PROBE:
180 	case CASE:
181 /* .rx,.rx */
182 	case MTPR:
183 	case CALLS:
184 	case CALLF:
185 	case CMP:
186 	case BIT:
187 	case CMPF:
188 	case CMPF2:
189 		splitrand(p);
190 		/* fool repladdr into doing right number of operands */
191 		lastrand=byondrd(p);
192 		if (p->op==CALLF || p->op==CALLS) clearreg();
193 		else repladdr(p);
194 	case TSTF:
195 		ccloc[0]=0;
196 	case PUSHD:
197 		break;
198 
199 /* acc only */
200 	case CVDF:
201 	case NEGF:
202 	case SINF:
203 	case COSF:
204 	case ATANF:
205 	case LOGF:
206 	case SQRTF:
207 	case EXPF:
208 		regs[ACC][0] = 0;
209 		break;
210 
211 #ifndef EMOD
212 /* .rx,.rx,.wx,.wx */
213 	case EDIV:
214 		splitrand(p);
215 		lastrand = regs[RT3];
216 		repladdr(p);
217 		dest(regs[RT3], p->subop, 1);
218 		dest(regs[RT4], p->subop, 0);
219 		break;
220 #endif EMOD
221 
222 /* .rx,.rx,.rx,wx */
223 	case EMUL:
224 		splitrand(p);
225 		lastrand = regs[RT4];
226 		repladdr(p);
227 		dest(regs[RT4],QUAD, 1); /* fourth operand is a quad */
228 		break;
229 	case CBR:
230 		if (p->subop>=JBC) {
231 			splitrand(p);
232 			lastrand=regs[RT3]; /* 2 operands can be optimized */
233 			repladdr(p);
234 			ccloc[0] = 0;
235 		} else
236 			reduncbr(p);
237 		break;
238 
239 	case JBR:
240 		redunbr(p);
241 
242 	default:
243 		clearreg();
244 	}
245 	}
246 }
247 
248 jumpsw()
249 {
250 	register struct node *p, *p1, *pt;
251 	register int t, nj;
252 
253 	t = 0;
254 	nj = 0;
255 	for (p=first.forw; p!=0; p = p->forw)
256 		p->seq = ++t;
257 	for (p=first.forw; p!=0; p = p1) {
258 		p1 = p->forw;
259 		if (p->op == CBR && p1->op==JBR && p->ref && p1->ref
260 		 && abs(p->seq - p->ref->seq) > abs(p1->seq - p1->ref->seq)) {
261 			if (p->ref==p1->ref)
262 				continue;
263 			p->subop = revbr[p->subop];
264 			p->pop=0;
265 			pt = p1->ref;
266 			p1->ref = p->ref;
267 			p->ref = pt;
268 			t = p1->labno;
269 			p1->labno = p->labno;
270 			p->labno = t;
271 #ifdef COPYCODE
272 			if (p->labno == 0) {
273 				pt = (struct node *)p1->code; p1->code = p->code; p->code = (char *)pt;
274 			}
275 #endif
276 			nrevbr++;
277 			nj++;
278 		}
279 	}
280 	return(nj);
281 }
282 
283 addaob()
284 {
285 	register struct node *p, *p1, *p2, *p3;
286 
287 	for (p = &first; (p1 = p->forw)!=0; p = p1) {
288 	if (p->op==INC && p->subop==LONG) {
289 		if (p1->op==LABEL && p1->refc==1 && p1->forw->op==CMP && p1->forw->subop==LONG
290 		  && (p2=p1->forw->forw)->op==CBR && p2->subop==JLE
291 		  && (p3=p2->ref->back)->op==JBR && p3->subop==0 && p3->ref==p1
292 		  && p3->forw->op==LABEL && p3->forw==p2->ref) {
293 			/* change	INC LAB: CMP	to	LAB: INC CMP */
294 			p->back->forw=p1; p1->back=p->back;
295 			p->forw=p1->forw; p1->forw->back=p;
296 			p->back=p1; p1->forw=p;
297 			p1=p->forw;
298 			/* adjust beginning value by 1 */
299 			p2=alloc(sizeof first); p2->op = DEC; p2->subop = LONG;
300 			p2->pop=0;
301 			p2->forw=p3; p2->back=p3->back; p3->back->forw=p2;
302 			p3->back=p2; p2->code=p->code; p2->labno=0;
303 		}
304 		if (p1->op==CMP && p1->subop==LONG &&
305 		  (p2=p1->forw)->op==CBR && p2->forw->op!=CBR) {
306 			register char *cp1,*cp2;
307 			splitrand(p1); if (!equstr(p->code,regs[RT1])) continue;
308 			if ((p2->subop==JLE || p2->subop==JLT) &&
309 			    checkaobdisp(p2)){
310 				if (p2->subop==JLE) p->op = AOBLEQ; else p->op = AOBLSS; p->subop = 0;
311 				cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); /* limit */
312 				cp2=regs[RT2]; cp1=p->code; while (*cp2++= *cp1++); /* index */
313 				p->pop=0; newcode(p);
314 				p->labno = p2->labno; delnode(p2); delnode(p1); naob++;
315 			}
316 		}
317 	}
318 	}
319 }
320 
321 ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */
322 	register int log;
323 	if (n==0 || n&(n-1)) return(-1); log=0;
324 	for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);}
325 }
326 
327 equop(p1, p2)
328 register struct node *p1, *p2;
329 {
330 	register char *cp1, *cp2;
331 
332 	if (p1->op != p2->op || p1->subop != p2->subop)
333 		return(0);
334 	if (p1->op == NIL && p1->subop == 0 && p1->pop != p2->pop)
335 		return(0);
336 	if (p1->op != NIL && ord(p1->op) < ord(MOV))
337 		return(0);
338 	switch (p1->op) {
339 	case EROU:	case JSW:	case TEXT:	case DATA:
340 	case BSS:	case ALIGN:	case WGEN:	case END:
341 		/* sufficient? */
342 		return(0);
343 	}
344 	if (p1->op==MOVA && p1->labno!=p2->labno) return(0);
345 	cp1 = p1->code;
346 	cp2 = p2->code;
347 	if (cp1==0 && cp2==0)
348 		return(1);
349 	if (cp1==0 || cp2==0)
350 		return(0);
351 	while (*cp1 == *cp2++)
352 		if (*cp1++ == 0)
353 			return(1);
354 	return(0);
355 }
356 
357 delnode(p) register struct node *p; {
358 	p->back->forw = p->forw;
359 	p->forw->back = p->back;
360 }
361 
362 decref(p)
363 register struct node *p;
364 {
365 	if (p && --p->refc <= 0) {
366 		nrlab++; nchange++;
367 		delnode(p);
368 	}
369 }
370 
371 struct node *
372 nonlab(ap)
373 struct node *ap;
374 {
375 	register struct node *p;
376 
377 	p = ap;
378 	while (p && p->op==LABEL)
379 		p = p->forw;
380 	return(p);
381 }
382 
383 clearuse() {
384 	register struct node **i;
385 	for (i=uses+NREG; i>uses;) *--i=0;
386 	useacc = 0;
387 }
388 
389 clearreg() {
390 	register char **i;
391 	for (i=regs+NREG+1; i>regs;){ **--i=0; **i=0; }
392 	conloc[0] = 0; ccloc[0] = 0;
393 }
394 
395 savereg(ai, s, type)
396 register char *s;
397 {
398 	register char *p, *sp;
399 
400 	sp = p = regs[ai];
401 	/* if any indexing, must be parameter or local */
402 	/* indirection (as in "*-4(fp)") is ok, however */
403 	*p++ = type;
404 	if (*s=='*' || *s=='$')
405 		*p++ = *s++;
406 	if (natural(s))
407 		strcpy(p, s);
408 	else {*sp = 0; return;}
409 }
410 
411 dest(s,type, ccflg)
412 register char *s;
413 {
414 	register int i;
415 
416 	if ((i = isreg(s)) >= 0) {
417 		*(short *)(regs[i]) = 0; /* if register destination, that reg is a goner */
418 		if (DOUBLE==(type&0xF) || DOUBLE==((type>>4)&0xF) || type==QUAD)
419 			*(short *)(regs[i+1]) = 0;
420 	}
421 	for (i=NREG; --i>=0;)
422 		if (regs[i][1]=='*' && equstr(s, regs[i]+2))
423 			*(short *)(regs[i]) = 0; /* previous indirection through destination is invalid */
424 	while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */
425 		*(short *)(regs[i]) = 0;
426 
427 	if (!natural(s)) {/* wild store, everything except constants vanishes */
428 		for (i=NREG; --i>=0;) if (regs[i][1] != '$') *(short *)(regs[i]) = 0;
429 		conloc[0] = 0; ccloc[0] = 0;
430 	} else {
431 		if(ccflg)setcc(s,type); /* natural destinations set condition codes */
432 		if (equstr(s, conloc))
433 			conloc[0] = 0;
434 	}
435 }
436 
437 splitrand(p) struct node *p; {
438 /* separate operands at commas, set up 'regs' and 'lastrand' */
439 register char *p1, *p2; register char **preg;
440 
441 	preg=regs+RT1;
442 	if (p1=p->code) while (*p1) {
443 		lastrand=p2= *preg++;
444 		while (*p1) if (','==(*p2++= *p1++)) {--p2; break;}
445 		*p2=0;
446 	}
447 	while (preg<(regs+RT1+5)) *(*preg++)=0;
448 }
449 
450 compat(have, want)
451 register int have, want;
452 {
453 	register int hsrc, hdst;
454 	extern int bitsize[];
455 
456 	if (0==(want &= 0xF)) return(1); /* anything satisfies a wildcard want */
457 	hsrc=have&0xF; if (0==(hdst=((have>>4)&0xF)) || hdst>=OP2) hdst=hsrc;
458 	if (want>=QUAD)
459 		return(bitsize[hdst]==bitsize[want] && bitsize[hsrc]==bitsize[want]);
460 	return(hsrc==want && hdst>=want && hdst<QUAD);
461 }
462 
463 equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));}
464 
465 findrand(as, type)
466 char *as;
467 {
468 	register char **i;
469 	for (i = regs+NREG; --i>=regs;) {
470 		if (**i && equstr(*i+1, as) && compat(**i,type))
471 			return(i-regs);
472 	}
473 	return(-1);
474 }
475 
476 isreg(s)
477 register char *s;
478 {
479 	if (*s++!='r' || !isdigit(*s++)) return(-1);
480 	if (*s==0) return(*--s-'0');
481 	if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'0');
482 	return(-1);
483 }
484 
485 /*
486 check()
487 {
488 	register struct node *p, *lp;
489 
490 	lp = &first;
491 	for (p=first.forw; p!=0; p = p->forw) {
492 		if (p->back != lp)
493 			abort(-1);
494 		lp = p;
495 	}
496 }
497 */
498 
499 newcode(p) struct node *p; {
500 	register char *p1,*p2,**preg;
501 
502 	preg=regs+RT1; p2=line;
503 	while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';}
504 	*--p2=0;
505 	p->code=copy(line);
506 }
507 
508 repladdr(p)
509 struct node *p;
510 {
511 	register int r;
512 	register char *p1;
513 	register char **preg;
514 	register int nrepl;
515 
516 	preg=regs+RT1; nrepl=0;
517 	while (lastrand!=(p1= *preg++))
518 		if (0<=(r=findrand(p1,p->subop))) {
519 			*p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0;
520 			nchange++; nrepl++; nsaddr++;
521 		}
522 	if (nrepl) newcode(p);
523 }
524 
525 /* conditional branches which are never/always taken */
526 reduncbr(p)
527 register struct node *p;
528 {
529 	register struct node *p1;
530 	register char *ap1, *ap2;
531 
532 	p1 = p->back;
533 	if (p1->op==CMP) {
534 		splitrand(p1);
535 		ap1 = findcon(regs[RT1], p1->subop);
536 		ap2 = findcon(regs[RT2], p1->subop);
537 	} else {
538 		if(!ccloc[0])
539 			return;
540 		ap1 = findcon(ccloc+1, ccloc[0]);
541 		ap2 = "$0";
542 	}
543 	switch (compare(p->subop, ap1, ap2)) {
544 	case 0:		/* branch never taken */
545 		delnode(p);
546 		nredunj++;
547 		nchange++;
548 		decref(p->ref);
549 		if(p->forw->op!=CBR && (p1->op==TST || p1->op==CMP)) {
550 			delnode(p1);
551 			nrtst++;
552 		}
553 		break;
554 	case 1:		/* branch always taken */
555 		p->op = JBR;
556 		p->subop = 0;
557 		p->pop = 0;
558 		nchange++;
559 		if(nonlab(p->ref)->op!=CBR && (p1->op==TST || p1->op==CMP)) {
560 			delnode(p1);
561 			nrtst++;
562 		}
563 	}
564 }
565 
566 /* a jump to a redundant compare (start of a 'for') */
567 redunbr(p)
568 register struct node *p;
569 {
570 	register struct node *p1;
571 	register char *ap1, *ap2;
572 
573 	if ((p1 = p->ref) == 0)
574 		return;
575 	p1 = nonlab(p1);
576 	if (p1->op==TST || p1->op==CMP)
577 		splitrand(p1);
578 	else
579 		return;
580 	if (p1->forw->op==CBR) {
581 		ap1 = findcon(regs[RT1], p1->subop);
582 		if (p1->op==TST)
583 			ap2 = "$0";
584 		else
585 			ap2 = findcon(regs[RT2], p1->subop);
586 		p1 = p1->forw;
587 		if (compare(p1->subop, ap1, ap2) > 0) {
588 			nredunj++;
589 			nchange++;
590 			decref(p->ref);
591 			p->ref = p1->ref;
592 			p->labno = p1->labno;
593 #ifdef COPYCODE
594 			if (p->labno == 0)
595 				p->code = p1->code;
596 			if (p->ref)
597 #endif
598 				p->ref->refc++;
599 		}
600 	} else if (p1->op==TST && equstr(regs[RT1],ccloc+1) &&
601 			equtype(ccloc[0],p1->subop)) {
602 		p1=insertl(p1->forw); decref(p->ref); p->ref=p1;
603 		nrtst++; nchange++;
604 	}
605 }
606 
607 char *
608 findcon(p, type)
609 	register char *p;
610 {
611 	register int r;
612 
613 	if (*p=='$')
614 		return(p);
615 	if ((r = isreg(p)) >= 0 && compat(regs[r][0],type))
616 		return(regs[r]+1);
617 	if (equstr(p, conloc) && equtype(conloc[0], type))
618 		return(conval+1);
619 	return(p);
620 }
621 
622 /* compare constants: 0 - branch taken; 1 - not taken; -1 - don't know */
623 compare(op, acp1, acp2)
624 char *acp1, *acp2;
625 {
626 	register char *cp1, *cp2;
627 	register int n1, n2, sign;
628 
629 	cp1 = acp1;
630 	cp2 = acp2;
631 	if (*cp1++ != '$' || *cp2++ != '$')
632 		return(-1);
633 	n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;}
634 	while (isdigit(*cp1)) {n1 *= 10; n1 += *cp1++ - '0';}
635 	n1 *= sign;
636 	n2 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;}
637 	while (isdigit(*cp2)) {n2 *= 10; n2 += *cp2++ - '0';}
638 	n2 *= sign;
639 	if (*cp1=='+')
640 		cp1++;
641 	if (*cp2=='+')
642 		cp2++;
643 	do {
644 		if (*cp1++ != *cp2)
645 			return(-1);
646 	} while (*cp2++);
647 	switch(op) {
648 
649 	case JEQ:
650 		return(n1 == n2);
651 	case JNE:
652 		return(n1 != n2);
653 	case JLE:
654 		return(n1 <= n2);
655 	case JGE:
656 		return(n1 >= n2);
657 	case JLT:
658 		return(n1 < n2);
659 	case JGT:
660 		return(n1 > n2);
661 	case JLO:
662 		return((unsigned)n1 < (unsigned)n2);
663 	case JHI:
664 		return((unsigned)n1 > (unsigned)n2);
665 	case JLOS:
666 		return((unsigned)n1 <= (unsigned)n2);
667 	case JHIS:
668 		return((unsigned)n1 >= (unsigned)n2);
669 	}
670 	return(-1);
671 }
672 
673 setcon(cv, cl, type)
674 register char *cv, *cl;
675 {
676 	register char *p;
677 
678 	if (*cv != '$')
679 		return;
680 	if (!natural(cl))
681 		return;
682 	p = conloc;
683 	while (*p++ = *cl++);
684 	p = conval;
685 	*p++ = type;
686 	while (*p++ = *cv++);
687 }
688 
689 setcc(ap,type)
690 char *ap;
691 {
692 	register char *p, *p1;
693 
694 	p = ap;
695 	if (!natural(p)) {
696 		ccloc[0] = 0;
697 		return;
698 	}
699 	p1 = ccloc;
700 	*p1++ = type;
701 	while (*p1++ = *p++);
702 }
703 
704 indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */
705 	while (*p) if (*p++=='[') return(1);
706 	return(0);
707 }
708 
709 natural(p)
710 register char *p;
711 {/* 1->simple local, parameter, global, or register; 0->otherwise */
712 
713 	if (*p=='*' || *p=='(' || *p=='$')
714 		return(0);
715 	while (*p++);
716 	p--;
717 	if (*--p==']' || *p==')' &&
718 	 !(*(p-2)=='f' || fortflg && (*--p=='1' || *p=='2') && *--p=='1'))
719 		return(0);
720 	return(1);
721 }
722 
723 /*
724 ** Tell if an argument is most likely static.
725 */
726 
727 isstatic(cp)
728 register char	*cp;
729 {
730 	if (*cp == '_' || *cp == 'L')
731 		return (1);
732 	return (0);
733 }
734 
735 
736 checkaobdisp(p)
737 register struct node *p;
738 {
739 register struct node *q;
740 register int i;
741 
742 
743 if (!aobflag) return(1);
744 /*  backward search */
745 	i = 0;
746 	q = p;
747 	while (i++ < MAXAOBDISP && ((q= q->back) !=&first))
748 	{
749 		if (p->ref == q)
750 		   return(1);
751 	}
752 
753 /*  forward search */
754 	i = 0;
755 	q = p;
756 	while (i++ < MAXAOBDISP && ((q= q->forw) !=0))
757 	{
758 		if (p->ref == q)
759 		   return(1);
760 	}
761 	return(0);
762 }
763 
764 
765 struct intleavetab intltab[] = {
766 	ADDF,	FLOAT,		1,
767 	ADDF,	DOUBLE,		1,
768 	SUBF,	FLOAT,		1,
769 	SUBF,	DOUBLE,		1,
770 	MULF,	FLOAT,		1,
771 	MULF,	DOUBLE,		1,
772 	DIVF,	FLOAT,		1,
773 	DIVF,	DOUBLE,		1,
774 	SINF,	FLOAT,		1,
775 	COSF,	FLOAT,		1,
776 	ATANF,	FLOAT,		1,
777 	LOGF,	FLOAT,		1,
778 	SQRTF,	FLOAT,		1,
779 	EXPF,	FLOAT,		1,
780 	LDF,	FLOAT,		0,
781 	LDF,	DOUBLE,		0,
782 	LNF,	FLOAT,		0,
783 	LNF,	DOUBLE,		0,
784 	STF,	FLOAT,		0,
785 	CMPF,	FLOAT,		0,
786 	CMPF,	DOUBLE,		0,
787 	CMPF2,	FLOAT,		0,
788 	TSTF,	FLOAT,		0,
789 	TSTF,	DOUBLE,		0,
790 	PUSHD,	DOUBLE,		0,
791 	CVLF,	U(LONG,FLOAT),	0,
792 	CVFL,	U(FLOAT,LONG),	0,
793 	LDFD,	U(FLOAT,DOUBLE),0,
794 	CVDF,	U(DOUBLE,FLOAT),0,
795 	NEGF,	FLOAT,		0,
796 	NIL,	0,		0};
797 
798 interleave()
799 {
800 	register struct node *p, *p1;
801 
802 	register struct intleavetab *t;
803 	register int r;
804 	int count;
805 	for (p= first.forw; p!=0; p = p->forw){
806 		count = 0;
807 		for  (t =intltab; t->op != NIL; t++){
808 			if (t->op == p->op && t->subop == p->subop){
809 			count = t->intleavect;
810 			break;
811 			}
812 		}
813 		if (count < 1) continue;
814 		p1 = p->forw;
815 		clearuse();
816 		clearreg();
817 		while ((p1 != 0) && (p1->op != CBR) &&
818 		      (p1->subop == FLOAT || p1->subop == DOUBLE ||
819 	              ((p1->subop&0xF0)==DOUBLE<<4) || ((p1->subop&0xF)==DOUBLE )||
820 	              ((p1->subop&0xF0)==FLOAT<<4) || (p1->subop&0xF)==FLOAT))
821 		{
822 			if (((r = isreg(p1->code)) >= 0)){
823 			uses[r] = p1;
824 			if ((p1->subop == DOUBLE) || ((p->subop&0xF0)==DOUBLE<<4) ||
825 		           ((p->subop&0xF)==DOUBLE))
826 				uses[r+1] = p1;
827 			}
828 			else checkreg(p1,p1->code);
829 			p1 = p1->forw;
830 
831 		}
832 		if (p1 == 0) return;
833 		if (!(sideeffect(p, p1)))
834 			insertblk(p,p1);
835 	}
836 
837 }
838 
839 
840 insertblk(p, p1)
841 struct node *p, *p1;
842 {
843 	p1->back->forw = p1->forw;
844 	p1->forw->back = p1->back;
845 	p1->forw = p->forw;
846 	p->forw->back = p1;
847 	p->forw = p1;
848 	p1->back = p;
849 }
850 
851 OpCode termop[] = {
852 	JBR, CBR, JMP, LABEL, DLABEL, EROU, JSW, TST, CMP, BIT,
853 	CALLF, CALLS, CASE, AOBLEQ, AOBLSS, CMPF, CMPF2, TSTF, MOVBLK, MFPR,
854 	MTPR, PROBE, MOVO, TEXT, DATA, BSS, ALIGN, END, LGEN, SET,
855 	LCOMM, COMM, NIL
856 };
857 
858 sideeffect(p,p1)
859 struct node *p, *p1;
860 {
861 	register struct node *q;
862 	register int r;
863 	register OpCode *t;
864 	register char *cp;
865 	int i;
866 
867 	if (p1->op == NIL) return(1);  /*  special instructions */
868 
869 	for (t = termop; *t!=NIL; t++){
870 		if (*t == p1->op) return(1);
871 	}
872 	if ((p1->forw != NULL) && (p1->forw->op == CBR))
873 		return(1);
874 	splitrand(p1);
875 	r = isreg(lastrand);
876 	if (uses[r] &&  r >= 0 ) return(1);
877 	if ((p1->op == EDIV) && (r = isreg(regs[RT3]) >= 0) &&
878 	   (uses[r]))  return(1);
879 
880 	for (q = p1->back ; q!=p; q=q->back)
881 	{
882 		if ((p1->op == PUSH || p1->op == PUSHA) &&
883 		    (q->op == PUSHD || q->op == PUSH || q->op == PUSHA))
884 		     return(1); 		     /* keep args in order */
885 		if (((i = strlen(q->code)) >= 5 &&    /* cvdl -(sp); pushl r0*/
886 		    (strcmp(q->code+i-5,"-(sp)") == 0 )) ||
887 		    (strcmp(lastrand,"-(sp)") == 0)) return(1);
888 		if (equstr(q->code, lastrand))
889 		    return(1);
890 		if (q->op == STF || q->op == CVFL || q->op == CVLF)
891 		   {
892 		    if (equstr(q->code, regs[RT1])) return(1);
893 		if (has3ops(p1) || p1->op == EMUL || p1->op == EDIV)
894 		    if (equstr(q->code, regs[RT2]))
895 		       return(1);
896 		/*  handle the case  std -56(fp) pushl -60(fp) pushl
897 		    -56(fp);
898 		*/
899 		if ((p1->forw != NULL) &&  (q->op == STF) &&
900 		(q->subop == DOUBLE)){
901 		if (!strncmp(q->code,p1->forw->code,strlen(q->code)))
902 			return(1);
903 		}
904 		}
905 	}
906 	return(0);
907 }
908 checkreg(p,s)
909 struct node *p;
910 char *s;
911 {
912 char *cp2;
913 register int r;
914 	/* check for (r),[r] */
915 	do if (*s=='(' || *s=='[') {/* get register number */
916 		char t;
917 		cp2= ++s; while (*++s!=')' && *s!=']'); t= *s; *s=0;
918 		if ((r=isreg(cp2)) >= 0)  {
919 			uses[r]=p;
920 		}
921 		*s=t;
922 	} while (*++s);
923 }
924