Annotation of researchv9/cmd/sun/c2/stackops.c, revision 1.1

1.1     ! root        1: 
        !             2: #ifndef lint
        !             3: static char sccsid[] = "@(#)stackops.c 1.1 86/02/03 Copyr 1985 Sun Micro";
        !             4: #endif
        !             5: 
        !             6: /*
        !             7:  * Copyright (c) 1985 by Sun Microsystems, Inc.
        !             8:  */
        !             9: 
        !            10: #include "as.h"
        !            11: #include "c2.h"
        !            12: 
        !            13: extern struct oper *newoperand();
        !            14: 
        !            15: #define previ( p ) { do p=p->back; while( ISDIRECTIVE(p->op) ); }
        !            16: 
        !            17: #define ispushop(o) ((o)->type_o == T_PREDEC && (o)->value_o == SPREG)
        !            18: #define ispopop(o) ((o)->type_o == T_POSTINC && (o)->value_o == SPREG)
        !            19: 
        !            20: extern int bytesize[];
        !            21: #define BYTESIZE( s ) (bytesize[ (int)(s)])
        !            22: 
        !            23: /*
        !            24:  * replace
        !            25:  *     (b)->move X,sp@-
        !            26:  *          ...
        !            27:  *     (n)->move sp@+,Rn
        !            28:  * with
        !            29:  *     (b)->move X,Rn
        !            30:  *          ...
        !            31:  *     (n) deleted
        !            32:  * Note that if Rn is live after (n), it now becomes live
        !            33:  * at all of the points in between (b) and (n).
        !            34:  */
        !            35: 
        !            36: static NODE *
        !            37: movedef(b,n,ip)
        !            38:     register NODE *b;
        !            39:     NODE *n;
        !            40:     struct ins_bkt *ip;
        !            41: {
        !            42:     register NODE *p;
        !            43:     regmask l;
        !            44: 
        !            45:     if (b->nref == 2)
        !            46:        freeoperand(b->ref[1]);
        !            47:     else 
        !            48:        b->nref = 2;
        !            49:     b->ref[1] = newoperand(n->ref[1]);
        !            50:     installinstruct(b,ip);
        !            51:     n = deletenode(n);
        !            52:     l = n->forw->rlive;
        !            53:     for (p = n; p != b; p = p->back) {
        !            54:        l = p->rlive = compute_normal(p, l);
        !            55:     }
        !            56:     return n;
        !            57: }
        !            58: 
        !            59: /*
        !            60:  * replace
        !            61:  *     (b)->pea X
        !            62:  *          ...
        !            63:  *     (n)->move sp@+,dn
        !            64:  * with
        !            65:  *     (b)->lea X,ar
        !            66:  *          movl ar,dn
        !            67:  *          ...
        !            68:  *     (n)  (deleted)
        !            69:  *
        !            70:  * This is like the previous transformation with an
        !            71:  * adjustment for the fact that 'lea' does not work
        !            72:  * with a d-register destination.
        !            73:  */
        !            74: static NODE*
        !            75: movedef2(b, n, ar, ip)
        !            76:     register NODE *b;
        !            77:     register NODE *n;
        !            78:     int ar;
        !            79:     struct ins_bkt *ip;
        !            80: {
        !            81:     register NODE *p;
        !            82:     register struct oper *o;
        !            83:     regmask l;
        !            84: 
        !            85:     /*
        !            86:      * rewrite (b) as "lea X,ar"
        !            87:      */
        !            88:     b->nref = 2;
        !            89:     o = newoperand(n->ref[1]);
        !            90:     o->value_o = ar;
        !            91:     b->ref[1] = o;
        !            92:     installinstruct(b,ip);
        !            93:     /*
        !            94:      * insert "movl ar,dn" following (b)
        !            95:      */
        !            96:     p = new();
        !            97:     p->nref = 2;
        !            98:     o = newoperand(o);
        !            99:     o->value_o = ar;
        !           100:     p->ref[0] = o;
        !           101:     o = newoperand(o);
        !           102:     o->value_o = n->ref[1]->value_o;
        !           103:     p->ref[1] = o;
        !           104:     cannibalize(p, "movl");
        !           105:     insert(p,b);
        !           106:     /*
        !           107:      * delete (n), update register lifetime information
        !           108:      */
        !           109:     n = deletenode(n);
        !           110:     l = n->forw->rlive;
        !           111:     for (p = n; p != b; p = p->back) {
        !           112:        l = p->rlive = compute_normal(p, l);
        !           113:     }
        !           114:     return n;
        !           115: }
        !           116: 
        !           117: 
        !           118: /*
        !           119:  * replace
        !           120:  *     (b)->move X,sp@-
        !           121:  *          ...
        !           122:  *     (n)-><op> sp@+,...
        !           123:  * with
        !           124:  *     (b) (deleted)
        !           125:  *          ...
        !           126:  *     (n)-><op> X,...
        !           127:  * Note that if X is a register, it now becomes live
        !           128:  * at all of the points in between (b) and (n).
        !           129:  */
        !           130: static NODE *
        !           131: moveuse(b, n, srce, ip)
        !           132:     NODE *b,*n;
        !           133:     struct oper *srce;
        !           134:     struct ins_bkt *ip;
        !           135: {
        !           136:     register NODE *p;
        !           137:     regmask l;
        !           138: 
        !           139:     freeoperand(n->ref[0]);
        !           140:     n->ref[0] = srce;
        !           141:     b = deletenode(b);
        !           142:     installinstruct(n,ip);
        !           143:     l = n->forw->rlive;
        !           144:     for (p = n; p != b; p = p->back) {
        !           145:        l = p->rlive = compute_normal(p, l);
        !           146:     }
        !           147:     return(n);
        !           148: }
        !           149: 
        !           150: 
        !           151: /*
        !           152:  * returns the "extended mode" instruction, if any,
        !           153:  * corresponding to the the instruction described by (ip).
        !           154:  */
        !           155: struct ins_bkt *
        !           156: extendedop(ip)
        !           157:     struct ins_bkt *ip;
        !           158: {
        !           159:     char buf[64];
        !           160: 
        !           161:     (void)strcpy(buf, ip->text_i);
        !           162:     buf[strlen(buf)-1] = 'x';
        !           163:     return(sopcode(buf));
        !           164: }
        !           165: 
        !           166: /*
        !           167:  * returns 1 if operands (op1) and (op2) may overlap
        !           168:  */
        !           169: int
        !           170: mayoverlap(op1, op2, subop1, subop2)
        !           171:     register struct oper *op1;
        !           172:     register struct oper *op2;
        !           173:     subop_t subop1;
        !           174:     subop_t subop2;
        !           175: {
        !           176:     int r1, r2;
        !           177:     struct sym_bkt *sym1, *sym2;
        !           178:     int lb1, lb2, ub1, ub2;    /* byte offset bounds of op1 and op2 */
        !           179:     int glb, lub;              /* greatest lower & least upper bounds */
        !           180: 
        !           181:     r1 = -1;
        !           182:     r2 = -1;
        !           183:     lb1 = 0;
        !           184:     lb2 = 0;
        !           185:     sym1 = NULL;
        !           186:     sym2 = NULL;
        !           187:     switch(op1->type_o) {
        !           188:     case T_IMMED:
        !           189:        return(0);
        !           190:     case T_REG:
        !           191:        return(op2->type_o == T_REG && op1->value_o == op2->value_o);
        !           192:     case T_POSTINC:
        !           193:     case T_PREDEC:
        !           194:        /* assume sp@+ and sp@- only overlap with each other */
        !           195:        if (op1->value_o == SPREG) {
        !           196:            if (op2->type_o == T_POSTINC || op2->type_o == T_PREDEC)
        !           197:                return(op2->value_o == SPREG);
        !           198:            return(0);
        !           199:        }
        !           200:        return(1);
        !           201:     case T_DISPL:
        !           202:        r1 = op1->reg_o;
        !           203:        /* fall through */
        !           204:     case T_ABSS:
        !           205:     case T_ABSL:
        !           206:     case T_NORMAL:
        !           207:        sym1 = op1->sym_o;
        !           208:        lb1 = op1->value_o;
        !           209:        ub1 = lb1 + BYTESIZE(subop1)-1;
        !           210:        break;
        !           211:     case T_DEFER:
        !           212:        r1 = op1->value_o;
        !           213:        ub1 = lb1 + BYTESIZE(subop1)-1;
        !           214:        break;
        !           215:     }
        !           216:     switch(op2->type_o) {
        !           217:     case T_IMMED:
        !           218:     case T_REG:
        !           219:        return(0);
        !           220:     case T_POSTINC:
        !           221:     case T_PREDEC:
        !           222:        return(op2->value_o != SPREG);
        !           223:     case T_DISPL:
        !           224:        r2 = op2->reg_o;
        !           225:        /* fall through */
        !           226:     case T_ABSS:
        !           227:     case T_ABSL:
        !           228:     case T_NORMAL:
        !           229:        sym2 = op2->sym_o;
        !           230:        lb2 = op2->value_o;
        !           231:        ub2 = lb2 + BYTESIZE(subop2)-1;
        !           232:        goto compute_overlap;
        !           233:     case T_DEFER:
        !           234:        r2 = op2->value_o;
        !           235:        ub2 = lb2 + BYTESIZE(subop2)-1;
        !           236:        /* fall through */
        !           237:     compute_overlap:
        !           238:        if (r1 != r2 || sym1 != sym2)
        !           239:            return(1);
        !           240:        ub1 = lb1 + BYTESIZE(subop1)-1;
        !           241:        ub2 = lb2 + BYTESIZE(subop2)-1;
        !           242:        glb = lb1 > lb2 ? lb1 : lb2;
        !           243:        lub = ub1 < ub2 ? ub1 : ub2;
        !           244:        return(glb <= lub);
        !           245:     default:
        !           246:        return(1);
        !           247:     }
        !           248: }
        !           249: 
        !           250: /*
        !           251:  * returns 1 if two operands are in adjacent *addressable* words
        !           252:  */
        !           253: int
        !           254: adjacent(op1, op2)
        !           255:     register struct oper *op1,*op2;
        !           256: {
        !           257:     int w;
        !           258:     struct oper temp;
        !           259: 
        !           260:     if (op1->type_o != op2->type_o) {
        !           261:        /* make DEFER operands look like DISPL operands */
        !           262:        if (op1->type_o == T_DEFER) {
        !           263:            temp.type_o = T_DISPL;
        !           264:            temp.reg_o = op1->value_o;
        !           265:            temp.value_o = 0;
        !           266:            op1 = &temp;
        !           267:        } else if (op2->type_o == T_DEFER) {
        !           268:            temp.type_o = T_DISPL;
        !           269:            temp.reg_o = op2->value_o;
        !           270:            temp.value_o = 0;
        !           271:            op2 = &temp;
        !           272:        } else {
        !           273:            return 0;
        !           274:        }
        !           275:     }
        !           276:     switch (op1->type_o){
        !           277:     case T_IMMED:
        !           278:     case T_NORMAL:
        !           279:     case T_ABSS:
        !           280:     case T_ABSL:
        !           281:        if (op1->sym_o != op2->sym_o) return 0; /* oops -- complex*/
        !           282:        /* fall through */
        !           283:     case T_REG: 
        !           284:     case T_DEFER:
        !           285:     case T_POSTINC:
        !           286:     case T_PREDEC:
        !           287:        if (op1->value_o + sizeof(long) != op2->value_o) return 0;
        !           288:        break;
        !           289:     case T_INDEX:
        !           290:        if (op1->disp_o + sizeof(long) != op2->disp_o) return 0;
        !           291:        /* fall through */
        !           292:     case T_DISPL:
        !           293:        if (op1->reg_o != op2->reg_o) return 0;
        !           294:        if (op1->value_o + sizeof(long) != op2->value_o) return 0;
        !           295:        break;
        !           296:     default:
        !           297:        return 0;
        !           298:     }
        !           299:     return 1;
        !           300: }
        !           301: 
        !           302: /*
        !           303:  * returns 1 if node (n) may use/modify operand (o)
        !           304:  */
        !           305: int
        !           306: may_touch(n, o, osubop, touchmask)
        !           307:     register NODE *n;
        !           308:     register struct oper *o;
        !           309:     int osubop;        /* subop of instruction using (o) */
        !           310:     register touchmask;
        !           311: {
        !           312:     register int i,v;
        !           313:     regmask l;
        !           314: 
        !           315:     switch(o->type_o) {
        !           316:     case T_IMMED:
        !           317:        return 0;
        !           318:     case T_REG:
        !           319:        if (touchmask&RMASK == touchmask)
        !           320:            return inmask(o->value_o,n->ruse);
        !           321:        if (touchmask&WMASK == touchmask)
        !           322:            return inmask(o->value_o,n->rset);
        !           323:        if (touchmask)
        !           324:            return inmask(o->value_o,addmask(n->rset,n->ruse));
        !           325:        return 0;
        !           326:     default:
        !           327:        /*
        !           328:         * for each operand modified by (n), see if
        !           329:         * a potential overlap with (o) exists.
        !           330:         */
        !           331:        if (n->op == OP_CALL)
        !           332:            return 1;
        !           333:        v = make_touchop(n, n->instr->touchop_i);
        !           334:        for (i = 0; i < n->nref; i++) {
        !           335:            if (v&touchmask) {
        !           336:                if (mayoverlap(o, n->ref[i], osubop, n->subop))
        !           337:                    return 1;
        !           338:            }
        !           339:            v >>= TOUCHWIDTH;
        !           340:        }
        !           341:     }
        !           342:     return 0;
        !           343: }
        !           344: 
        !           345: 
        !           346: /*
        !           347:  * reduce stack traffic exposed by inline expansion
        !           348:  * of procedures
        !           349:  */
        !           350: int
        !           351: stackops()
        !           352: {
        !           353:     register NODE *n;
        !           354:     register NODE *p,*b;
        !           355:     register struct ins_bkt *ip;
        !           356:     register struct oper *o;
        !           357:     register int regno;
        !           358:     extern NODE *deletenode();
        !           359:     int changes;
        !           360:     regmask l;
        !           361:     int offset;
        !           362:     int r;
        !           363: 
        !           364:     changes = 0;
        !           365:     for (n=first.forw; n != &first; n=n->forw) {
        !           366: 
        !           367:        /*
        !           368:         * Pattern #0:
        !           369:         *      (0) sub  #X,sp
        !           370:         *      (1) add  #Y,sp  -or- (1) lea sp@(Y),sp
        !           371:         * Rewrite:
        !           372:         *      delete both, or use a single addql, subql, or lea
        !           373:         */
        !           374:        if (n->op == OP_SUB
        !           375:          && n->ref[1]->type_o == T_REG && n->ref[1]->value_o == SPREG
        !           376:          && n->ref[0]->type_o == T_IMMED) {
        !           377:            p = n->forw;
        !           378:            switch(p->op) {
        !           379:            case OP_ADD:
        !           380:                o = p->ref[1];
        !           381:                if (o->type_o == T_REG && o->value_o == SPREG
        !           382:                  && p->ref[0]->type_o == T_IMMED) {
        !           383:                    goto delete_adjust;
        !           384:                }
        !           385:                break;
        !           386:            case OP_LEA:
        !           387:                o = p->ref[1];
        !           388:                if (o->type_o == T_REG && o->value_o == SPREG
        !           389:                  && p->ref[0]->type_o == T_DISPL
        !           390:                  && p->ref[0]->reg_o == SPREG ) {
        !           391:                    goto delete_adjust;
        !           392:                }
        !           393:                break;
        !           394:            delete_adjust:
        !           395:                offset = n->ref[0]->value_o - p->ref[0]->value_o;
        !           396:                p = deletenode(p);
        !           397:                if (offset == 0) {
        !           398:                    n = deletenode(n);
        !           399:                } else if (offset >= 1 && offset <= 8) {
        !           400:                    n->ref[0]->value_o = offset;
        !           401:                    installinstruct(n, sopcode("addql"));
        !           402:                } else if (offset <= -8 && offset >= -1) {
        !           403:                    n->ref[0]->value_o = -offset;
        !           404:                    installinstruct(n, sopcode("subql"));
        !           405:                } else {
        !           406:                    o = n->ref[0];
        !           407:                    o->type_o = T_DISPL;
        !           408:                    o->reg_o = SPREG;
        !           409:                    o->value_o = offset;
        !           410:                    installinstruct(n, sopcode("lea"));
        !           411:                }
        !           412:                continue;
        !           413:            }
        !           414:        }
        !           415: 
        !           416:        /*
        !           417:         * Pattern #1:
        !           418:         *      (b) movl  X,sp@-
        !           419:         *      ...
        !           420:         *      (n) <op>  sp@+,...
        !           421:         *
        !           422:         * if possible, rewrite as
        !           423:         *      (b) (deleted)
        !           424:         *      ...
        !           425:         *      (n) <op>  X,...
        !           426:         *
        !           427:         * Requirements:
        !           428:         *      X must not be a control register or i/o device.
        !           429:         *      X must not be modified in the interim.
        !           430:         *      Side effects of X must not be used in the interim.
        !           431:         */
        !           432:        if (ISINSTRUC(n->op) && n->ref[0] != NULL && ispopop(n->ref[0])) {
        !           433:            b = n;
        !           434:            o = NULL;
        !           435:            do {
        !           436:                previ(b);
        !           437:                if (b->op == OP_FIRST || b->op == OP_LABEL
        !           438:                  || ISBRANCH(b->op)) {
        !           439:                    /* flow of control to reach this point is unknown */
        !           440:                    break;
        !           441:                }
        !           442:                if (b->op == OP_PEA) {
        !           443:                    switch(b->ref[0]->type_o) {
        !           444:                    case T_ABSS:
        !           445:                    case T_ABSL:
        !           446:                    case T_NORMAL:
        !           447:                        /*
        !           448:                         * srce is #X
        !           449:                         */
        !           450:                        o = newoperand(b->ref[0]);
        !           451:                        o->type_o = T_IMMED;
        !           452:                        b->subop = SUBOP_L;
        !           453:                    }
        !           454:                    break;
        !           455:                }
        !           456:                if (b->op == OP_CLR && ispushop(b->ref[0])) {
        !           457:                    /*
        !           458:                     * srce is #0
        !           459:                     */
        !           460:                    o = newoperand(b->ref[0]);
        !           461:                    o->type_o = T_IMMED;
        !           462:                    o->value_o = 0;
        !           463:                    break;
        !           464:                }
        !           465:                if (b->op == OP_MOVE && ispushop(b->ref[1])) {
        !           466:                    o = newoperand(b->ref[0]);
        !           467:                    break;
        !           468:                }
        !           469:                if (inmask(SPREG,b->rset) || inmask(SPREG,b->ruse)) {
        !           470:                    /* unknown use/modification of sp */
        !           471:                    break;
        !           472:                }
        !           473:            } while(1);
        !           474:            /*
        !           475:             * If the preceding search yielded a usable operand,
        !           476:             * determine whether its use can be moved from node
        !           477:             * (b) to (n).
        !           478:             */
        !           479:            if (o != NULL) {
        !           480:                l = submask(b->rset, MAKEWMASK(SPREG, LW));
        !           481:                if ( o->type_o == T_REG && !datareg(o->value_o)
        !           482:                  || o->type_o != T_IMMED && o->type_o != T_REG && !cancache(o)
        !           483:                  || !emptymask(andmask(l, b->forw->rlive))) {
        !           484:                    /*
        !           485:                     * x is a control register or might be an i/o device,
        !           486:                     * or has non-trivial side effects: cannot move.
        !           487:                     */
        !           488:                    freeoperand(o);
        !           489:                    o = NULL;
        !           490:                } else {
        !           491:                    /* search for defs of X and defs affecting access to X */
        !           492:                    l = submask(b->ruse, MAKERMASK(SPREG, LR));
        !           493:                    p = n;
        !           494:                    previ(p);
        !           495:                    while (p != b) {
        !           496:                        if (may_touch(p, o, b->subop, WMASK)) {
        !           497:                            freeoperand(o);     /* bail out */
        !           498:                            o = NULL;
        !           499:                            break;
        !           500:                        }
        !           501:                        if (!emptymask(andmask(l, p->rset))) {
        !           502:                            /*
        !           503:                             * (p) defines register used at (b);  if (p)
        !           504:                             * is a simple register load, and if the lifetime
        !           505:                             * of the register is restricted to (p)..(n),
        !           506:                             * we may be able to use a different register,
        !           507:                             * eliminating the conflict
        !           508:                             */
        !           509:                            int r1,r2;
        !           510:                            if (p->op != OP_MOVE
        !           511:                              || p->ref[1]->type_o != T_REG ) {
        !           512:                                freeoperand(o); /* bail out */
        !           513:                                o = NULL;
        !           514:                                break;
        !           515:                            }
        !           516:                            r1 = p->ref[1]->value_o;
        !           517:                            r2 = find_freereg(p, n, reg_access[r1]);
        !           518:                            if (r2 == -1 || !can_reassign_reg(p, n, r1, r2)) {
        !           519:                                freeoperand(o); /* bail out */
        !           520:                                o = NULL;
        !           521:                                break;
        !           522:                            }
        !           523:                            reassign_reg(p, n, r1, r2);
        !           524:                        }
        !           525:                        previ(p);
        !           526:                    }
        !           527:                }
        !           528:            }
        !           529:            /*
        !           530:             * If it is feasible to move the use of the operand X,
        !           531:             * find out whether X is a suitable source operand of
        !           532:             * the instruction at (n).
        !           533:             */
        !           534:            if (o != NULL) {
        !           535:                if (BYTESIZE(b->subop) == BYTESIZE(n->subop)
        !           536:                  && operand_ok(n->instr, o, n->ref[1], n->ref[2])) {
        !           537:                    n = moveuse(b, n, o, n->instr);
        !           538:                    changes++;
        !           539:                    continue;
        !           540:                }
        !           541:                /*
        !           542:                 * if X is a floating point register, try rewriting
        !           543:                 * node (n) using an extended floating point opcode
        !           544:                 */
        !           545:                if (o->type_o == T_REG && freg(o->value_o)) {
        !           546:                    ip = extendedop(n->instr);
        !           547:                    if (ip != NULL
        !           548:                      && operand_ok(ip, o, n->ref[1], n->ref[2])) {
        !           549:                        n = moveuse(b, n, o, ip);
        !           550:                        changes++;
        !           551:                        continue;
        !           552:                    }
        !           553:                }
        !           554:                /*
        !           555:                 * if X is an addressable double operand and the
        !           556:                 * the use of sp@+ occurs in a double precision
        !           557:                 * floating point operation, use X directly.
        !           558:                 */
        !           559:                if (n->subop == SUBOP_D && o->type_o != T_REG
        !           560:                  && b->back->op == OP_MOVE
        !           561:                  && b->back->subop == SUBOP_L
        !           562:                  && ispushop(b->back->ref[1])
        !           563:                  && adjacent(o, b->back->ref[0])) {
        !           564:                    (void) deletenode(b->back);
        !           565:                    n = moveuse(b, n, o, n->instr);
        !           566:                    changes++;
        !           567:                    continue;
        !           568:                }
        !           569:                freeoperand(o); /* give up */
        !           570:            } /* if o != NULL */
        !           571:        } /* if ISINSTRUCT... */
        !           572: 
        !           573:        /*
        !           574:         * Other patterns assume the instruction at (n) is a move.
        !           575:         */
        !           576:        if (n->op != OP_MOVE)
        !           577:            continue;
        !           578: 
        !           579:        /*
        !           580:         * Pattern #2:
        !           581:         *      (b) move X,sp@-
        !           582:         *          ....
        !           583:         *      (n) move sp@+,rn
        !           584:         * If possible, rewrite as:
        !           585:         *      (b) move X,rn
        !           586:         *          ....
        !           587:         *      (n) (deleted)
        !           588:         * Requirements:
        !           589:         *      Rn must neither be used nor set in the interim.
        !           590:         *      If rn is an a-register, condition codes must not
        !           591:         *      be live immediately following (b).
        !           592:         *      If rn is not an a-register, condition codes must not
        !           593:         *      be live immediately following (n).
        !           594:         */
        !           595:        o = n->ref[0];
        !           596:        regno = n->ref[1]->value_o;
        !           597:        if(ispopop(o) && n->ref[1]->type_o == T_REG
        !           598:          && !(dreg(regno) && inmask(CCREG,n->forw->rlive))
        !           599:          && !(freg(regno) && inmask(FPCCREG, n->forw->rlive))) {
        !           600:            b = n;
        !           601:            do {
        !           602:                previ(b);
        !           603:                if (b->op == OP_FIRST || b->op == OP_LABEL
        !           604:                  || ISBRANCH(b->op)) {
        !           605:                    /* flow of control to reach this point is unknown */
        !           606:                    break;
        !           607:                }
        !           608:                if (b->op == OP_PEA) {
        !           609:                    /* note: PEA does not set the condition codes */
        !           610:                    if (areg(regno)) {
        !           611:                        /*
        !           612:                         * rewrite as: lea <srce>,areg
        !           613:                         */
        !           614:                        n = movedef(b,n,sopcode("lea"));
        !           615:                        changes++;
        !           616:                    } else if ((r = dead_areg(b)) != -1
        !           617:                      && !inmask(CCREG,b->forw->rlive)) {
        !           618:                        /*
        !           619:                         * rewrite as:  lea <srce>,areg;
        !           620:                         *              movl areg,rn
        !           621:                         */
        !           622:                        n = movedef2(b,n,r,sopcode("lea"));
        !           623:                        changes++;
        !           624:                    } else {
        !           625:                        switch(b->ref[0]->type_o) {
        !           626:                        case T_ABSS:
        !           627:                        case T_ABSL:
        !           628:                        case T_NORMAL:
        !           629:                            /*
        !           630:                             * rewrite as: movl #<srce>,reg
        !           631:                             */
        !           632:                            b->ref[0]->type_o = T_IMMED;
        !           633:                            n = movedef(b,n,sopcode("movl"));
        !           634:                            changes++;
        !           635:                        }
        !           636:                    }
        !           637:                    break;
        !           638:                }
        !           639:                if (b->op == OP_CLR && ispushop(b->ref[0])
        !           640:                  && b->subop == SUBOP_L
        !           641:                  && !(areg(regno) && inmask(CCREG,b->forw->rlive))) {
        !           642:                    /*
        !           643:                     * rewrite as: movl #0,reg
        !           644:                     */
        !           645:                    b->ref[0]->type_o = T_IMMED;
        !           646:                    b->ref[0]->value_o = 0;
        !           647:                    n = movedef(b,n,sopcode("movl"));
        !           648:                    changes++;
        !           649:                    break;
        !           650:                }
        !           651:                if (b->op == OP_MOVE && ispushop(b->ref[1])
        !           652:                  && b->subop == SUBOP_L
        !           653:                  && !(areg(regno) && inmask(CCREG,b->forw->rlive))) {
        !           654:                    /*
        !           655:                     * try to change into MOVE <srce>,reg
        !           656:                     * beware floating point register operands
        !           657:                     */
        !           658:                    if (!freg(regno)) {
        !           659:                        /* reg is a-reg or d-reg */
        !           660:                        if (b->subop == SUBOP_D || b->subop == SUBOP_X) {
        !           661:                            /* can't move doubles to a register pair */
        !           662:                        } else if (areg(regno)
        !           663:                          && b->ref[0]->type_o == T_REG
        !           664:                          && freg(b->ref[0]->value_o)) {
        !           665:                            /* can't move fp reg to a-reg */
        !           666:                        } else if (b->subop == n->subop) {
        !           667:                            /* easy case */
        !           668:                            n = movedef(b,n,n->instr);
        !           669:                            changes++;
        !           670:                        }
        !           671:                    } else {
        !           672:                        o = b->ref[0];
        !           673:                        if (o->type_o == T_REG && freg(o->value_o)) {
        !           674:                            /*
        !           675:                             * freg-freg move
        !           676:                             */
        !           677:                            n = movedef(b,n,sopcode("fmovex"));
        !           678:                        } else if (b->subop == n->subop
        !           679:                          && BYTESIZE(n->subop) <= sizeof(long)
        !           680:                          && !(o->type_o == T_REG && areg(o->value_o))) {
        !           681:                            /*
        !           682:                             * move single word to freg
        !           683:                             */
        !           684:                            n = movedef(b,n,n->instr);
        !           685:                            changes++;
        !           686:                        } else if (n->subop == SUBOP_D
        !           687:                          && o->type_o != T_REG
        !           688:                          && b->back->op == OP_MOVE
        !           689:                          && b->back->subop == SUBOP_L
        !           690:                          && ispushop(b->back->ref[1])
        !           691:                          && adjacent(o, b->back->ref[0])) {
        !           692:                            /*
        !           693:                             * move addressable double operand to freg
        !           694:                             */
        !           695:                            (void) deletenode(b->back);
        !           696:                            b->subop = SUBOP_D;
        !           697:                            n = movedef(b,n,n->instr);
        !           698:                            changes++;
        !           699:                        }
        !           700:                        /* else forget it! */
        !           701:                    }
        !           702:                    break;
        !           703:                }
        !           704:                if (inmask(regno,b->rset) || inmask(regno,b->ruse)) {
        !           705:                    /* dest reg was used or modified along the way */
        !           706:                    break;
        !           707:                }
        !           708:                if (inmask(SPREG,b->rset) || inmask(SPREG,b->ruse)) {
        !           709:                    /* some other use/modification of sp */
        !           710:                    break;
        !           711:                }
        !           712:            } while(1);
        !           713:        }
        !           714: 
        !           715:        /*
        !           716:         * Pattern #3:
        !           717:         *      (b) move sp@+,rn
        !           718:         *          ....
        !           719:         *      (n) move rn,sp@-
        !           720:         *
        !           721:         * if possible, rewrite as
        !           722:         *      (b) move sp@,rn
        !           723:         *          ....
        !           724:         *      (n) (deleted)
        !           725:         *
        !           726:         * requirements:
        !           727:         *      Rn must not be used or set in the interim.
        !           728:         *      Condition codes must not be live after either (b) or (n).
        !           729:         */
        !           730:        o = n->ref[1];
        !           731:        if (ispushop(o) && n->ref[0]->type_o == T_REG
        !           732:          && datareg(n->ref[0]->value_o)
        !           733:          && !inmask(CCREG,n->forw->rlive)
        !           734:          && !inmask(FPCCREG, n->forw->rlive)) {
        !           735:            regno = n->ref[0]->value_o;
        !           736:            b = n;
        !           737:            do {
        !           738:                previ(b);
        !           739:                if (b->op == OP_FIRST || b->op == OP_LABEL
        !           740:                  || ISBRANCH(b->op)) {
        !           741:                    /* flow of control to reach this point is unknown */
        !           742:                    break;
        !           743:                }
        !           744:                if (b->op == OP_MOVE && ispopop(b->ref[0])
        !           745:                  && b->subop == n->subop
        !           746:                  && sameops(b->ref[1], n->ref[0])
        !           747:                  && !inmask(CCREG, b->forw->rlive)
        !           748:                  && !inmask(FPCCREG, b->forw->rlive)) {
        !           749:                    /* pushing same value that was just popped */
        !           750:                    n = deletenode(n);
        !           751:                    b->ref[0]->type_o = T_DEFER;
        !           752:                    installinstruct(b, b->instr);
        !           753:                    l = n->forw->rlive;
        !           754:                    for (p = n; p != b; p = p->back) {
        !           755:                        l = p->rlive = compute_normal(p, l);
        !           756:                    }
        !           757:                    changes++;
        !           758:                    break;
        !           759:                }
        !           760:                if (inmask(regno,b->rset) || inmask(regno,b->ruse)) {
        !           761:                    /* reg was used/modified along the way */
        !           762:                    break;
        !           763:                }
        !           764:                if (inmask(SPREG,b->rset) || inmask(SPREG,b->ruse)) {
        !           765:                    /* some other use/modification of sp */
        !           766:                    break;
        !           767:                }
        !           768:            } while(1);
        !           769:        } /* if */
        !           770: 
        !           771:     } /* for */
        !           772:     return(changes);
        !           773: }

unix.superglobalmegacorp.com

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