Research V7 development
[unix-history] / usr / src / cmd / c / c21.c
CommitLineData
3823a6ae
DR
1#
2/*
3 * C object code improver-- second part
4 */
5
6#include "c2.h"
7
8rmove()
9{
10 register struct node *p;
11 register int r;
12 register r1, flt;
13
14 for (p=first.forw; p!=0; p = p->forw) {
15 flt = 0;
16 switch (p->op) {
17
18 case MOVF:
19 case MOVFO:
20 case MOVOF:
21 flt = NREG;
22
23 case MOV:
24 if (p->subop==BYTE)
25 goto dble;
26 dualop(p);
27 if ((r = findrand(regs[RT1], flt)) >= 0) {
28 if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR
29 && p->forw->op!=SXT
30 && p->forw->op!=CFCC) {
31 p->forw->back = p->back;
32 p->back->forw = p->forw;
33 redunm++;
34 continue;
35 }
36 }
37 if (equstr(regs[RT1], "$0")) {
38 p->op = CLR;
39 strcpy(regs[RT1], regs[RT2]);
40 regs[RT2][0] = 0;
41 p->code = copy(1, regs[RT1]);
42 goto sngl;
43 }
44 repladdr(p, 0, flt);
45 r = isreg(regs[RT1]);
46 r1 = isreg(regs[RT2]);
47 dest(regs[RT2], flt);
48 if (r >= 0)
49 if (r1 >= 0)
50 savereg(r1+flt, regs[r+flt]);
51 else
52 savereg(r+flt, regs[RT2]);
53 else
54 if (r1 >= 0)
55 savereg(r1+flt, regs[RT1]);
56 else
57 setcon(regs[RT1], regs[RT2]);
58 source(regs[RT1]);
59 setcc(regs[RT2]);
60 continue;
61
62 case ADDF:
63 case SUBF:
64 case DIVF:
65 case MULF:
66 flt = NREG;
67 goto dble;
68
69 case ADD:
70 case SUB:
71 case BIC:
72 case BIS:
73 case MUL:
74 case DIV:
75 case ASH:
76 dble:
77 dualop(p);
78 if (p->op==BIC && (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777"))) {
79 p->op = CLR;
80 strcpy(regs[RT1], regs[RT2]);
81 regs[RT2][0] = 0;
82 p->code = copy(1, regs[RT1]);
83 goto sngl;
84 }
85 if ((p->op==BIC || p->op==BIS) && equstr(regs[RT1], "$0")) {
86 if (p->forw->op!=CBR) {
87 p->back->forw = p->forw;
88 p->forw->back = p->back;
89 continue;
90 }
91 }
92 repladdr(p, 0, flt);
93 source(regs[RT1]);
94 dest(regs[RT2], flt);
95 if (p->op==DIV && (r = isreg(regs[RT2])>=0))
96 regs[r+1][0] = 0;
97 ccloc[0] = 0;
98 continue;
99
100 case CLRF:
101 case NEGF:
102 flt = NREG;
103
104 case CLR:
105 case COM:
106 case INC:
107 case DEC:
108 case NEG:
109 case ASR:
110 case ASL:
111 case SXT:
112 singop(p);
113 sngl:
114 dest(regs[RT1], flt);
115 if (p->op==CLR && flt==0)
116 if ((r = isreg(regs[RT1])) >= 0)
117 savereg(r, "$0");
118 else
119 setcon("$0", regs[RT1]);
120 ccloc[0] = 0;
121 continue;
122
123 case TSTF:
124 flt = NREG;
125
126 case TST:
127 singop(p);
128 repladdr(p, 0, flt);
129 source(regs[RT1]);
130 if (equstr(regs[RT1], ccloc)) {
131 p->back->forw = p->forw;
132 p->forw->back = p->back;
133 p = p->back;
134 nrtst++;
135 nchange++;
136 }
137 continue;
138
139 case CMPF:
140 flt = NREG;
141
142 case CMP:
143 case BIT:
144 dualop(p);
145 source(regs[RT1]);
146 source(regs[RT2]);
147 if(p->op==BIT) {
148 if (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777")) {
149 p->op = TST;
150 strcpy(regs[RT1], regs[RT2]);
151 regs[RT2][0] = 0;
152 p->code = copy(1, regs[RT1]);
153 nchange++;
154 nsaddr++;
155 } else if (equstr(regs[RT2], "$-1") || equstr(regs[RT2], "$177777")) {
156 p->op = TST;
157 regs[RT2][0] = 0;
158 p->code = copy(1, regs[RT1]);
159 nchange++;
160 nsaddr++;
161 }
162 if (equstr(regs[RT1], "$0")) {
163 p->op = TST;
164 regs[RT2][0] = 0;
165 p->code = copy(1, regs[RT1]);
166 nchange++;
167 nsaddr++;
168 } else if (equstr(regs[RT2], "$0")) {
169 p->op = TST;
170 strcpy(regs[RT1], regs[RT2]);
171 regs[RT2][0] = 0;
172 p->code = copy(1, regs[RT1]);
173 nchange++;
174 nsaddr++;
175 }
176 }
177 repladdr(p, 1, flt);
178 ccloc[0] = 0;
179 continue;
180
181 case CBR:
182 if (p->back->op==TST || p->back->op==CMP) {
183 if (p->back->op==TST) {
184 singop(p->back);
185 savereg(RT2, "$0");
186 } else
187 dualop(p->back);
188 r = compare(p->subop, findcon(RT1), findcon(RT2));
189 if (r==0) {
190 p->back->back->forw = p->forw;
191 p->forw->back = p->back->back;
192 decref(p->ref);
193 p = p->back->back;
194 nchange++;
195 } else if (r>0) {
196 p->op = JBR;
197 p->subop = 0;
198 p->back->back->forw = p;
199 p->back = p->back->back;
200 p = p->back;
201 nchange++;
202 }
203 }
204 case CFCC:
205 ccloc[0] = 0;
206 continue;
207
208 case JBR:
209 redunbr(p);
210
211 default:
212 clearreg();
213 }
214 }
215}
216
217jumpsw()
218{
219 register struct node *p, *p1;
220 register t;
221 register struct node *tp;
222 int nj;
223
224 t = 0;
225 nj = 0;
226 for (p=first.forw; p!=0; p = p->forw)
227 p->refc = ++t;
228 for (p=first.forw; p!=0; p = p1) {
229 p1 = p->forw;
230 if (p->op == CBR && p1->op==JBR && p->ref && p1->ref
231 && abs(p->refc - p->ref->refc) > abs(p1->refc - p1->ref->refc)) {
232 if (p->ref==p1->ref)
233 continue;
234 p->subop = revbr[p->subop];
235 tp = p1->ref;
236 p1->ref = p->ref;
237 p->ref = tp;
238 t = p1->labno;
239 p1->labno = p->labno;
240 p->labno = t;
241 nrevbr++;
242 nj++;
243 }
244 }
245 return(nj);
246}
247
248addsob()
249{
250 register struct node *p, *p1;
251
252 for (p = &first; (p1 = p->forw)!=0; p = p1) {
253 if (p->op==DEC && isreg(p->code)>=0
254 && p1->op==CBR && p1->subop==JNE) {
255 if (p->refc < p1->ref->refc)
256 continue;
257 if (toofar(p1))
258 continue;
259 p->labno = p1->labno;
260 p->op = SOB;
261 p->subop = 0;
262 p1->forw->back = p;
263 p->forw = p1->forw;
264 nsob++;
265 }
266 }
267}
268
269toofar(p)
270struct node *p;
271{
272 register struct node *p1;
273 int len;
274
275 len = 0;
276 for (p1 = p->ref; p1 && p1!=p; p1 = p1->forw)
277 len += ilen(p1);
278 if (len < 128)
279 return(0);
280 return(1);
281}
282
283ilen(p)
284register struct node *p;
285{
286 register l;
287
288 switch (p->op) {
289 case LABEL:
290 case DLABEL:
291 case TEXT:
292 case EROU:
293 case EVEN:
294 return(0);
295
296 case CBR:
297 return(6);
298
299 default:
300 dualop(p);
301 return(2 + adrlen(regs[RT1]) + adrlen(regs[RT2]));
302 }
303}
304
305adrlen(s)
306register char *s;
307{
308 if (*s == 0)
309 return(0);
310 if (*s=='r')
311 return(0);
312 if (*s=='(' && *(s+1)=='r')
313 return(0);
314 if (*s=='-' && *(s+1)=='(')
315 return(0);
316 return(2);
317}
318
319abs(x)
320{
321 return(x<0? -x: x);
322}
323
324equop(ap1, p2)
325struct node *ap1, *p2;
326{
327 register char *cp1, *cp2;
328 register struct node *p1;
329
330 p1 = ap1;
331 if (p1->op!=p2->op || p1->subop!=p2->subop)
332 return(0);
333 if (p1->op>0 && p1->op<MOV)
334 return(0);
335 cp1 = p1->code;
336 cp2 = p2->code;
337 if (cp1==0 && cp2==0)
338 return(1);
339 if (cp1==0 || cp2==0)
340 return(0);
341 while (*cp1 == *cp2++)
342 if (*cp1++ == 0)
343 return(1);
344 return(0);
345}
346
347decref(p)
348register struct node *p;
349{
350 if (--p->refc <= 0) {
351 nrlab++;
352 p->back->forw = p->forw;
353 p->forw->back = p->back;
354 }
355}
356
357struct node *
358nonlab(p)
359struct node *p;
360{
361 while (p && p->op==LABEL)
362 p = p->forw;
363 return(p);
364}
365
366char *
367alloc(n)
368register n;
369{
370 register char *p;
371
372 n++;
373 n &= ~01;
374 if (lasta+n >= lastr) {
375 if (sbrk(2000) == (char *)-1) {
376 fprintf(stderr, "C Optimizer: out of space\n");
377 exit(1);
378 }
379 lastr += 2000;
380 }
381 p = lasta;
382 lasta += n;
383 return(p);
384}
385
386clearreg()
387{
388 register int i;
389
390 for (i=0; i<2*NREG; i++)
391 regs[i][0] = '\0';
392 conloc[0] = 0;
393 ccloc[0] = 0;
394}
395
396savereg(ai, as)
397char *as;
398{
399 register char *p, *s, *sp;
400
401 sp = p = regs[ai];
402 s = as;
403 if (source(s))
404 return;
405 while (*p++ = *s) {
406 if (s[0]=='(' && s[1]=='r' && s[2]<'5') {
407 *sp = 0;
408 return;
409 }
410 if (*s++ == ',')
411 break;
412 }
413 *--p = '\0';
414}
415
416dest(as, flt)
417char *as;
418{
419 register char *s;
420 register int i;
421
422 s = as;
423 source(s);
424 if ((i = isreg(s)) >= 0)
425 regs[i+flt][0] = 0;
426 for (i=0; i<NREG+NREG; i++)
427 if (*regs[i]=='*' && equstr(s, regs[i]+1))
428 regs[i][0] = 0;
429 while ((i = findrand(s, flt)) >= 0)
430 regs[i][0] = 0;
431 while (*s) {
432 if ((*s=='(' && (*(s+1)!='r' || *(s+2)!='5')) || *s++=='*') {
433 for (i=0; i<NREG+NREG; i++) {
434 if (regs[i][0] != '$')
435 regs[i][0] = 0;
436 conloc[0] = 0;
437 }
438 return;
439 }
440 }
441}
442
443singop(ap)
444struct node *ap;
445{
446 register char *p1, *p2;
447
448 p1 = ap->code;
449 p2 = regs[RT1];
450 while (*p2++ = *p1++);
451 regs[RT2][0] = 0;
452}
453
454
455dualop(ap)
456struct node *ap;
457{
458 register char *p1, *p2;
459 register struct node *p;
460
461 p = ap;
462 p1 = p->code;
463 p2 = regs[RT1];
464 while (*p1 && *p1!=',')
465 *p2++ = *p1++;
466 *p2++ = 0;
467 p2 = regs[RT2];
468 *p2 = 0;
469 if (*p1++ !=',')
470 return;
471 while (*p2++ = *p1++);
472}
473
474findrand(as, flt)
475char *as;
476{
477 register int i;
478 for (i = flt; i<NREG+flt; i++) {
479 if (equstr(regs[i], as))
480 return(i);
481 }
482 return(-1);
483}
484
485isreg(as)
486char *as;
487{
488 register char *s;
489
490 s = as;
491 if (s[0]=='r' && s[1]>='0' && s[1]<='4' && s[2]==0)
492 return(s[1]-'0');
493 return(-1);
494}
495
496check()
497{
498 register struct node *p, *lp;
499
500 lp = &first;
501 for (p=first.forw; p!=0; p = p->forw) {
502 if (p->back != lp)
503 abort();
504 lp = p;
505 }
506}
507
508source(ap)
509char *ap;
510{
511 register char *p1, *p2;
512
513 p1 = ap;
514 p2 = p1;
515 if (*p1==0)
516 return(0);
517 while (*p2++);
518 if (*p1=='-' && *(p1+1)=='('
519 || *p1=='*' && *(p1+1)=='-' && *(p1+2)=='('
520 || *(p2-2)=='+') {
521 while (*p1 && *p1++!='r');
522 if (*p1>='0' && *p1<='4')
523 regs[*p1 - '0'][0] = 0;
524 return(1);
525 }
526 return(0);
527}
528
529repladdr(p, f, flt)
530struct node *p;
531{
532 register r;
533 int r1;
534 register char *p1, *p2;
535 static char rt1[50], rt2[50];
536
537 if (f)
538 r1 = findrand(regs[RT2], flt);
539 else
540 r1 = -1;
541 r = findrand(regs[RT1], flt);
542 if (r1 >= NREG)
543 r1 -= NREG;
544 if (r >= NREG)
545 r -= NREG;
546 if (r>=0 || r1>=0) {
547 p2 = regs[RT1];
548 for (p1 = rt1; *p1++ = *p2++;);
549 if (regs[RT2][0]) {
550 p1 = rt2;
551 *p1++ = ',';
552 for (p2 = regs[RT2]; *p1++ = *p2++;);
553 } else
554 rt2[0] = 0;
555 if (r>=0) {
556 rt1[0] = 'r';
557 rt1[1] = r + '0';
558 rt1[2] = 0;
559 nsaddr++;
560 }
561 if (r1>=0) {
562 rt2[1] = 'r';
563 rt2[2] = r1 + '0';
564 rt2[3] = 0;
565 nsaddr++;
566 }
567 p->code = copy(2, rt1, rt2);
568 }
569}
570
571movedat()
572{
573 register struct node *p1, *p2;
574 struct node *p3;
575 register seg;
576 struct node data;
577 struct node *datp;
578
579 if (first.forw == 0)
580 return;
581 if (lastseg != TEXT && lastseg != -1) {
582 p1 = (struct node *)alloc(sizeof(first));
583 p1->op = lastseg;
584 p1->subop = 0;
585 p1->code = NULL;
586 p1->forw = first.forw;
587 p1->back = &first;
588 first.forw->back = p1;
589 first.forw = p1;
590 }
591 datp = &data;
592 for (p1 = first.forw; p1!=0; p1 = p1->forw) {
593 if (p1->op == DATA) {
594 p2 = p1->forw;
595 while (p2 && p2->op!=TEXT)
596 p2 = p2->forw;
597 if (p2==0)
598 break;
599 p3 = p1->back;
600 p1->back->forw = p2->forw;
601 p2->forw->back = p3;
602 p2->forw = 0;
603 datp->forw = p1;
604 p1->back = datp;
605 p1 = p3;
606 datp = p2;
607 }
608 }
609 if (data.forw) {
610 datp->forw = first.forw;
611 first.forw->back = datp;
612 data.forw->back = &first;
613 first.forw = data.forw;
614 }
615 seg = lastseg;
616 for (p1 = first.forw; p1!=0; p1 = p1->forw) {
617 if (p1->op==TEXT||p1->op==DATA||p1->op==BSS) {
618 if (p2 = p1->forw) {
619 if (p2->op==TEXT||p2->op==DATA||p2->op==BSS)
620 p1->op = p2->op;
621 }
622 if (p1->op == seg || p1->forw&&p1->forw->op==seg) {
623 p1->back->forw = p1->forw;
624 p1->forw->back = p1->back;
625 p1 = p1->back;
626 continue;
627 }
628 seg = p1->op;
629 }
630 }
631}
632
633redunbr(p)
634register struct node *p;
635{
636 register struct node *p1;
637 register char *ap1;
638 char *ap2;
639
640 if ((p1 = p->ref) == 0)
641 return;
642 p1 = nonlab(p1);
643 if (p1->op==TST) {
644 singop(p1);
645 savereg(RT2, "$0");
646 } else if (p1->op==CMP)
647 dualop(p1);
648 else
649 return;
650 if (p1->forw->op!=CBR)
651 return;
652 ap1 = findcon(RT1);
653 ap2 = findcon(RT2);
654 p1 = p1->forw;
655 if (compare(p1->subop, ap1, ap2)>0) {
656 nredunj++;
657 nchange++;
658 decref(p->ref);
659 p->ref = p1->ref;
660 p->labno = p1->labno;
661 p->ref->refc++;
662 }
663}
664
665char *
666findcon(i)
667{
668 register char *p;
669 register r;
670
671 p = regs[i];
672 if (*p=='$')
673 return(p);
674 if ((r = isreg(p)) >= 0)
675 return(regs[r]);
676 if (equstr(p, conloc))
677 return(conval);
678 return(p);
679}
680
681compare(oper, cp1, cp2)
682register char *cp1, *cp2;
683{
684 register unsigned n1, n2;
685
686 if (*cp1++ != '$' || *cp2++ != '$')
687 return(-1);
688 n1 = 0;
689 while (*cp2 >= '0' && *cp2 <= '7') {
690 n1 <<= 3;
691 n1 += *cp2++ - '0';
692 }
693 n2 = n1;
694 n1 = 0;
695 while (*cp1 >= '0' && *cp1 <= '7') {
696 n1 <<= 3;
697 n1 += *cp1++ - '0';
698 }
699 if (*cp1=='+')
700 cp1++;
701 if (*cp2=='+')
702 cp2++;
703 do {
704 if (*cp1++ != *cp2)
705 return(-1);
706 } while (*cp2++);
707 switch(oper) {
708
709 case JEQ:
710 return(n1 == n2);
711 case JNE:
712 return(n1 != n2);
713 case JLE:
714 return((int)n1 <= (int)n2);
715 case JGE:
716 return((int)n1 >= (int)n2);
717 case JLT:
718 return((int)n1 < (int)n2);
719 case JGT:
720 return((int)n1 > (int)n2);
721 case JLO:
722 return(n1 < n2);
723 case JHI:
724 return(n1 > n2);
725 case JLOS:
726 return(n1 <= n2);
727 case JHIS:
728 return(n1 >= n2);
729 }
730 return(-1);
731}
732
733setcon(ar1, ar2)
734char *ar1, *ar2;
735{
736 register char *cl, *cv, *p;
737
738 cl = ar2;
739 cv = ar1;
740 if (*cv != '$')
741 return;
742 if (!natural(cl))
743 return;
744 p = conloc;
745 while (*p++ = *cl++);
746 p = conval;
747 while (*p++ = *cv++);
748}
749
750equstr(ap1, ap2)
751char *ap1, *ap2;
752{
753 char *p1, *p2;
754
755 p1 = ap1;
756 p2 = ap2;
757 do {
758 if (*p1++ != *p2)
759 return(0);
760 } while (*p2++);
761 return(1);
762}
763
764setcc(ap)
765char *ap;
766{
767 register char *p, *p1;
768
769 p = ap;
770 if (!natural(p)) {
771 ccloc[0] = 0;
772 return;
773 }
774 p1 = ccloc;
775 while (*p1++ = *p++);
776}
777
778natural(ap)
779char *ap;
780{
781 register char *p;
782
783 p = ap;
784 if (*p=='*' || *p=='(' || *p=='-'&&*(p+1)=='(')
785 return(0);
786 while (*p++);
787 p--;
788 if (*--p == '+' || *p ==')' && *--p != '5')
789 return(0);
790 return(1);
791}