|
|
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: #define NUSE 6
10: struct node *uses[NUSE]; /* for backwards flow analysis */
11: char *lastrand; /* last operand of instruction */
12: char *findcon();
13:
14: ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */
15: register int log;
16: if (n==0 || n&(n-1)) return(-1); log=0;
17: for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);}
18: }
19:
20: equop(p1, p2)
21: register struct node *p1, *p2;
22: {
23: register char *cp1, *cp2;
24:
25: if (p1->op != p2->op || p1->subop != p2->subop)
26: return(0);
27: if (p1->op>0 && p1->op<MOV)
28: return(0);
29: if (p1->op==MOVA && p1->labno!=p2->labno) return(0);
30: cp1 = p1->code;
31: cp2 = p2->code;
32: if (cp1==0 && cp2==0)
33: return(1);
34: if (cp1==0 || cp2==0)
35: return(0);
36: while (*cp1 == *cp2++)
37: if (*cp1++ == 0)
38: return(1);
39: return(0);
40: }
41:
42: delnode(p) register struct node *p; {
43: p->back->forw = p->forw;
44: p->forw->back = p->back;
45: }
46:
47: decref(p)
48: register struct node *p;
49: {
50: if (p && --p->refc <= 0) {
51: nrlab++; nchange++;
52: delnode(p);
53: }
54: }
55:
56: struct node *
57: nonlab(ap)
58: struct node *ap;
59: {
60: register struct node *p;
61:
62: p = ap;
63: while (p && p->op==LABEL)
64: p = p->forw;
65: return(p);
66: }
67:
68: clearuse() {
69: register struct node **i;
70: for (i=uses+NUSE; i>uses;) *--i=0;
71: }
72:
73: clearreg() {
74: register char **i;
75: for (i=regs+NREG; i>regs;){ **--i=0; **i=0; }
76: conloc[0] = 0; ccloc[0] = 0;
77: }
78:
79: savereg(ai, s, type)
80: register char *s;
81: {
82: register char *p, *sp;
83:
84: sp = p = regs[ai];
85: /* if any indexing, must be parameter or local */
86: /* indirection (as in "*-4(fp)") is ok, however */
87: *p++ = type;
88: while (*p++ = *s)
89: if (*s=='[' || *s++=='(' && *s!='f') {*sp = 0; return;}
90: }
91:
92: dest(s,type, ccflg)
93: register char *s;
94: {
95: register int i;
96:
97: if ((i = isreg(s)) >= 0) {
98: *(short *)(regs[i]) = 0; /* if register destination, that reg is a goner */
99: }
100: for (i=NREG; --i>=0;)
101: if (regs[i][1]=='*' && equstr(s, regs[i]+2))
102: *(short *)(regs[i]) = 0; /* previous indirection through destination is invalid */
103: while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */
104: *(short *)(regs[i]) = 0;
105: if (!natural(s)) {/* wild store, everything except constants vanishes */
106: for (i=NREG; --i>=0;) if (regs[i][1] != '$') *(short *)(regs[i]) = 0;
107: conloc[0] = 0; ccloc[0] = 0;
108: } else if(ccflg)setcc(s,type); /* natural destinations set condition codes */
109: }
110:
111: splitrand(p) struct node *p; {
112: /* separate operands at commas, set up 'regs' and 'lastrand' */
113: register char *p1, *p2; register char **preg;
114:
115: preg=regs+RT1;
116: if (p1=p->code) while (*p1) {
117: lastrand=p2= *preg++;
118: while (*p1) if (','==(*p2++= *p1++)) {--p2; break;}
119: *p2=0;
120: }
121: while (preg<(regs+RT1+5)) *(*preg++)=0;
122: }
123:
124: compat(have, want) {
125: register int hsrc, hdst;
126:
127: if (0==(want &= 0xF)) return(1); /* anything satisfies a wildcard want */
128: hsrc=have&0xF; if (0==(hdst=((have>>4)&0xF)) || hdst>=OP2) hdst=hsrc;
129: if (want>=QUAD) return(hdst==want && hsrc==want);
130: return(hsrc==want && hdst>=want && hdst<QUAD);
131: }
132:
133: equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));}
134:
135: findrand(as, type)
136: char *as;
137: {
138: register char **i;
139: for (i = regs+NREG; --i>=regs;) {
140: if (**i && equstr(*i+1, as) && compat(**i,type))
141: return(i-regs);
142: }
143: return(-1);
144: }
145:
146: isreg(s)
147: register char *s;
148: {
149: if (*s++!='r' || !isdigit(*s++)) return(-1);
150: if (*s==0) return(*--s-'0');
151: if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'0');
152: return(-1);
153: }
154:
155: /*
156: check()
157: {
158: register struct node *p, *lp;
159:
160: lp = &first;
161: for (p=first.forw; p!=0; p = p->forw) {
162: if (p->back != lp)
163: abort(-1);
164: lp = p;
165: }
166: }
167: */
168:
169: newcode(p) struct node *p; {
170: register char *p1,*p2,**preg;
171:
172: preg=regs+RT1; p2=line;
173: while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';}
174: *--p2=0;
175: p->code=copy(line);
176: }
177:
178: repladdr(p)
179: struct node *p;
180: {
181: register r;
182: register char *p1;
183: register char **preg;
184: register int nrepl;
185:
186: preg=regs+RT1; nrepl=0;
187: while (lastrand!=(p1= *preg++))
188: if (0<=(r=findrand(p1,p->subop))) {
189: *p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0;
190: nchange++; nrepl++; nsaddr++;
191: }
192: if (nrepl) newcode(p);
193: }
194:
195: /* conditional branches which are never/always taken */
196: reduncbr(p)
197: register struct node *p;
198: {
199: register struct node *p1;
200: register char *ap1, *ap2;
201:
202: p1 = p->back;
203: if (p1->op==CMP) {
204: splitrand(p1);
205: ap1 = findcon(regs[RT1], p1->subop);
206: ap2 = findcon(regs[RT2], p1->subop);
207: } else {
208: if(!ccloc[0])
209: return;
210: ap1 = findcon(ccloc+1, ccloc[0]);
211: ap2 = "$0";
212: }
213: switch (compare(p->subop, ap1, ap2)) {
214: case 0: /* branch never taken */
215: delnode(p);
216: nredunj++;
217: nchange++;
218: decref(p->ref);
219: if(p->forw->op!=CBR && (p1->op==TST || p1->op==CMP)) {
220: delnode(p1);
221: nrtst++;
222: }
223: break;
224: case 1: /* branch always taken */
225: p->op = JBR;
226: p->subop = 0;
227: p->pop = 0;
228: nchange++;
229: }
230: }
231:
232: /* a jump to a redundant compare (start of a 'for') */
233: redunbr(p)
234: register struct node *p;
235: {
236: register struct node *p1;
237: register char *ap1, *ap2;
238:
239: if ((p1 = p->ref) == 0)
240: return;
241: p1 = nonlab(p1);
242: if (p1->op==TST || p1->op==CMP)
243: splitrand(p1);
244: else
245: return;
246: if (p1->forw->op==CBR) {
247: ap1 = findcon(regs[RT1], p1->subop);
248: if (p1->op==TST)
249: ap2 = "$0";
250: else
251: ap2 = findcon(regs[RT2], p1->subop);
252: p1 = p1->forw;
253: if (compare(p1->subop, ap1, ap2) > 0) {
254: nredunj++;
255: nchange++;
256: decref(p->ref);
257: p->ref = p1->ref;
258: p->labno = p1->labno;
259: #ifdef COPYCODE
260: if (p->labno == 0)
261: p->code = p1->code;
262: if (p->ref)
263: #endif
264: p->ref->refc++;
265: }
266: } else if (p1->op==TST && equstr(regs[RT1],ccloc+1) &&
267: equtype(ccloc[0],p1->subop)) {
268: p1=insertl(p1->forw); decref(p->ref); p->ref=p1;
269: nrtst++; nchange++;
270: }
271: }
272:
273: char *
274: findcon(p, type)
275: register char *p;
276: {
277: register r;
278:
279: if (*p=='$')
280: return(p);
281: if ((r = isreg(p)) >= 0 && compat(regs[r][0],type))
282: return(regs[r]+1);
283: if (equstr(p, conloc))
284: return(conval+1);
285: return(p);
286: }
287:
288: /* compare constants: 0 - branch taken; 1 - not taken; -1 - don't know */
289: compare(op, acp1, acp2)
290: char *acp1, *acp2;
291: {
292: register char *cp1, *cp2;
293: register n1, n2, sign;
294:
295: cp1 = acp1;
296: cp2 = acp2;
297: if (*cp1++ != '$' || *cp2++ != '$')
298: return(-1);
299: n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;}
300: while (isdigit(*cp1)) {n1 *= 10; n1 += *cp1++ - '0';}
301: n1 *= sign;
302: n2 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;}
303: while (isdigit(*cp2)) {n2 *= 10; n2 += *cp2++ - '0';}
304: n2 *= sign;
305: if (*cp1=='+')
306: cp1++;
307: if (*cp2=='+')
308: cp2++;
309: do {
310: if (*cp1++ != *cp2)
311: return(-1);
312: } while (*cp2++);
313: switch(op) {
314:
315: case JEQ:
316: return(n1 == n2);
317: case JNE:
318: return(n1 != n2);
319: case JLE:
320: return(n1 <= n2);
321: case JGE:
322: return(n1 >= n2);
323: case JLT:
324: return(n1 < n2);
325: case JGT:
326: return(n1 > n2);
327: case JLO:
328: return((unsigned)n1 < (unsigned)n2);
329: case JHI:
330: return((unsigned)n1 > (unsigned)n2);
331: case JLOS:
332: return((unsigned)n1 <= (unsigned)n2);
333: case JHIS:
334: return((unsigned)n1 >= (unsigned)n2);
335: }
336: return(-1);
337: }
338:
339: setcon(cv, cl, type)
340: register char *cv, *cl;
341: {
342: register char *p;
343:
344: if (*cv != '$')
345: return;
346: if (!natural(cl))
347: return;
348: p = conloc;
349: while (*p++ = *cl++);
350: p = conval;
351: *p++ = type;
352: while (*p++ = *cv++);
353: }
354:
355: equstr(p1, p2)
356: register char *p1, *p2;
357: {
358: do {
359: if (*p1++ != *p2)
360: return(0);
361: } while (*p2++);
362: return(1);
363: }
364:
365: setcc(ap,type)
366: char *ap;
367: {
368: register char *p, *p1;
369:
370: p = ap;
371: if (!natural(p)) {
372: ccloc[0] = 0;
373: return;
374: }
375: p1 = ccloc;
376: *p1++ = type;
377: while (*p1++ = *p++);
378: }
379:
380: indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */
381: while (*p) if (*p++=='[') return(1);
382: return(0);
383: }
384:
385: natural(p)
386: register char *p;
387: {/* 1->simple local, parameter, global, or register; 0->otherwise */
388:
389: if (*p=='*' || *p=='(' || *p=='$')
390: return(0);
391: while (*p++);
392: p--;
393: if (*--p==']' || *p==')' && *(p-2)!='f')
394: return(0);
395: return(1);
396: }
397:
398: /*
399: ** Tell if an argument is most likely static.
400: */
401:
402: isstatic(cp)
403: register char *cp;
404: {
405: if (*cp == '_' || *cp == 'L' || (*cp++ == 'v' && *cp == '.'))
406: return (1);
407: return (0);
408: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.