|
|
1.1 root 1: #include <u.h>
2: #include <libc.h>
3: #include <bio.h>
4: #include <ctype.h>
5: #define Extern extern
6: #include "parl.h"
7: #include "globl.h"
8:
9: void
10: peep(void)
11: {
12: Reg *r, *r1, *r2;
13: Inst *p;
14: int t;
15: /*
16: * complete R structure
17: */
18: t = 0;
19: for(r=firstr; r!=R; r=r1) {
20: r1 = r->next;
21: if(r1 == R)
22: break;
23: p = r->prog->next;
24: while(p != r1->prog)
25: switch(p->op) {
26: default:
27: r2 = rega();
28: r->next = r2;
29: r2->next = r1;
30:
31: r2->prog = p;
32: r2->p1 = r;
33: r->s1 = r2;
34: r2->s1 = r1;
35: r1->p1 = r2;
36:
37: r = r2;
38: t++;
39:
40: case ADATA:
41: case ADYNT:
42: case AINIT:
43: case AGLOBL:
44: case ANAME:
45: p = p->next;
46: }
47: }
48:
49: loop1:
50: t = 0;
51: for(r=firstr; r!=R; r=r->next) {
52: p = r->prog;
53: if(p->op == AMOVW || p->op == AFMOVF || p->op == AFMOVD)
54: if(regtyp(&p->dst)) {
55: if(regtyp(&p->src1))
56: if(p->src1.type == p->dst.type) {
57: if(copyprop(r)) {
58: excise(r);
59: t++;
60: } else
61: if(subprop(r) && copyprop(r)) {
62: excise(r);
63: t++;
64: }
65: }
66: if(regzer(&p->src1))
67: if(p->dst.type == A_REG) {
68: p->src1.type = A_REG;
69: p->src1.reg = 0;
70: if(copyprop(r)) {
71: excise(r);
72: t++;
73: } else
74: if(subprop(r) && copyprop(r)) {
75: excise(r);
76: t++;
77: }
78: }
79: }
80: }
81: if(t)
82: goto loop1;
83: }
84:
85: void
86: excise(Reg *r)
87: {
88: Inst *p;
89:
90: p = r->prog;
91: p->op = ANOP;
92: p->src1 = zprog.src1;
93: p->dst = zprog.dst;
94: p->reg = zprog.reg; /**/
95: }
96:
97: Reg*
98: uniqp(Reg *r)
99: {
100: Reg *r1;
101:
102: r1 = r->p1;
103: if(r1 == R) {
104: r1 = r->p2;
105: if(r1 == R || r1->p2next != R)
106: return R;
107: } else
108: if(r->p2 != R)
109: return R;
110: return r1;
111: }
112:
113: Reg*
114: uniqs(Reg *r)
115: {
116: Reg *r1;
117:
118: r1 = r->s1;
119: if(r1 == R) {
120: r1 = r->s2;
121: if(r1 == R)
122: return R;
123: } else
124: if(r->s2 != R)
125: return R;
126: return r1;
127: }
128:
129: regzer(Adres *a)
130: {
131:
132: if(a->type == A_CONST)
133: if(a->sym == ZeroS)
134: if(a->ival == 0)
135: return 1;
136: if(a->type == A_REG)
137: if(a->reg == 0)
138: return 1;
139: return 0;
140: }
141:
142: regtyp(Adres *a)
143: {
144:
145: if(a->type == A_REG) {
146: if(a->reg != 0)
147: return 1;
148: return 0;
149: }
150: if(a->type == A_FREG)
151: return 1;
152: return 0;
153: }
154:
155: /*
156: * the idea is to substitute
157: * one register for another
158: * from one MOV to another
159: * MOV a, R0
160: * ADD b, R0 / no use of R1
161: * MOV R0, R1
162: * would be converted to
163: * MOV a, R1
164: * ADD b, R1
165: * MOV R1, R0
166: * hopefully, then the former or latter MOV
167: * will be eliminated by copy propagation.
168: */
169: int
170: subprop(Reg *r0)
171: {
172: Inst *p;
173: Adres *v1, *v2;
174: Reg *r;
175: int t;
176:
177: p = r0->prog;
178: v1 = &p->src1;
179: if(!regtyp(v1))
180: return 0;
181: v2 = &p->dst;
182: if(!regtyp(v2))
183: return 0;
184: for(r=uniqp(r0); r!=R; r=uniqp(r)) {
185: if(uniqs(r) == R)
186: break;
187: p = r->prog;
188: switch(p->op) {
189: case AJMPL:
190: return 0;
191:
192: case AADD:
193: case ASUB:
194: case ASLL:
195: case ASRL:
196: case ASRA:
197: case AOR:
198: case AAND:
199: case AXOR:
200: case AMUL:
201: case ADIV:
202: case ADIVL:
203: case AMOD:
204: case AMODL:
205:
206: case AFADDD:
207: case AFADDF:
208: case AFSUBD:
209: case AFSUBF:
210: case AFMULD:
211: case AFMULF:
212: case AFDIVD:
213: case AFDIVF:
214: if(p->dst.type == v1->type)
215: if(p->dst.reg == v1->reg) {
216: if(p->reg == Nreg)
217: p->reg = p->dst.reg;
218: goto gotit;
219: }
220: break;
221:
222: case AFMOVF:
223: case AFMOVD:
224: case AMOVW:
225: if(p->dst.type == v1->type)
226: if(p->dst.reg == v1->reg)
227: goto gotit;
228: break;
229: }
230: if(copyau(&p->src1, v2) ||
231: copyau1(p, v2) ||
232: copyau(&p->dst, v2))
233: break;
234: if(copysub(&p->src1, v1, v2, 0) ||
235: copysub1(p, v1, v2, 0) ||
236: copysub(&p->dst, v1, v2, 0))
237: break;
238: }
239: return 0;
240:
241: gotit:
242: copysub(&p->dst, v1, v2, 1);
243: if(opt('P')) {
244: print("gotit: %a->%a\n%i", v1, v2, r->prog);
245: if(p->src1.type == v2->type)
246: print(" excise");
247: print("\n");
248: }
249: for(r=uniqs(r); r!=r0; r=uniqs(r)) {
250: p = r->prog;
251: copysub(&p->src1, v1, v2, 1);
252: copysub1(p, v1, v2, 1);
253: copysub(&p->dst, v1, v2, 1);
254: if(opt('P'))
255: print("%i\n", r->prog);
256: }
257: t = v1->reg;
258: v1->reg = v2->reg;
259: v2->reg = t;
260: if(opt('P'))
261: print("%i last\n", r->prog);
262: return 1;
263: }
264:
265: /*
266: * The idea is to remove redundant copies.
267: * v1->v2 F=0
268: * (use v2 s/v2/v1/)*
269: * set v1 F=1
270: * use v2 return fail
271: * -----------------
272: * v1->v2 F=0
273: * (use v2 s/v2/v1/)*
274: * set v1 F=1
275: * set v2 return success
276: */
277: int
278: copyprop(Reg *r0)
279: {
280: Inst *p;
281: Adres *v1, *v2;
282: Reg *r;
283:
284: p = r0->prog;
285: v1 = &p->src1;
286: v2 = &p->dst;
287: if(copyas(v1, v2))
288: return 1;
289: for(r=firstr; r!=R; r=r->next)
290: r->active = 0;
291: return copy1(v1, v2, r0->s1, 0);
292: }
293:
294: copy1(Adres *v1, Adres *v2, Reg *r, int f)
295: {
296: int t;
297: Inst *p;
298:
299: if(r->active) {
300: if(opt('P'))
301: print("act set; return 1\n");
302: return 1;
303: }
304: r->active = 1;
305: if(opt('P'))
306: print("copy %a->%a f=%d\n", v1, v2, f);
307: for(; r != R; r = r->s1) {
308: p = r->prog;
309: if(opt('P'))
310: print("%i", p);
311: if(!f && uniqp(r) == R) {
312: f = 1;
313: if(opt('P'))
314: print("; merge; f=%d", f);
315: }
316: t = copyu(p, v2, A);
317: switch(t) {
318: case 2: /* rar, cant split */
319: if(opt('P'))
320: print("; %arar; return 0\n", v2);
321: return 0;
322:
323: case 3: /* set */
324: if(opt('P'))
325: print("; %aset; return 1\n", v2);
326: return 1;
327:
328: case 1: /* used, substitute */
329: case 4: /* use and set */
330: if(f) {
331: if(!opt('P'))
332: return 0;
333: if(t == 4)
334: print("; %aused+set and f=%d; return 0\n", v2, f);
335: else
336: print("; %aused and f=%d; return 0\n", v2, f);
337: return 0;
338: }
339: if(copyu(p, v2, v1)) {
340: if(opt('P'))
341: print("; sub fail; return 0\n");
342: return 0;
343: }
344: if(opt('P'))
345: print("; sub%a/%a", v2, v1);
346: if(t == 4) {
347: if(opt('P'))
348: print("; %aused+set; return 1\n", v2);
349: return 1;
350: }
351: break;
352: }
353: if(!f) {
354: t = copyu(p, v1, A);
355: if(!f && (t == 2 || t == 3 || t == 4)) {
356: f = 1;
357: if(opt('P'))
358: print("; %aset and !f; f=%d", v1, f);
359: }
360: }
361: if(opt('P'))
362: print("\n");
363: if(r->s2)
364: if(!copy1(v1, v2, r->s2, f))
365: return 0;
366: }
367: return 1;
368: }
369:
370: /*
371: * return
372: * 1 if v only used (and substitute),
373: * 2 if read-alter-rewrite
374: * 3 if set
375: * 4 if set and used
376: * 0 otherwise (not touched)
377: */
378: int
379: copyu(Inst *p, Adres *v, Adres *s)
380: {
381:
382: switch(p->op) {
383:
384: default:
385: if(opt('P'))
386: print(" (???)");
387: return 2;
388:
389:
390: case ANOP: /* read, write */
391: case AMOVW:
392: case AMOVH:
393: case AMOVHU:
394: case AMOVB:
395: case AMOVBU:
396:
397: case AFMOVF:
398: case AFMOVD:
399: case AFMOVDW:
400: case AFMOVWD:
401: case AFMOVFW:
402: case AFMOVWF:
403: case AFMOVFD:
404: case AFMOVDF:
405: if(s != A) {
406: if(copysub(&p->src1, v, s, 1))
407: return 1;
408: if(!copyas(&p->dst, v))
409: if(copysub(&p->dst, v, s, 1))
410: return 1;
411: return 0;
412: }
413: if(copyas(&p->dst, v)) {
414: if(copyau(&p->src1, v))
415: return 4;
416: return 3;
417: }
418: if(copyau(&p->src1, v))
419: return 1;
420: if(copyau(&p->dst, v))
421: return 1;
422: return 0;
423:
424: case AADD: /* read read write */
425: case ASUB:
426: case ASLL:
427: case ASRL:
428: case ASRA:
429: case AOR:
430: case AAND:
431: case AXOR:
432: case AMUL:
433: case ADIV:
434: case ADIVL:
435: case AMOD:
436: case AMODL:
437:
438: case AFADDF:
439: case AFADDD:
440: case AFSUBF:
441: case AFSUBD:
442: case AFMULF:
443: case AFMULD:
444: case AFDIVF:
445: case AFDIVD:
446: if(s != A) {
447: if(copysub(&p->src1, v, s, 1))
448: return 1;
449: if(copysub1(p, v, s, 1))
450: return 1;
451: if(!copyas(&p->dst, v))
452: if(copysub(&p->dst, v, s, 1))
453: return 1;
454: return 0;
455: }
456: if(copyas(&p->dst, v)) {
457: if(p->reg == Nreg)
458: p->reg = p->dst.reg;
459: if(copyau(&p->src1, v))
460: return 4;
461: if(copyau1(p, v))
462: return 4;
463: return 3;
464: }
465: if(copyau(&p->src1, v))
466: return 1;
467: if(copyau1(p, v))
468: return 1;
469: if(copyau(&p->dst, v))
470: return 1;
471: return 0;
472:
473: case ABA: /* no reference */
474: case ABCC:
475: case ABCS:
476: case ABE:
477: case ABG:
478: case ABGE:
479: case ABGU:
480: case ABL:
481: case ABLE:
482: case ABLEU:
483: case ABN:
484: case ABNE:
485: case ABNEG:
486: case ABPOS:
487: case ABVC:
488: case ABVS:
489: case AFBA:
490: case AFBE:
491: case AFBG:
492: case AFBGE:
493: case AFBL:
494: case AFBLE:
495: case AFBLG:
496: case AFBN:
497: case AFBNE:
498: case AFBO:
499: case AFBU:
500: case AFBUE:
501: case AFBUG:
502: case AFBUGE:
503: case AFBUL:
504: case AFBULE:
505: break;
506:
507: case ACMP: /* read read */
508: case AFCMPD:
509: case AFCMPF:
510: if(s != A) {
511: if(copysub(&p->src1, v, s, 1))
512: return 1;
513: return copysub(&p->dst, v, s, 1);
514: }
515: if(copyau(&p->src1, v))
516: return 1;
517: if(copyau(&p->dst, v))
518: return 1;
519: break;
520:
521: case AJMP: /* funny */
522: if(s != A) {
523: if(copysub(&p->dst, v, s, 1))
524: return 1;
525: return 0;
526: }
527: if(copyau(&p->dst, v))
528: return 1;
529: return 0;
530:
531: case ARETURN: /* funny */
532: if(v->type == A_REG && v->reg == REGRET)
533: return 2;
534: if(v->type == A_FREG && v->reg == FREGRET)
535: return 2;
536:
537: case AJMPL: /* funny */
538: if(v->type == A_REG) {
539: if(v->reg == Regspass)
540: return 2;
541: if(v->reg == RegSP)
542: return 2;
543: }
544: if(s != A) {
545: if(copysub(&p->dst, v, s, 1))
546: return 1;
547: return 0;
548: }
549: if(copyau(&p->dst, v))
550: return 4;
551: return 3;
552:
553: case ATEXT: /* funny */
554: if(v->type == A_REG)
555: if(v->reg == Regspass)
556: return 3;
557: return 0;
558: }
559: return 0;
560: }
561:
562: int
563: a2type(Inst *p)
564: {
565:
566: switch(p->op) {
567: case AADD:
568: case ASUB:
569: case ASLL:
570: case ASRL:
571: case ASRA:
572: case AOR:
573: case AAND:
574: case AXOR:
575: case AMUL:
576: case ADIV:
577: case ADIVL:
578: case AMOD:
579: case AMODL:
580: return A_REG;
581:
582: case AFADDF:
583: case AFADDD:
584: case AFSUBF:
585: case AFSUBD:
586: case AFMULF:
587: case AFMULD:
588: case AFDIVF:
589: case AFDIVD:
590: return A_FREG;
591: }
592: return A_NONE;
593: }
594:
595: /*
596: * direct reference,
597: * could be set/use depending on
598: * semantics
599: */
600: int
601: copyas(Adres *a, Adres *v)
602: {
603:
604: if(regtyp(v))
605: if(a->type == v->type)
606: if(a->reg == v->reg)
607: return 1;
608: return 0;
609: }
610:
611: /*
612: * either direct or indirect
613: */
614: int
615: copyau(Adres *a, Adres *v)
616: {
617:
618: if(copyas(a, v))
619: return 1;
620: if(v->type == A_REG)
621: if(a->type == A_INDREG)
622: if(v->reg == a->reg)
623: return 1;
624: return 0;
625: }
626:
627: int
628: copyau1(Inst *p, Adres *v)
629: {
630:
631: if(regtyp(v))
632: if(p->src1.type == v->type || p->dst.type == v->type)
633: if(p->reg == v->reg) {
634: if(a2type(p) != v->type)
635: print("botch a2type %i\n", p);
636: return 1;
637: }
638: return 0;
639: }
640:
641: /*
642: * substitute s for v in a
643: * return failure to substitute
644: */
645: int
646: copysub(Adres *a, Adres *v, Adres *s, int f)
647: {
648:
649: if(f)
650: if(copyau(a, v))
651: a->reg = s->reg;
652: return 0;
653: }
654:
655: int
656: copysub1(Inst *p1, Adres *v, Adres *s, int f)
657: {
658:
659: if(f)
660: if(copyau1(p1, v))
661: p1->reg = s->reg;
662: return 0;
663: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.