|
|
1.1 ! root 1: /* ! 2: * n2/i386/peep.c ! 3: * Peephole optimizer. ! 4: * Look through the code graph, tracking the state of the machine ! 5: * and deleting or simplifing instructions ! 6: * which have no effect on the machine state. ! 7: * This code is machine independent in spirit. ! 8: * i386. ! 9: */ ! 10: ! 11: #ifdef vax ! 12: #include "INC$LIB:cc2.h" ! 13: #else ! 14: #include "cc2.h" ! 15: #endif ! 16: ! 17: /* ! 18: * The register state table is an AFIELD structure for each machine register, ! 19: * indexed by machine register code. ! 20: * An "a_mode" of "A_NONE" means the register is empty ! 21: * or contains unknown information. ! 22: */ ! 23: AFIELD regstate[NMREG]; ! 24: ! 25: /* Forward. */ ! 26: void emptyall(); ! 27: void emptymreg(); ! 28: int noeffect(); ! 29: void simplify(); ! 30: void simpoper(); ! 31: void track(); ! 32: int afcompare(); ! 33: void afupdate(); ! 34: AFIELD *afresolve(); ! 35: int afdependency(); ! 36: void emptyaf(); ! 37: ! 38: /* ! 39: * Mainline of the peephole optimizer. ! 40: * Mark all of the world as unknown. ! 41: * Sweep the code graph, watching out for labels and machine code. ! 42: * Any label makes the entire machine state an unknown; ! 43: * with some flow analysis, this would not really be necessary. ! 44: */ ! 45: peephole() ! 46: { ! 47: register INS *ip; ! 48: register int rel; ! 49: ! 50: emptyall(); ! 51: for (ip=ins.i_fp; ip!=&ins; ip=ip->i_fp) { ! 52: if (ip->i_type == LLABEL) ! 53: emptyall(); ! 54: else if (ip->i_type == JUMP) { ! 55: rel = ip->i_rel; ! 56: if (rel==ZLOOP || rel==ZLOOPE || rel==ZLOOPNE) ! 57: emptymreg(MECX); ! 58: } else if (ip->i_type == CODE) { ! 59: if (noeffect(ip)) { ! 60: ip = deleteins(ip, ip->i_fp); ! 61: ++nuseless; ! 62: ++changes; ! 63: } else { ! 64: simplify(ip); ! 65: track(ip); ! 66: } ! 67: } ! 68: } ! 69: } ! 70: ! 71: /* ! 72: * Mark all of the registers in the processor state as empty. ! 73: * Used whenever the state of the machine is, or will become, ! 74: * completely undefined. ! 75: */ ! 76: void ! 77: emptyall() ! 78: { ! 79: register int i; ! 80: ! 81: for (i = 0; i < NMREG; i++) ! 82: emptymreg(i); ! 83: } ! 84: ! 85: /* ! 86: * Mark machine register "r" as empty ! 87: * (containing unknown data) in the processor state. ! 88: * Zap any processor state entries based off the register. ! 89: */ ! 90: void ! 91: emptymreg(i) register int i; ! 92: { ! 93: register AFIELD *sp; ! 94: ! 95: regstate[i].a_mode = A_NONE; /* mark register state empty */ ! 96: for (sp = ®state[0]; sp < ®state[NMREG]; ++sp) ! 97: if (MODRM(sp) == (A_XB | i)) ! 98: sp->a_mode = A_NONE; ! 99: } ! 100: ! 101: /* ! 102: * Given a pointer to a CODE node, ! 103: * return 1 if the instruction has no effect on the machine state. ! 104: * Look at the operands of the instruction and the values ! 105: * currently in the registers. ! 106: * Make sure that an instruction that is being used ! 107: * to set the flags is not considered to have no effect. ! 108: */ ! 109: int ! 110: noeffect(ip) register INS *ip; ! 111: { ! 112: register AFIELD *sp, *afp0, *afp1; ! 113: ! 114: afp0 = af_p(ip, 0); ! 115: afp1 = af_p(ip, 1); ! 116: if (ip->i_op == ZSUB) { ! 117: if (MOD(afp0) == A_DR && afp0->a_mode == afp1->a_mode) { ! 118: /* sub reg, reg */ ! 119: sp = ®state[REGM(afp0)]; ! 120: if (MOD(sp) == A_IMM && sp->a_sp == NULL && sp->a_value == 0) { ! 121: /* Value is already $0; check if flags needed */ ! 122: if ((ip = ip->i_fp) == &ins) ! 123: return 0; ! 124: return (ip->i_type!=JUMP || ip->i_rel==ZJMP); ! 125: } ! 126: } ! 127: return 0; ! 128: } else if (ip->i_op == ZLEA) ! 129: return afcompare(A_EA, afp0, afp1); ! 130: else if (ip->i_op == ZMOV) ! 131: return (MOD(afp0)==A_DR && afcompare(0, afp0, afp1)); ! 132: if (ip->i_fp->i_type == EPILOG && (usedregs & (BESI|BEDI|BEBX)) == 0) { ! 133: /* ! 134: * "add %esp, $n" or "pop %ecx" before "leave" has no effect. ! 135: * Watch out for functions which restore register variables, ! 136: * the stack adjust is required before the restores. ! 137: * This knows the details of i386/emit1.c/genepilog() ! 138: * code generation. ! 139: */ ! 140: return ((ip->i_op == ZADD && afp0->a_mode == A_RESP) ! 141: || (ip->i_op == ZPOP && afp0->a_mode == A_RECX)); ! 142: } ! 143: return 0; ! 144: } ! 145: ! 146: /* ! 147: * Try to make a CODE node into a simpler node that ! 148: * performs the same transformation of the machine state. ! 149: * Currently, this just tries to replace memory operands of dual op instructions ! 150: * and push instructions with register data and to simplify ZCMP. ! 151: */ ! 152: void ! 153: simplify(ip) register INS *ip; ! 154: { ! 155: switch (ip->i_op) { ! 156: ! 157: case ZCMP: ! 158: case ZCMPB: ! 159: case ZCMPW: ! 160: simpcompare(ip); ! 161: break; ! 162: ! 163: case ZADC: ! 164: case ZADD: ! 165: case ZAND: ! 166: case ZOR: ! 167: case ZSBB: ! 168: case ZSUB: ! 169: case ZXOR: ! 170: simpoper(af_p(ip, 1)); ! 171: break; ! 172: ! 173: case ZPUSH: ! 174: simpoper(af_p(ip, 0)); ! 175: break; ! 176: } ! 177: } ! 178: ! 179: /* ! 180: * The "afp" points at an AFIELD. ! 181: * If it is a memory AFIELD, look through the processor state ! 182: * to see if a register contains the same value. ! 183: * Adjust the AFIELD to refer to the machine register if found. ! 184: */ ! 185: void ! 186: simpoper(afp) register AFIELD *afp; ! 187: { ! 188: register int i, mode; ! 189: ! 190: mode = MOD(afp); ! 191: if (mode==A_IMM || mode==A_DIR || mode==A_XB) { ! 192: for (i = 0; i < NMREG; i++) { ! 193: if (afcompare(0, ®state[i], afp)) { ! 194: /* Gotcha, simplify the operand. */ ! 195: afp->a_mode = A_DR | i; ! 196: afp->a_sp = NULL; ! 197: afp->a_value = 0; ! 198: ++nsimplify; ! 199: ++changes; ! 200: break; ! 201: } ! 202: } ! 203: } ! 204: } ! 205: ! 206: /* ! 207: * Simplify "cmp %eax, $0" to "or %eax, %eax" ! 208: * (and similarly for word and byte compare). ! 209: * The code generator sometimes generates the less efficient form ! 210: * for TREG patterns, because the TREG could be a stack temporary. ! 211: */ ! 212: simpcompare(ip) register INS *ip; ! 213: { ! 214: register AFIELD *afp1; ! 215: AFIELD *afp0; ! 216: int mode, op; ! 217: ! 218: afp1 = af_p(ip, 1); ! 219: if (MOD(afp1) != A_IMM || afp1->a_sp != NULL || afp1->a_value != 0) ! 220: return; /* second operand is not 0 */ ! 221: afp0 = af_p(ip, 0); ! 222: mode = MOD(afp0); ! 223: op = ip->i_op; ! 224: if (op == ZCMP && mode == A_DR) ! 225: op = ZOR; ! 226: else if (op == ZCMPB && mode == A_BR) ! 227: op = ZORB; ! 228: else if (op == ZCMPW && mode == A_WR) ! 229: op = ZORW; ! 230: else ! 231: return; ! 232: ip->i_op = op; /* change ZCMP? to ZOR? */ ! 233: afp1->a_mode = afp0->a_mode; /* change 0 to register */ ! 234: ++nsimplify; ! 235: ++changes; ! 236: } ! 237: ! 238: /* ! 239: * Look at the CODE node pointed to by "ip", ! 240: * and make the required changes to the processor state. ! 241: * Some special compiler idioms have special checks. ! 242: * Any instruction for which there is no special knowledge ! 243: * is assumed to have no effect on the machine state. ! 244: */ ! 245: void ! 246: track(ip) register INS *ip; ! 247: { ! 248: register AFIELD *sp, *afp0, *afp1; ! 249: register short destmode; ! 250: register short destreg; ! 251: register short length; ! 252: ! 253: afp0 = af_p(ip, 0); ! 254: afp1 = af_p(ip, 1); ! 255: ! 256: /* Special idioms. */ ! 257: if (MOD(afp0) == A_DR && afp0->a_mode == afp1->a_mode) { ! 258: if (ip->i_op == ZOR) ! 259: return; /* or reg, reg */ ! 260: if (ip->i_op == ZSUB) { /* sub reg, reg */ ! 261: sp = ®state[REGM(afp0)]; ! 262: sp->a_mode = A_IMM; /* register becomes $0 */ ! 263: sp->a_sp = NULL; ! 264: sp->a_value = 0; ! 265: return; ! 266: } ! 267: } ! 268: ! 269: switch (ip->i_op) { ! 270: ! 271: /* Clobber all registers. */ ! 272: case ZCALL: ! 273: case ZICALL: ! 274: case ZIXCALL: ! 275: case ZXCALL: ! 276: case ZCMPS: ! 277: case ZCMPSB: ! 278: case ZLODS: ! 279: case ZLODSB: ! 280: case ZMOVS: ! 281: case ZMOVSB: ! 282: case ZSCAS: ! 283: case ZSCASB: ! 284: case ZSTOS: ! 285: case ZSTOSB: ! 286: case ZXCHG: ! 287: case ZXCHGB: ! 288: emptyall(); ! 289: break; ! 290: ! 291: /* Clobber EAX. */ ! 292: case ZCBW: ! 293: case ZCWDE: ! 294: case ZDIVB: ! 295: case ZIDIVB: ! 296: case ZIMULB: ! 297: case ZMULB: ! 298: emptymreg(MEAX); ! 299: break; ! 300: ! 301: /* Clobber ECX. */ ! 302: case ZREPE: ! 303: case ZREPNE: ! 304: emptymreg(MECX); ! 305: break; ! 306: ! 307: /* Clobber EDX. */ ! 308: case ZCDQ: ! 309: case ZCWD: ! 310: emptymreg(MEDX); ! 311: break; ! 312: ! 313: /* Clobber EAX and EDX. */ ! 314: case ZDIV: ! 315: case ZIDIV: ! 316: case ZIMUL: ! 317: case ZMUL: ! 318: emptymreg(MEAX); ! 319: emptymreg(MEDX); ! 320: break; ! 321: ! 322: /* Clobber register or memory. */ ! 323: /* Byte operations. */ ! 324: case ZADDB: ! 325: case ZANDB: ! 326: case ZDECB: ! 327: case ZINCB: ! 328: case ZNEGB: ! 329: case ZNOTB: ! 330: case ZORB: ! 331: case ZRCLB: ! 332: case ZRCRB: ! 333: case ZROLB: ! 334: case ZRORB: ! 335: case ZSALB: ! 336: case ZSARB: ! 337: case ZSHLB: ! 338: case ZSHRB: ! 339: case ZSUBB: ! 340: case ZXORB: ! 341: length = 8; ! 342: goto lab; ! 343: ! 344: /* Word operations. */ ! 345: case ZADDW: ! 346: case ZANDW: ! 347: case ZDECW: ! 348: case ZINCW: ! 349: case ZNEGW: ! 350: case ZNOTW: ! 351: case ZORW: ! 352: case ZSALW: ! 353: case ZSARW: ! 354: case ZSHLW: ! 355: case ZSHRW: ! 356: case ZSUBW: ! 357: case ZXORW: ! 358: case ZIMULW: ! 359: length = 16; ! 360: goto lab; ! 361: ! 362: /* Dword operations. */ ! 363: case ZADC: ! 364: case ZADD: ! 365: case ZAND: ! 366: case ZINC: ! 367: case ZDEC: ! 368: case ZNEG: ! 369: case ZNOT: ! 370: case ZOR: ! 371: case ZPOP: ! 372: case ZRCL: ! 373: case ZRCR: ! 374: case ZROL: ! 375: case ZROR: ! 376: case ZSAL: ! 377: case ZSAR: ! 378: case ZSBB: ! 379: case ZSHL: ! 380: case ZSHR: ! 381: case ZSUB: ! 382: case ZXOR: ! 383: case ZIMULI: ! 384: length = 32; ! 385: lab: ! 386: destmode = MOD(afp0); ! 387: if (destmode==A_DR || destmode==A_BR || destmode == A_WR) { ! 388: /* To register. */ ! 389: destreg = REGM(afp0); ! 390: if (length == 8) ! 391: destreg &= 0x03; /* e.g. AH -> MEAX */ ! 392: emptymreg(destreg); ! 393: } else if (length == 32 && (destmode==A_DIR || destmode==A_XB)) ! 394: emptyaf(afp0); ! 395: else ! 396: emptyall(); ! 397: break; ! 398: ! 399: /* Track LEA. */ ! 400: case ZLEA: ! 401: afupdate(A_EA, afp0, afp1); ! 402: break; ! 403: ! 404: /* Track MOV. */ ! 405: case ZMOV: ! 406: destmode = MOD(afp0); ! 407: if (destmode==A_DR) ! 408: afupdate(0, afp0, afp1); ! 409: else if (destmode==A_DIR || destmode==A_XB) { ! 410: emptyaf(afp0); ! 411: destmode = MOD(afp1); ! 412: if (destmode==A_DR) ! 413: afupdate(0, afp1, afp0); ! 414: } else ! 415: emptyall(); ! 416: break; ! 417: ! 418: /* Track MOVB, MOVW, MOVSX[B], MOVZX[B]. */ ! 419: case ZMOVB: ! 420: case ZMOVW: ! 421: case ZMOVSX: ! 422: case ZMOVSXB: ! 423: case ZMOVZX: ! 424: case ZMOVZXB: ! 425: destmode = MOD(afp0); ! 426: destreg = REGM(afp0); ! 427: if (ip->i_op == ZMOVB && destmode == A_BR) ! 428: emptymreg(destreg&0x03); ! 429: else if (ip->i_op == ZMOVW && destmode == A_WR) ! 430: emptymreg(destreg); ! 431: else if (destmode==A_DR) ! 432: emptymreg(destreg); ! 433: else if (destmode==A_DIR || destmode==A_XB) ! 434: emptyaf(afp0); ! 435: else ! 436: emptyall(); ! 437: break; ! 438: ! 439: /* Not explicitly listed above: no effect on state. */ ! 440: default: ! 441: break; ! 442: } ! 443: } ! 444: ! 445: /* ! 446: * Compare two address fields "afp1" and "afp2". ! 447: * They must be "resolved" to the machine state if registers. ! 448: * The "afp1" argument always is the register side, ! 449: * and is required to have the flags that are set in "flags" in the address. ! 450: * The "afp2" is the lvalue side. ! 451: */ ! 452: int ! 453: afcompare(flag, afp1, afp2) int flag; register AFIELD *afp1, *afp2; ! 454: { ! 455: register short mode; ! 456: ! 457: if ((afp1 = afresolve(afp1, 0)) == NULL) ! 458: return 0; ! 459: if ((afp2 = afresolve(afp2, 0)) == NULL) ! 460: return 0; ! 461: if (afp1->a_mode==A_NONE || afp2->a_mode==A_NONE) ! 462: return 0; ! 463: if (afp1->a_mode != afp2->a_mode) ! 464: return 0; ! 465: mode = MOD(afp1); ! 466: if (mode==A_IMM || mode==A_DIR || mode==A_XB) { ! 467: if (afp1->a_sp != afp2->a_sp) ! 468: return 0; ! 469: if (afp1->a_value != afp2->a_value) ! 470: return 0; ! 471: if ((afp1->a_mode&A_EA) != flag) ! 472: return 0; ! 473: } ! 474: return 1; ! 475: } ! 476: ! 477: /* ! 478: * Update address fields in the processor state table. ! 479: * The arguments have the same functions ! 480: * as their namesakes in "afcompare" (above). ! 481: */ ! 482: void ! 483: afupdate(flag, afp1, afp2) int flag; register AFIELD *afp1, *afp2; ! 484: { ! 485: if ((afp1 = afresolve(afp1, 1)) == NULL) ! 486: cbotch("afupdate"); ! 487: if ((afp2 = afresolve(afp2, 0)) == NULL) ! 488: afp1->a_mode = A_NONE; ! 489: else if (afdependency(afp1, afp2)) ! 490: afp1->a_mode = A_NONE; ! 491: else { ! 492: afp1->a_mode = afp2->a_mode; ! 493: afp1->a_sp = afp2->a_sp; ! 494: afp1->a_value = afp2->a_value; ! 495: if (afp1->a_mode != A_NONE) ! 496: afp1->a_mode |= flag; ! 497: } ! 498: } ! 499: ! 500: /* ! 501: * Resolve an address descriptor to the entry in the processor state. ! 502: * If the entry will not map for some reason, return NULL. ! 503: * If "flag" is set the register descriptor is flushed. ! 504: */ ! 505: AFIELD * ! 506: afresolve(afp, flag) register AFIELD *afp; int flag; ! 507: { ! 508: register short mode, reg; ! 509: ! 510: if ((mode = MOD(afp)) == A_BR || mode == A_WR) ! 511: return NULL; /* do not map byte and word registers */ ! 512: if (mode == A_DR) { ! 513: reg = REGM(afp); ! 514: if (flag != 0) ! 515: emptymreg(reg); ! 516: return ®state[reg]; ! 517: } ! 518: return afp; ! 519: } ! 520: ! 521: /* ! 522: * Given two AFIELD nodes, ! 523: * return true if the second depends on the value of the first. ! 524: * This checks for instructions like "mov bx,3[bx]", ! 525: * where you must not set the contents of "bx" to be "3[bx]". ! 526: */ ! 527: int ! 528: afdependency(afp1, afp2) register AFIELD *afp1, *afp2; ! 529: { ! 530: register int i; ! 531: ! 532: for (i = 0; i < NMREG; i++) ! 533: if (afp1 == ®state[i]) ! 534: return (MODRM(afp2) == (A_XB | i)); ! 535: return 0; ! 536: } ! 537: ! 538: /* ! 539: * Purge any processor state entries that ! 540: * think they are holding the value of "afp". ! 541: * This is used to purge the state of the world when a register ! 542: * is stored into memory. ! 543: */ ! 544: void ! 545: emptyaf(afp) ! 546: register AFIELD *afp; ! 547: { ! 548: register int i; ! 549: ! 550: for (i = 0; i < NMREG; i++) ! 551: if (afcompare(0, ®state[i], afp)) ! 552: emptymreg(i); ! 553: } ! 554: ! 555: /* end of n2/i386/peep.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.