Annotation of coherent/b/bin/c/n2/i386/peep.c, revision 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.