xref: /original-bsd/old/pcc/c2.tahoe/c22.c (revision 241757c4)
1 #ifndef lint
2 static char sccsid[] = "@(#)c22.c	1.9 (Berkeley/CCI) 05/12/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, p->op!=CVT || r<0);
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 		p->labno=p1->labno;
604 		nrtst++; nchange++;
605 	}
606 }
607 
608 char *
609 findcon(p, type)
610 	register char *p;
611 {
612 	register int r;
613 
614 	if (*p=='$')
615 		return(p);
616 	if ((r = isreg(p)) >= 0 && compat(regs[r][0],type))
617 		return(regs[r]+1);
618 	if (equstr(p, conloc) && equtype(conloc[0], type))
619 		return(conval+1);
620 	return(p);
621 }
622 
623 /* compare constants: 0 - branch taken; 1 - not taken; -1 - don't know */
624 compare(op, acp1, acp2)
625 char *acp1, *acp2;
626 {
627 	register char *cp1, *cp2;
628 	register int n1, n2, sign;
629 
630 	cp1 = acp1;
631 	cp2 = acp2;
632 	if (*cp1++ != '$' || *cp2++ != '$')
633 		return(-1);
634 	n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;}
635 	while (isdigit(*cp1)) {n1 *= 10; n1 += *cp1++ - '0';}
636 	n1 *= sign;
637 	n2 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;}
638 	while (isdigit(*cp2)) {n2 *= 10; n2 += *cp2++ - '0';}
639 	n2 *= sign;
640 	if (*cp1=='+')
641 		cp1++;
642 	if (*cp2=='+')
643 		cp2++;
644 	do {
645 		if (*cp1++ != *cp2)
646 			return(-1);
647 	} while (*cp2++);
648 	switch(op) {
649 
650 	case JEQ:
651 		return(n1 == n2);
652 	case JNE:
653 		return(n1 != n2);
654 	case JLE:
655 		return(n1 <= n2);
656 	case JGE:
657 		return(n1 >= n2);
658 	case JLT:
659 		return(n1 < n2);
660 	case JGT:
661 		return(n1 > n2);
662 	case JLO:
663 		return((unsigned)n1 < (unsigned)n2);
664 	case JHI:
665 		return((unsigned)n1 > (unsigned)n2);
666 	case JLOS:
667 		return((unsigned)n1 <= (unsigned)n2);
668 	case JHIS:
669 		return((unsigned)n1 >= (unsigned)n2);
670 	}
671 	return(-1);
672 }
673 
674 setcon(cv, cl, type)
675 register char *cv, *cl;
676 {
677 	register char *p;
678 
679 	if (*cv != '$')
680 		return;
681 	if (!natural(cl))
682 		return;
683 	p = conloc;
684 	while (*p++ = *cl++);
685 	p = conval;
686 	*p++ = type;
687 	while (*p++ = *cv++);
688 }
689 
690 setcc(ap,type)
691 char *ap;
692 {
693 	register char *p, *p1;
694 
695 	p = ap;
696 	if (!natural(p)) {
697 		ccloc[0] = 0;
698 		return;
699 	}
700 	p1 = ccloc;
701 	*p1++ = type;
702 	while (*p1++ = *p++);
703 }
704 
705 indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */
706 	while (*p) if (*p++=='[') return(1);
707 	return(0);
708 }
709 
710 natural(p)
711 register char *p;
712 {/* 1->simple local, parameter, global, or register; 0->otherwise */
713 
714 	if (*p=='*' || *p=='(' || *p=='$')
715 		return(0);
716 	while (*p++);
717 	p--;
718 	if (*--p==']' || *p==')' &&
719 	 !(*(p-2)=='f' || fortflg && (*--p=='1' || *p=='2') && *--p=='1'))
720 		return(0);
721 	return(1);
722 }
723 
724 /*
725 ** Tell if an argument is most likely static.
726 */
727 
728 isstatic(cp)
729 register char	*cp;
730 {
731 	if (*cp == '_' || *cp == 'L')
732 		return (1);
733 	return (0);
734 }
735 
736 
737 checkaobdisp(p)
738 register struct node *p;
739 {
740 register struct node *q;
741 register int i;
742 
743 
744 if (!aobflag) return(1);
745 /*  backward search */
746 	i = 0;
747 	q = p;
748 	while (i++ < MAXAOBDISP && ((q= q->back) !=&first))
749 	{
750 		if (p->ref == q)
751 		   return(1);
752 	}
753 
754 /*  forward search */
755 	i = 0;
756 	q = p;
757 	while (i++ < MAXAOBDISP && ((q= q->forw) !=0))
758 	{
759 		if (p->ref == q)
760 		   return(1);
761 	}
762 	return(0);
763 }
764 
765 
766 struct intleavetab intltab[] = {
767 	ADDF,	FLOAT,		1,
768 	ADDF,	DOUBLE,		1,
769 	SUBF,	FLOAT,		1,
770 	SUBF,	DOUBLE,		1,
771 	MULF,	FLOAT,		1,
772 	MULF,	DOUBLE,		1,
773 	DIVF,	FLOAT,		1,
774 	DIVF,	DOUBLE,		1,
775 	SINF,	FLOAT,		1,
776 	COSF,	FLOAT,		1,
777 	ATANF,	FLOAT,		1,
778 	LOGF,	FLOAT,		1,
779 	SQRTF,	FLOAT,		1,
780 	EXPF,	FLOAT,		1,
781 	LDF,	FLOAT,		0,
782 	LDF,	DOUBLE,		0,
783 	LNF,	FLOAT,		0,
784 	LNF,	DOUBLE,		0,
785 	STF,	FLOAT,		0,
786 	CMPF,	FLOAT,		0,
787 	CMPF,	DOUBLE,		0,
788 	CMPF2,	FLOAT,		0,
789 	TSTF,	FLOAT,		0,
790 	TSTF,	DOUBLE,		0,
791 	PUSHD,	DOUBLE,		0,
792 	CVLF,	U(LONG,FLOAT),	0,
793 	CVFL,	U(FLOAT,LONG),	0,
794 	LDFD,	U(FLOAT,DOUBLE),0,
795 	CVDF,	U(DOUBLE,FLOAT),0,
796 	NEGF,	FLOAT,		0,
797 	NIL,	0,		0};
798 
799 interleave()
800 {
801 	register struct node *p, *p1;
802 
803 	register struct intleavetab *t;
804 	register int r;
805 	int count;
806 	for (p= first.forw; p!=0; p = p->forw){
807 		count = 0;
808 		for  (t =intltab; t->op != NIL; t++){
809 			if (t->op == p->op && t->subop == p->subop){
810 			count = t->intleavect;
811 			break;
812 			}
813 		}
814 		if (count < 1) continue;
815 		p1 = p->forw;
816 		clearuse();
817 		clearreg();
818 		while ((p1 != 0) && (p1->op != CBR) &&
819 		      (p1->subop == FLOAT || p1->subop == DOUBLE ||
820 	              ((p1->subop&0xF0)==DOUBLE<<4) || ((p1->subop&0xF)==DOUBLE )||
821 	              ((p1->subop&0xF0)==FLOAT<<4) || (p1->subop&0xF)==FLOAT))
822 		{
823 			if (((r = isreg(p1->code)) >= 0)){
824 			uses[r] = p1;
825 			if ((p1->subop == DOUBLE) || ((p->subop&0xF0)==DOUBLE<<4) ||
826 		           ((p->subop&0xF)==DOUBLE))
827 				uses[r+1] = p1;
828 			}
829 			else checkreg(p1,p1->code);
830 			p1 = p1->forw;
831 
832 		}
833 		if (p1 == 0) return;
834 		if (!(sideeffect(p, p1)))
835 			insertblk(p,p1);
836 	}
837 
838 }
839 
840 
841 insertblk(p, p1)
842 struct node *p, *p1;
843 {
844 	p1->back->forw = p1->forw;
845 	p1->forw->back = p1->back;
846 	p1->forw = p->forw;
847 	p->forw->back = p1;
848 	p->forw = p1;
849 	p1->back = p;
850 }
851 
852 OpCode termop[] = {
853 	JBR, CBR, JMP, LABEL, DLABEL, EROU, JSW, TST, CMP, BIT,
854 	CALLF, CALLS, CASE, AOBLEQ, AOBLSS, CMPF, CMPF2, TSTF, MOVBLK, MFPR,
855 	MTPR, PROBE, MOVO, TEXT, DATA, BSS, ALIGN, END, LGEN, SET,
856 	LCOMM, COMM, NIL
857 };
858 
859 sideeffect(p,p1)
860 struct node *p, *p1;
861 {
862 	register struct node *q;
863 	register int r;
864 	register OpCode *t;
865 	register char *cp;
866 	int i;
867 
868 	if (p1->op == NIL) return(1);  /*  special instructions */
869 
870 	for (t = termop; *t!=NIL; t++){
871 		if (*t == p1->op) return(1);
872 	}
873 	if ((p1->forw != NULL) && (p1->forw->op == CBR))
874 		return(1);
875 	splitrand(p1);
876 	r = isreg(lastrand);
877 	if (uses[r] &&  r >= 0 ) return(1);
878 	if ((p1->op == EDIV) && (r = isreg(regs[RT3]) >= 0) &&
879 	   (uses[r]))  return(1);
880 
881 	for (q = p1->back ; q!=p; q=q->back)
882 	{
883 		if ((p1->op == PUSH || p1->op == PUSHA) &&
884 		    (q->op == PUSHD || q->op == PUSH || q->op == PUSHA))
885 		     return(1); 		     /* keep args in order */
886 		if (((i = strlen(q->code)) >= 5 &&    /* cvdl -(sp); pushl r0*/
887 		    (strcmp(q->code+i-5,"-(sp)") == 0 )) ||
888 		    (strcmp(lastrand,"-(sp)") == 0)) return(1);
889 		if (equstr(q->code, lastrand))
890 		    return(1);
891 		if (q->op == STF || q->op == CVFL || q->op == CVLF)
892 		   {
893 		    if (equstr(q->code, regs[RT1])) return(1);
894 		if (has3ops(p1) || p1->op == EMUL || p1->op == EDIV)
895 		    if (equstr(q->code, regs[RT2]))
896 		       return(1);
897 		/*  handle the case  std -56(fp) pushl -60(fp) pushl
898 		    -56(fp);
899 		*/
900 		if ((p1->forw != NULL) &&  (q->op == STF) &&
901 		(q->subop == DOUBLE)){
902 		if (!strncmp(q->code,p1->forw->code,strlen(q->code)))
903 			return(1);
904 		}
905 		}
906 	}
907 	return(0);
908 }
909 checkreg(p,s)
910 struct node *p;
911 char *s;
912 {
913 char *cp2;
914 register int r;
915 	/* check for (r),[r] */
916 	do if (*s=='(' || *s=='[') {/* get register number */
917 		char t;
918 		cp2= ++s; while (*++s!=')' && *s!=']'); t= *s; *s=0;
919 		if ((r=isreg(cp2)) >= 0)  {
920 			uses[r]=p;
921 		}
922 		*s=t;
923 	} while (*++s);
924 }
925