Annotation of coherent/b/bin/c/n2/i386/peep.c, revision 1.1.1.1

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 = &regstate[0]; sp < &regstate[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 = &regstate[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, &regstate[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 = &regstate[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 &regstate[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 == &regstate[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, &regstate[i], afp))
                    552:                        emptymreg(i);
                    553: }
                    554: 
                    555: /* end of n2/i386/peep.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.