|
|
1.1 root 1: /*
2: * Peephole optimizer. Look through the
3: * code graph, tracking the state of the machine
4: * and deleting and/or simplifing instructions that
5: * have no change on the machine state. This code
6: * is machine independent in spirit, but is in fact
7: * only for the Intel 8086.
8: */
9: #ifdef vax
10: #include "INC$LIB:cc2.h"
11: #else
12: #include "cc2.h"
13: #endif
14:
15: /*
16: * Machine registers. These codes are the
17: * same as the ones used by the processor in the
18: * REGM field of an instruction. This makes it easier
19: * to get the register code from an AFIELD. Unless
20: * Intel changes the chip, do not change the values
21: * here.
22: */
23: #define MAX 0
24: #define MCX 1
25: #define MDX 2
26: #define MBX 3
27: #define MSP 4
28: #define MBP 5
29: #define MSI 6
30: #define MDI 7
31:
32: #define MES 0
33: #define MCS 1
34: #define MSS 2
35: #define MDS 3
36:
37: #define NMREG 8
38: #define NSREG 4
39:
40: /*
41: * Register state tables. Just an AFIELD
42: * structure for each kind of register (machine or
43: * segment). An "a_mode" of "A_NONE" means the
44: * register is empty or contains unknown information.
45: * Indexed by machine register code.
46: */
47: AFIELD mregstate[NMREG];
48: AFIELD sregstate[NSREG];
49:
50: AFIELD *afresolve();
51:
52: AFIELD afdsfakeing = { A_SR|MDS, NULL, 0 };
53: AFIELD afesfakeing = { A_SR|MES, NULL, 0 };
54:
55: /*
56: * Mainline of the peephole pass.
57: * Mark all of the world as unknown. Sweep the
58: * code graph, watching out for labels and machine
59: * code. Any label makes the entire machine state an
60: * unknown (with some flow analysis, this would not really
61: * be necessary).
62: */
63: peephole()
64: {
65: register INS *ip;
66: register int rel;
67:
68: emptyall();
69: for (ip=ins.i_fp; ip!=&ins; ip=ip->i_fp) {
70: if (ip->i_type == LLABEL)
71: emptyall();
72: else if (ip->i_type == JUMP) {
73: rel = ip->i_rel;
74: if (rel==ZLOOP || rel==ZLOOPE || rel==ZLOOPNE)
75: emptymreg(&mregstate[MCX]);
76: } else if (ip->i_type == CODE) {
77: if (noeffect(ip)) {
78: ip = deleteins(ip, ip->i_fp);
79: ++nuseless;
80: ++changes;
81: } else {
82: simplify(ip);
83: track(ip);
84: }
85: }
86: }
87: }
88:
89: /*
90: * Mark all of the registers in the
91: * processor state as empty. Used whenever the
92: * state of the machine is, or will become,
93: * completely undefined.
94: */
95: emptyall()
96: {
97: register AFIELD *sp;
98:
99: sp = &mregstate[0];
100: while (sp < &mregstate[NMREG]) {
101: emptymreg(sp);
102: ++sp;
103: }
104: sp = &sregstate[0];
105: while (sp < &sregstate[NSREG]) {
106: emptysreg(sp);
107: ++sp;
108: }
109: }
110:
111: /*
112: * Flag machine register "r" as empty
113: * (contains unknown data) in the processor state.
114: * If "r" is an indexing base (BX, SI, DI) then any
115: * processor state entries based off these registers
116: * must also be set empty. Note that there is a
117: * register number change between bx and [bx], so a
118: * bit of funnyness is required.
119: */
120: emptymreg(rsp)
121: register AFIELD *rsp;
122: {
123: register AFIELD *sp;
124: register short xmode;
125:
126: rsp->a_mode = A_NONE;
127: if (rsp == &mregstate[MBX]
128: || rsp == &mregstate[MSI]
129: || rsp == &mregstate[MDI]) {
130: if (rsp == &mregstate[MBX])
131: xmode = A_XBX;
132: else if (rsp == &mregstate[MSI])
133: xmode = A_XSI;
134: else
135: xmode = A_XDI;
136: sp = &mregstate[0];
137: while (sp < &mregstate[NMREG]) {
138: if ((sp->a_mode&(A_AMOD|A_REGM)) == xmode)
139: sp->a_mode = A_NONE;
140: ++sp;
141: }
142: sp = &sregstate[0];
143: while (sp < &sregstate[NSREG]) {
144: if ((sp->a_mode&(A_AMOD|A_REGM)) == xmode)
145: sp->a_mode = A_NONE;
146: ++sp;
147: }
148: }
149: }
150:
151: /*
152: * Flag segment register "r" as empty
153: * (contains unknown data) in the processor state.
154: * If "r" is the ES register then all entries in the
155: * processor state being accessed through ES must also
156: * flagged as empty.
157: */
158: emptysreg(rsp)
159: register AFIELD *rsp;
160: {
161: register AFIELD *sp;
162:
163: rsp->a_mode = A_NONE;
164: if (rsp == &sregstate[MES]) {
165: sp = &mregstate[0];
166: while (sp < &mregstate[NMREG]) {
167: if ((sp->a_mode&A_AMOD) != A_NONE
168: && (sp->a_mode&A_PREFX) == A_ES)
169: sp->a_mode = A_NONE;
170: ++sp;
171: }
172: sp = &sregstate[0];
173: while (sp < &sregstate[NSREG]) {
174: if ((sp->a_mode&A_AMOD) != A_NONE
175: && (sp->a_mode&A_PREFX) == A_ES)
176: sp->a_mode = A_NONE;
177: ++sp;
178: }
179: }
180: if (rsp == &sregstate[MDS]) {
181: sp = &mregstate[0];
182: while (sp < &mregstate[NMREG]) {
183: if ((sp->a_mode&A_AMOD) != A_NONE) {
184: if ((sp->a_mode&A_PREFX) == A_DS)
185: sp->a_mode = A_NONE;
186: else if ((sp->a_mode&A_PREFX) == A_NONE
187: && (sp->a_mode&(A_AMOD|A_REGM)) != A_XBP)
188: sp->a_mode = A_NONE;
189: }
190: ++sp;
191: }
192: sp = &sregstate[0];
193: while (sp < &sregstate[NSREG]) {
194: if ((sp->a_mode&A_AMOD) != A_NONE) {
195: if ((sp->a_mode&A_PREFX) == A_DS)
196: sp->a_mode = A_NONE;
197: else if ((sp->a_mode&A_PREFX) == A_NONE
198: && (sp->a_mode&(A_AMOD|A_REGM)) != A_XBP)
199: sp->a_mode = A_NONE;
200: }
201: ++sp;
202: }
203: }
204: }
205:
206: /*
207: * This routine, given a pointer to
208: * a CODE node, returns 1 if the instruction has
209: * no effect on the machine state. This is determined by
210: * looking at the operands of the instruction and the value
211: * that is currently in the registers. Some care must be
212: * taken to make sure that an instruction that is being used
213: * to set the flags is not considered to have no effect.
214: */
215: noeffect(ip)
216: register INS *ip;
217: {
218: register AFIELD *sp;
219: register short mode;
220:
221: if (ip->i_op == ZSUB) {
222: if ((ip->i_af[0].a_mode&A_AMOD) == A_WR
223: && ip->i_af[0].a_mode == ip->i_af[1].a_mode) {
224: sp = &mregstate[ip->i_af[0].a_mode&A_REGM];
225: if ((sp->a_mode&A_AMOD) == A_IMM
226: && sp->a_sp == NULL
227: && sp->a_value == 0) {
228: /* Need flags? */
229: if ((ip = ip->i_fp) == &ins)
230: return (0);
231: if (ip->i_type==JUMP && ip->i_rel!=ZJMP)
232: return (0);
233: return (1);
234: }
235: }
236: return (0);
237: }
238: if (ip->i_op == ZLEA) {
239: if (afcompare(A_EA, &ip->i_af[0], &ip->i_af[1], 0))
240: return (1);
241: return (0);
242: }
243: if (ip->i_op==ZLDS || ip->i_op==ZLES) {
244: sp = (ip->i_op==ZLDS) ? &sregstate[MDS] : &sregstate[MES];
245: if (afcompare(0, sp, &ip->i_af[1], 2)
246: && afcompare(0, &ip->i_af[0], &ip->i_af[1], 0))
247: return (1);
248: return (0);
249: }
250: if (ip->i_op == ZMOV) {
251: mode = ip->i_af[0].a_mode&A_AMOD;
252: if ((mode==A_WR || mode==A_SR)
253: && afcompare(0, &ip->i_af[0], &ip->i_af[1], 0))
254: return (1);
255: return (0);
256: }
257: return (0);
258: }
259:
260: /*
261: * This routine looks at a CODE node
262: * and tries to make it into a simpler node that
263: * performs the same transformation of the machine
264: * state. The current idioms understood are:
265: * 1) Look for "half loaded" "lds" and "les" instructions
266: * that can be changed into the approproate "mov".
267: * 2) Try to replace memory operands of dual op instructions
268: * and push instructions with old register data.
269: */
270: simplify(ip)
271: register INS *ip;
272: {
273: register AFIELD *sp;
274:
275: switch (ip->i_op) {
276:
277: case ZLDS:
278: case ZLES:
279: sp = (ip->i_op==ZLDS) ? &sregstate[MDS] : &sregstate[MES];
280: if (afcompare(0, sp, &ip->i_af[1], 2)) {
281: if (!afcompare(0, &ip->i_af[0], &ip->i_af[1], 0)) {
282: ip->i_op = ZMOV;
283: ++nsimplify;
284: ++changes;
285: }
286: } else if (afcompare(0, &ip->i_af[0], &ip->i_af[1], 0)) {
287: if (ip->i_op == ZLDS)
288: ip->i_af[0].a_mode = A_SR|MDS; else
289: ip->i_af[0].a_mode = A_SR|MES;
290: ip->i_af[1].a_value += 2;
291: ip->i_op = ZMOV;
292: ++nsimplify;
293: ++changes;
294: }
295: break;
296:
297: case ZADC:
298: case ZADD:
299: case ZAND:
300: case ZOR:
301: case ZSBB:
302: case ZSUB:
303: case ZXOR:
304: simpoper(&ip->i_af[1]);
305: break;
306:
307: case ZPUSH:
308: simpoper(&ip->i_af[0]);
309: break;
310: }
311: }
312:
313: /*
314: * The "afp" points at an AFIELD. If it is
315: * a memory AFIELD look through the processor state
316: * to see if a register contains the same value. If such
317: * a register is found adjust the AFIELD to refer to the
318: * machine register.
319: */
320: simpoper(afp)
321: register AFIELD *afp;
322: {
323: register AFIELD *sp;
324: register int mode;
325:
326: mode = afp->a_mode&A_AMOD;
327: if (mode==A_IMM || mode==A_DIR || mode==A_X) {
328: sp = &mregstate[0];
329: while (sp < &mregstate[NMREG]) {
330: if (afcompare(0, sp, afp, 0)) {
331: afp->a_mode = A_WR | (sp-&mregstate[0]);
332: afp->a_sp = NULL;
333: afp->a_value = 0;
334: ++nsimplify;
335: ++changes;
336: break;
337: }
338: ++sp;
339: }
340: }
341: }
342:
343: /*
344: * Look at the CODE node pointed to
345: * by "ip", and make the required changes to the processor
346: * state. Some special compiler idioms have special checks.
347: * Any instruction for which there is no special knowledge
348: * is assumed to have no effect on the machine state.
349: */
350: track(ip)
351: register INS *ip;
352: {
353: register AFIELD *sp;
354: register short destmode;
355: register short destreg;
356: register short isbyte;
357:
358: if (ip->i_op == ZOR
359: && (ip->i_af[0].a_mode&A_AMOD) == A_WR
360: && ip->i_af[0].a_mode == ip->i_af[1].a_mode)
361: return;
362: if (ip->i_op == ZSUB
363: && (ip->i_af[0].a_mode&A_AMOD) == A_WR
364: && ip->i_af[0].a_mode == ip->i_af[1].a_mode) {
365: sp = &mregstate[ip->i_af[0].a_mode&A_REGM];
366: sp->a_mode = A_IMM;
367: sp->a_sp = NULL;
368: sp->a_value = 0;
369: return;
370: }
371: isbyte = 0;
372: switch (ip->i_op) {
373:
374: case ZAAA:
375: case ZAAD:
376: case ZAAM:
377: case ZAAS:
378: case ZCBW:
379: case ZDAA:
380: case ZDAS:
381: case ZDIVB:
382: case ZIDIVB:
383: case ZIMULB:
384: case ZIN:
385: case ZINB:
386: case ZLAHF:
387: case ZMULB:
388: emptymreg(&mregstate[MAX]);
389: break;
390:
391: case ZCWD:
392: emptymreg(&mregstate[MDX]);
393: break;
394:
395: case ZDIV:
396: case ZIDIV:
397: case ZIMUL:
398: case ZMUL:
399: emptymreg(&mregstate[MAX]);
400: emptymreg(&mregstate[MDX]);
401: break;
402:
403: case ZREPE:
404: case ZREPNE:
405: emptymreg(&mregstate[MCX]);
406: break;
407:
408: case ZCALL:
409: case ZICALL:
410: case ZIXCALL:
411: case ZXCALL:
412: case ZCMPS:
413: case ZCMPSB:
414: case ZINT:
415: case ZINTO:
416: case ZLODS:
417: case ZLODSB:
418: case ZMOVS:
419: case ZMOVSB:
420: case ZSCAS:
421: case ZSCASB:
422: case ZSTOS:
423: case ZSTOSB:
424: case ZXCHG:
425: case ZXCHGB:
426: case ZXLAT:
427: emptyall();
428: break;
429:
430: case ZADCB:
431: case ZADDB:
432: case ZANDB:
433: case ZDECB:
434: case ZINCB:
435: case ZNEGB:
436: case ZNOTB:
437: case ZORB:
438: case ZRCLB:
439: case ZRCRB:
440: case ZROLB:
441: case ZRORB:
442: case ZSALB:
443: case ZSARB:
444: case ZSBBB:
445: case ZSHLB:
446: case ZSHRB:
447: case ZSUBB:
448: case ZXORB:
449: isbyte = 1;
450: case ZADC:
451: case ZADD:
452: case ZAND:
453: case ZINC:
454: case ZDEC:
455: case ZNEG:
456: case ZNOT:
457: case ZOR:
458: case ZPOP:
459: case ZRCL:
460: case ZRCR:
461: case ZROL:
462: case ZROR:
463: case ZSAL:
464: case ZSAR:
465: case ZSBB:
466: case ZSHL:
467: case ZSHR:
468: case ZSUB:
469: case ZXOR:
470: case ZIMULI:
471: destmode = ip->i_af[0].a_mode&A_AMOD;
472: destreg = ip->i_af[0].a_mode&A_REGM;
473: if (destmode==A_WR || destmode==A_BR) {
474: if (isbyte != 0)
475: destreg &= 0x03;
476: emptymreg(&mregstate[destreg]);
477: } else if (destmode == A_SR)
478: emptysreg(&sregstate[destreg]);
479: else if (isbyte==0 && (destmode==A_DIR || destmode==A_X))
480: emptyaf(&ip->i_af[0]);
481: else
482: emptyall();
483: break;
484:
485: case ZLEA:
486: afupdate(A_EA, &ip->i_af[0], &ip->i_af[1], 0);
487: break;
488:
489: case ZLDS:
490: afupdate(0, &ip->i_af[0], &ip->i_af[1], 0);
491: afupdate(0, &afdsfakeing, &ip->i_af[1], 2);
492: break;
493:
494: case ZLES:
495: afupdate(0, &ip->i_af[0], &ip->i_af[1], 0);
496: afupdate(0, &afesfakeing, &ip->i_af[1], 2);
497: break;
498:
499: case ZMOV:
500: destmode = ip->i_af[0].a_mode&A_AMOD;
501: destreg = ip->i_af[0].a_mode&A_REGM;
502: if (destmode==A_WR || destmode==A_SR)
503: afupdate(0, &ip->i_af[0], &ip->i_af[1], 0);
504: else if (destmode==A_DIR || destmode==A_X) {
505: emptyaf(&ip->i_af[0]);
506: destmode = ip->i_af[1].a_mode&A_AMOD;
507: if (destmode==A_WR || destmode==A_SR)
508: afupdate(0, &ip->i_af[1], &ip->i_af[0], 0);
509: } else
510: emptyall();
511: break;
512:
513: case ZMOVB:
514: destmode = ip->i_af[0].a_mode&A_AMOD;
515: destreg = ip->i_af[0].a_mode&A_REGM;
516: if (destmode == A_BR)
517: emptymreg(&mregstate[destreg&0x03]);
518: else if (destmode==A_DIR || destmode==A_X)
519: emptyaf(&ip->i_af[0]);
520: else
521: emptyall();
522: }
523: }
524:
525: /*
526: * This routine compares address fields.
527: * The "afp1" and "afp2" parameters are the fields
528: * themselves. They must be "resolved" to the machine
529: * state if registers. The "afp1" argument always is
530: * the register side, and is required to have the flags
531: * that are set in "flags" in the address. The "afp2"
532: * is the lvalue side; it gets its address adjusted by
533: * "bump" bytes before the compare is done.
534: */
535: afcompare(flag, afp1, afp2, bump)
536: register AFIELD *afp1;
537: register AFIELD *afp2;
538: {
539: register short mode;
540:
541: if ((afp1=afresolve(afp1, 0x00, 0)) == NULL)
542: return (0);
543: if ((afp2=afresolve(afp2, bump, 0)) == NULL)
544: return (0);
545: if (afp1->a_mode==A_NONE || afp2->a_mode==A_NONE)
546: return (0);
547: if (afp1->a_mode != afp2->a_mode)
548: return (0);
549: mode = afp1->a_mode&A_AMOD;
550: if (mode==A_IMM || mode==A_DIR || mode==A_X) {
551: if (afp1->a_sp != afp2->a_sp)
552: return (0);
553: if (afp1->a_value != afp2->a_value+bump)
554: return (0);
555: if ((afp1->a_mode&A_EA) != flag)
556: return (0);
557: }
558: return (1);
559: }
560:
561: /*
562: * Update address fields in the processor
563: * state tables. The arguments have the same functions
564: * as their namesakes in "afcompare" (above).
565: */
566: afupdate(flag, afp1, afp2, bump)
567: register AFIELD *afp1;
568: register AFIELD *afp2;
569: {
570: if ((afp1=afresolve(afp1, 0x00, 1)) == NULL)
571: cbotch("afupdate");
572: if ((afp2=afresolve(afp2, bump, 0)) == NULL)
573: afp1->a_mode = A_NONE;
574: else if (afdependency(afp1, afp2))
575: afp1->a_mode = A_NONE;
576: else {
577: afp1->a_mode = afp2->a_mode;
578: afp1->a_sp = afp2->a_sp;
579: afp1->a_value = afp2->a_value+bump;
580: if (afp1->a_mode != A_NONE)
581: afp1->a_mode |= flag;
582: }
583: }
584:
585: /*
586: * Resolve an address descriptor to the entry
587: * in the processor state. If the entry will not map
588: * for some reason, return NULL. The "bump" argument is
589: * passed so that "afresolve" can fail on bumped registers.
590: * If "flag" is set the register descriptor is flushed.
591: */
592: AFIELD *
593: afresolve(afp, bump, flag)
594: register AFIELD *afp;
595: {
596: register short mode;
597:
598: if ((mode=afp->a_mode&A_AMOD) == A_BR)
599: return (NULL);
600: if (mode == A_WR) {
601: if (bump != 0)
602: return (NULL);
603: afp = &mregstate[afp->a_mode&A_REGM];
604: if (flag != 0)
605: emptymreg(afp);
606: return (afp);
607: }
608: if (mode == A_SR) {
609: if (bump != 0)
610: return (NULL);
611: afp = &sregstate[afp->a_mode&A_REGM];
612: if (flag != 0)
613: emptysreg(afp);
614: return (afp);
615: }
616: return (afp);
617: }
618:
619: /*
620: * Given two AFIELD nodes,
621: * return true if the second depends
622: * on the value of the first. This checks
623: * for instructions like "mov bx,3[bx]",
624: * where you must not set the contents of
625: * "bx" to be "3[bx]".
626: */
627: afdependency(afp1, afp2)
628: register AFIELD *afp1;
629: register AFIELD *afp2;
630: {
631: if (afp1 == &mregstate[MBX]) {
632: if ((afp2->a_mode&(A_AMOD|A_REGM)) == A_XBX)
633: return (1);
634: return (0);
635: }
636: if (afp1 == &mregstate[MSI]) {
637: if ((afp2->a_mode&(A_AMOD|A_REGM)) == A_XSI)
638: return (1);
639: return (0);
640: }
641: if (afp1 == &mregstate[MDI]) {
642: if ((afp2->a_mode&(A_AMOD|A_REGM)) == A_XDI)
643: return (1);
644: return (0);
645: }
646: if (afp1 == &sregstate[MES]) {
647: if ((afp2->a_mode&A_PREFX) == A_ES)
648: return (1);
649: return (0);
650: }
651: if (afp1 == &sregstate[MDS]) {
652: if ((afp2->a_mode&A_PREFX) == A_DS)
653: return (1);
654: if ((afp2->a_mode&A_PREFX) == A_NONE
655: && (afp2->a_mode&(A_AMOD|A_REGM)) != A_XBP)
656: return (1);
657: return (0);
658: }
659: return (0);
660: }
661:
662: /*
663: * Purge any processor state entries that
664: * think they are holding the value of "afp". This
665: * is used to purge the state of the world when a register
666: * is stored into memory.
667: */
668: emptyaf(afp)
669: register AFIELD *afp;
670: {
671: register AFIELD *sp;
672:
673: sp = &mregstate[0];
674: while (sp < &mregstate[NMREG]) {
675: if (afcompare(0, sp, afp, 0))
676: emptymreg(sp);
677: ++sp;
678: }
679: sp = &sregstate[0];
680: while (sp < &sregstate[NSREG]) {
681: if (afcompare(0, sp, afp, 0))
682: emptysreg(sp);
683: ++sp;
684: }
685: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.