Annotation of researchv9/cmd/sun/c2/stackops.c, revision 1.1.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.