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