Annotation of researchv9/jerq/sgs/optim/w2opt.c, revision 1.1.1.1

1.1       root        1: /* @(#) w2opt.c: 1.6 4/28/84                           */
                      2: /* w2opt.c
                      3: **
                      4: **     3B20S optimizer -- two instruction peephole window
                      5: **
                      6: **
                      7: ** This module contains the code that improves two-instruction
                      8: ** sequences.  The general scheme is to put those improvements
                      9: ** first which result in removing code, followed by the others.
                     10: **
                     11: ** In some cases we play around with the live/dead information
                     12: ** to convince the one-instruction window not to throw away
                     13: ** code we need.  This is particularly evident when we remove
                     14: ** redundant compares:  we want to make sure that the instruction
                     15: ** that calculates the result indicators does not get deleted.
                     16: */
                     17: 
                     18: /* Some general caveats (learned the hard way):
                     19: **
                     20: **     1.  When instructions get interchanged, we must take care that
                     21: **         we don't alter the condition codes that would have resulted
                     22: **         when executing the instructions in their original order.
                     23: **     2.  We can't move adds to %sp, since we may move them after the
                     24: **         place which refers to the newly allocated space on the stack.
                     25: */
                     26: 
                     27: /* #include "defs" -- optim.h takes care of this */
                     28: #include "optim.h"
                     29: #include "optutil.h"
                     30: 
                     31: extern int sprintf();
                     32: /* w2opt -- 2-instruction peephole window */
                     33: 
                     34: boolean                                        /* true if changes made */
                     35: w2opt(pf,pl)
                     36: register NODE * pf;                    /* first instruction node of window */
                     37: register NODE * pl;                    /* second instruction node */
                     38: {
                     39:     int cop1 = pf->op;                 /* op code number of first inst. */
                     40:     int cop2 = pl->op;                 /* op code number of second inst. */
                     41: 
                     42:     int opn;                           /* op code number (for istriadic) */
                     43:     char * opst;                       /* op code string (for istriadic) */
                     44: 
                     45:     boolean f;                         /* temporary boolean used to
                     46:                                        ** distinguish cases below
                     47:                                        */
                     48:     int temp;                          /* general integer temporary */
                     49:     long templ;                                /* general long temporary */
                     50:     int src1, dst1;                    /* sizes of movX source, destination */
                     51:     int src2, dst2;                    /* sizes of second such movX */
                     52: /* merge moves back into triadic
                     53: **
                     54: **     opw3 O1,O2,R
                     55: **     movw R,O3               ->      op3 O1,O2,O3
                     56: **
                     57: **     if R dead
                     58: **
                     59: **     We depend on the 1-instruction peephole to break such instructions
                     60: **     apart again if appropriate.
                     61: */
                     62: 
                     63: 
                     64:     if (
                     65:            istriadic(pf,&opn,&opst)
                     66:        &&  cop2 == MOVW
                     67:        &&  isdead(pl->op1,pl)          /* also tests whether reg. */
                     68:        &&  strcmp(pf->op3,pl->op1) == 0
                     69:        &&  ! usesreg(pl->op2,pl->op1)  /* register not used in destination */
                     70:        )
                     71:     {
                     72:        wchange();                      /* making a change */
                     73:        pf->op3 = pl->op2;              /* copy operand pointer */
                     74:        makedead(pl->op1,pf);           /* turn off liveness of R in op3 */
                     75:        if (! isdead(pl->op2,pl))
                     76:            makelive(pl->op2,pf);       /* turn on liveness of O3, in case
                     77:                                        ** it's a register
                     78:                                        */
                     79:        lmrgin1(pf,pl,pf);              /* preserve line number info */ 
                     80:        mvlivecc(pl);                   /* preserve condition code info */
                     81:        DELNODE(pl);                    /* delete second node */
                     82:        return(true);
                     83:     }
                     84: /* Combine two dyadics into a triadic, if possible.
                     85: **
                     86: ** This improvement is useful on processors for which triadics are
                     87: ** better than dyadics.
                     88: **
                     89: **     movw O2,O3
                     90: **     opw2 O1,O3              ->      op3 O1,O2,O3
                     91: **
                     92: **     if O1 does not use O3 in any way
                     93: */
                     94: 
                     95: #ifdef IMPTRIAD
                     96: #ifdef M32                             /* applies only to BELLMAC-32 */
                     97: 
                     98:        if (   cop1 == MOVW
                     99:            && totriadic(pl, &opn, &opst) /* check whether dyadic can go
                    100:                                          ** to triadic
                    101:                                          */
                    102:            && strcmp(pf->op2, pl->op2) == 0
                    103:            && ! usesvar(pl->op1, pf->op2)
                    104:            && ( isiros(pf->op1) || isiros(pl->op1) )
                    105:            && isiros(pf->op2)          /* safe from mmio */
                    106:            )
                    107:        {
                    108:            wchange();                  /* we're changing something */
                    109: 
                    110:            /* make changes to second instruction */
                    111: 
                    112:            pl->op3 = pl->op2;          /* make room for new operand */
                    113:            pl->op2 = pf->op1;          /* copy from first inst. */
                    114:            chgop(pl, opn, opst);       /* change opcode to triadic */
                    115:            lmrgin2(pf,pl,pl);  /* preserve line number info */ 
                    116:            mvlivecc(pf);               /* preserve condition code info */
                    117:            DELNODE(pf);                /* delete first inst. */
                    118:            return(true);
                    119:        }
                    120: 
                    121: #endif /* def M32 */
                    122: #endif /* IMPTRIAD */
                    123: /* Remove unnecessary movw's before compares.
                    124: **
                    125: **     movw O1,R
                    126: **     cmpw O2,R               ->      cmpw O2,O1
                    127: ** or
                    128: **
                    129: **     movw O1,R
                    130: **     cmpw R,O2               ->      cmpw O1,O2
                    131: **
                    132: **     if R dead after cmpw
                    133: **/
                    134: 
                    135:     if (
                    136:            cop1 == MOVW
                    137:        &&  cop2 == CMPW
                    138:        &&  isdead(pf->op2,pl)           /* (implicit isreg test, too) */
                    139:        &&  (
                    140:                ( (f = samereg(pf->op2,pl->op1)) 
                    141:                       && ! usesreg(pl->op2,pl->op1)
                    142:                       && ( isiros(pf->op1) || isiros(pl->op2) )
                    143:                                        /* safe from mmio */
                    144:                       )
                    145:             || ( samereg(pf->op2,pl->op2) && ! usesreg(pl->op1,pl->op2) )
                    146:            )
                    147:        )
                    148:     {
                    149:        wchange();                      /* flag changes */
                    150:        if (f)                          /* true if second case above */
                    151:            pl->op1 = pf->op1;
                    152:        else
                    153:            pl->op2 = pf->op1;
                    154:        lmrgin1(pf,pl,pl);              /* preserve line number info */ 
                    155:        mvlivecc(pf);           /* preserve condition code info */
                    156:        DELNODE(pf);                    /* discard movw */
                    157:        return(true);
                    158:     }
                    159: /* Eliminate compares against zero if preceded by instruction that
                    160: ** sets result indicators.  Because some 3B20S instructions do not
                    161: ** set all result indicators, we can only discard compares after
                    162: ** those instructions that set all of the relevant ones.  w3opt
                    163: ** takes care of those which set a limited range of result indicators,
                    164: ** but which are followed by a suitable conditional jump.
                    165: **
                    166: ** None of the arithmetic operations set the "unsigned" result indicators,
                    167: ** so we retain compares before any unsigned-conditional jump.
                    168: **
                    169: **     op O1,O2[,O3]           ->      op O1,O2[,O3]
                    170: **     cmpX O[2|3],&0
                    171: **
                    172: **/
                    173: 
                    174:     if (
                    175:            (cop2 == CMPW || cop2 == CMPH || cop2 == CMPB)
                    176:        &&  strcmp(pl->op2,"&0") == 0
                    177:        &&  strcmp(dst(pf),pl->op1) == 0
                    178:        &&  (MOVB <= cop1 && cop1 <= ARSW3)
                    179:        &&  stype(cop1) == stype(cop2)
                    180:        &&  (pl->forw->op < JLU || pl->forw->op > JGEU)
                    181:        &&  isiros(pl->op1)             /* safe from mmio */
                    182:        )
                    183:     {
                    184:        wchange();                      /* changing window */
                    185:        lmrgin3(pf,pl,pf);              /* preserve line number info */ 
                    186:        mvlivecc(pl);           /* preserve condition code info */
                    187:        DELNODE(pl);                    /* delete the compare */
                    188:        return(true);                   /* announce success */
                    189:     }
                    190: /* Eliminate compares against zero if preceding instruction sets condition
                    191: ** codes (special cases).
                    192: **
                    193: **     movw O1,O2
                    194: **     cmpw O1,&0              ->      movw O1,O2
                    195: **
                    196: ** or
                    197: **     call &n,O
                    198: **     cmpw %r0,&0             ->      call &n,O
                    199: **
                    200: ** This last improvement is moderately dangerous.  It depends on the
                    201: ** fact that, in C, a function returning a value puts the value in r0
                    202: ** just before exiting.  The return indicators would then be set correctly.
                    203: ** An assembly coder could blow this assumption to pieces.
                    204: ** Once again we have to watch out for unsigned tests following the cmpw,
                    205: ** since a "movw" in the called function would not set the unsigned
                    206: ** result indicators.
                    207: */
                    208: 
                    209: 
                    210:     if (
                    211:            cop2 == CMPW
                    212:        &&  strcmp(pl->op2,"&0") == 0
                    213:        && (
                    214:                (
                    215:                    cop1 == MOVW
                    216:                &&  strcmp(pf->op1,pl->op1) == 0
                    217:                &&  ! usesvar(pf->op1,pf->op2)
                    218:                                        /* O1 cannot use O2 in any way */
                    219:                &&  isiros(pf->op1)     /* safe for mmio */
                    220:                )
                    221: #ifdef CALLCMPW                                /* make this a selectable option */
                    222:            ||
                    223:                (
                    224:                    cop1 == CALL
                    225:                &&  strcmp(pl->op1,"%r0") == 0
                    226:                )
                    227: #endif /* def CALLCMPW */
                    228:            )
                    229:        &&  ! (JLU <= pl->forw->op && pl->forw->op <= JGEU)
                    230:                                        /* disallow unsigned jump after cmpw */
                    231:        )
                    232:     {
                    233:        wchange();
                    234:        lmrgin3(pf,pl,pf);              /* preserve line number info */ 
                    235:        mvlivecc(pl);           /* preserve condition code info */
                    236:        DELNODE(pl);
                    237:        return(true);
                    238:     }
                    239: /* One of the assumptions about eliminating "cmpw" after a "call"
                    240: ** is that all functions set result indicators upon returning a value.
                    241: ** If the value is set by a bit-field extract, this is not so.
                    242: ** Therefore, we must insert an extra "cmpw" to compensate:
                    243: **
                    244: **     extzv   O1,O2,O3,%r0    -->     extzv   O1,O2,O3,%r0
                    245: **                             -->     cmpw    %r0,&0
                    246: **     ret                     -->     ret
                    247: */
                    248: 
                    249: #ifdef CALLCMPW                        /* only if this is enabled */
                    250: 
                    251:     if (
                    252:            cop1 == EXTZV
                    253:        &&  cop2 == RET
                    254:        &&  strcmp(pf->op4,"%r0") == 0
                    255:        )
                    256:     {
                    257:        NODE * newnode = insert(pf);    /* create new node after extzv */
                    258: 
                    259:        wchange();                      /* making a change */
                    260:        chgop(newnode,CMPW,"cmpw");     /* set op code number and string */
                    261:        newnode->op1 = "%r0";           /* set up instruction */
                    262:        newnode->op2 = "&0";
                    263:        newnode->nlive = pf->nlive;     /* save live/dead as predecessor */
                    264:        pf->nlive &= ~CONCODES;         /* killing condition codes */
                    265:        return(true);                   /* made a change */
                    266:     }
                    267: #endif /* def CALLCMPW */
                    268: /* This next set of improvements deals with pairs of move's. */
                    269: 
                    270: /* case 1:  redundant movw
                    271: **
                    272: **     movw O1,O2
                    273: **     movw O2,O1              ->      movw O1,O2
                    274: ** or
                    275: **
                    276: **     movw O1,O2
                    277: **     movw O1,O2              ->      movw O1,O2 (second one)
                    278: **
                    279: ** Note that, for the second improvement, O2 cannot be used by O1.
                    280: */
                    281:     if (cop1 == MOVW && cop2 == MOVW)
                    282:     {
                    283:        if (    strcmp(pf->op1,pl->op2) == 0    /* first case */ 
                    284:            &&  strcmp(pf->op2,pl->op1) == 0
                    285:            &&  isiros(pf->op1)
                    286:            &&  isiros(pf->op2)         /* safe from mmio */
                    287:           )
                    288:        {
                    289:            wchange();                          /* change window */
                    290:            lmrgin3(pf,pl,pf);          /* preserve line number info */ 
                    291:            mvlivecc(pl);       /* perserve conditions codes live info */
                    292:            DELNODE(pl);                        /* delete second inst. */
                    293:            return(true);
                    294:        }
                    295:        
                    296:        if (    strcmp(pf->op1,pl->op1) == 0    /* second case */
                    297:            &&  strcmp(pf->op2,pl->op2) == 0
                    298:            &&  ! usesvar(pl->op1,pf->op2)
                    299:            &&  isiros(pf->op1)
                    300:            &&  isiros(pf->op2)         /* safe from mmio */
                    301:           )
                    302:        {
                    303:            wchange();
                    304:            lmrgin3(pf,pl,pl);          /* preserve line number info */ 
                    305:            mvlivecc(pf);       /* perserve conditions codes live info */
                    306:            DELNODE(pf);                        /* delete first inst. */
                    307:            return(true);
                    308:        }
                    309:     }
                    310: /* Case 2:  arbitrary size moves with intermediate register
                    311: **
                    312: ** The idea here is to collapse pairs of moves, possibly with different
                    313: ** sized operands, into one correct move.  We assume that a register
                    314: ** is used unnecessarily in the operation.  That is, we are looking at
                    315: **
                    316: **     movX    O1,R
                    317: **     movY    R,O2            ->      movZ O1,O2
                    318: **
                    319: **     if R dead after movY and O2 doesn't use R
                    320: **     or O2 is same register as R
                    321: **
                    322: ** where X, Y, and Z are things like "twb" (as in, "movtwb"), "h",
                    323: ** and "bbw".  The trick is to choose the correct move based on the
                    324: ** sizes of the operands.  There are 81 (gasp!) combinations of four
                    325: ** operands, with three choices per operand.  The code below is
                    326: ** correct, but misses one obscure case:
                    327: **
                    328: **     movtbh  O1,R
                    329: **     movtwh  R,O2            ->      movh O1,O2
                    330: */
                    331: 
                    332:     if (
                    333:            ismove(pf,&src1,&dst1)      /* test, get source, dest. sizes */
                    334:        &&  ismove(pl,&src2,&dst2)
                    335:        &&  isreg(pf->op2)
                    336:        &&  samereg(pf->op2, pl->op1)
                    337:        &&  (
                    338:                ( isdead(pl->op1,pl) &&  ! usesreg(pl->op2,pl->op1) )
                    339:             || samereg(pl->op1,pl->op2)
                    340:             )
                    341:        )
                    342:     /* fall through to sub-cases */
                    343:     {
                    344:     /* sub-case 1:
                    345:     **  Sizes of movX source and movY destination are equal.  Source of
                    346:     **  movX no larger than destination, source of movY no smaller than its
                    347:     **  destination.  ("Size" here refers to number of bytes in effective
                    348:     **  operand.)  Example:
                    349:     **
                    350:     **         movbbw O1,R                             s = 1; d = 4
                    351:     **         movthb R,O2     ->      movb O1,O2      s = 2; d = 1
                    352:     **
                    353:     ** (More common case...)
                    354:     **
                    355:     **         movw O1,R                               s = 4; d = 4
                    356:     **         movw R,O2       ->      movw O1,O2      s = 4; d = 4
                    357:     */
                    358: 
                    359:        if (
                    360:                src1 == dst2
                    361:            &&  src1 <= dst1
                    362:            &&  src2 >= dst2
                    363:            )
                    364:        {
                    365:            wchange();
                    366:            pl->op1 = pf->op1;          /* copy down first operand */
                    367:            lmrgin1(pf,pl,pl);  /* preserve line number info */ 
                    368:            mvlivecc(pf);       /* perserve conditions codes live info */
                    369:            DELNODE(pf);                /* delete first node */
                    370:            switch (src1)               /* choose correct new instruction */
                    371:            {
                    372:            case 1:                     /* byte to byte */
                    373:                chgop(pl,MOVB,"movb"); break;
                    374:            
                    375:            case 2:                     /* halfword to halfword */
                    376:                chgop(pl,MOVH,"movh"); break;
                    377: 
                    378:            case 4:                     /* word to word */
                    379:                chgop(pl,MOVW,"movw"); break;
                    380:            }
                    381:            return(true);
                    382:        }
                    383:     /* sub-case 2:
                    384:     ** Both sources are the same size, and either the destinations are
                    385:     **  the same size or destination of movX larger than source.
                    386:     **  Examples:
                    387:     **
                    388:     **         movzbw  O1,R                            s = 1; d = 4
                    389:     **         movb    R,O2    ->      movb O1,O2      s = 1; d = 1
                    390:     **
                    391:     **         movtwh  O1,R                            s = 4; d = 2
                    392:     **         movtwh  R,O2    ->      movtwh O1,O2    s = 4; d = 2
                    393:     */
                    394: 
                    395:        if (
                    396:                src1 == src2            /* source sizes equal */
                    397:            &&  (
                    398:                    src1 <= dst1
                    399:                ||  dst1 == dst2
                    400:                )
                    401:            )
                    402:        {
                    403:            wchange();                  /* making a change */
                    404:            pl->op1 = pf->op1;          /* copy operand */
                    405:            lmrgin1(pf,pl,pl);  /* preserve line number info */ 
                    406:            mvlivecc(pf);       /* perserve conditions codes live info */
                    407:            DELNODE(pf);                /* delete first node */
                    408:            return(true);
                    409:        }
                    410:     /* sub-case 3:
                    411:     **  Destination 1, source 2, and destination 2 are all the same size.
                    412:     **  Example:
                    413:     **
                    414:     **         movzhw O1,R                             s = 2; d = 4
                    415:     **         movw R,O2       ->      movzhw O1,O2    s = 4; d = 4
                    416:     */
                    417: 
                    418:        if (
                    419:                dst1 == src2
                    420:            &&  src2 == dst2
                    421:            )
                    422:        {
                    423:            wchange();
                    424:            pf->op2 = pl->op2;          /* copy up second operand */
                    425:            makelive(pf->op2,pf);       /* make sure first inst. won't now
                    426:                                        ** go away
                    427:                                        */
                    428:            lmrgin1(pf,pl,pf);  /* preserve line number info */ 
                    429:            mvlivecc(pl);       /* perserve conditions codes live info */
                    430:            DELNODE(pl);                /* delete second node */
                    431:            return(true);
                    432:        }
                    433:     } /* end move-move merging */
                    434: /* Merge register move into indirect reference.
                    435: **
                    436: ** The purpose of this improvement is to eliminate a movw if it is
                    437: ** used to load a register which is then used exclusively for an
                    438: ** indirect reference.  Examples:
                    439: **
                    440: **     movw O1,R
                    441: **     op2 0(R),O2             ->      op2 *O1,O2
                    442: **
                    443: **     if R dead after op2
                    444: **     if R not used in O2, except as 0(R)
                    445: **
                    446: ** We use utility routine 'doindirect' to do this in a general way
                    447: ** for, in fact, any instruction and not just op2.
                    448: */
                    449: 
                    450:     if ( cop1 == MOVW && isreg(pf->op2))
                    451:     {
                    452:        /* use utility routine to check for feasibility.  Replace
                    453:        ** 0(R) with suitable indirection from O1
                    454:        */
                    455: 
                    456:        if (doindirect(pl,pf->op2,pf->op1))
                    457:        {
                    458:            lmrgin1(pf,pl,pl);  /* preserve line number info */ 
                    459:            mvlivecc(pf);       /* perserve conditions codes live info */
                    460:            DELNODE(pf);                /* success.  delete first node */
                    461:            return(true);
                    462:        }
                    463:     }
                    464: /* Address arithmetic:
                    465: **
                    466: ** This transformation merges instructions of the form
                    467: **
                    468: **     addw2 &m,R
                    469: **
                    470: ** with operands of the form
                    471: **
                    472: **     n(R)
                    473: **
                    474: ** yielding a replacement operand of the form
                    475: **
                    476: **     m+n(R)
                    477: **
                    478: ** We do this in a general way, transforming all of the operands in the
                    479: ** instruction that follows the addw2 (subw2) that can be transformed.
                    480: ** The transformation cannot be performed if the second instruction uses
                    481: ** R in any other way.  Note that dyadic instructions like
                    482: **
                    483: **     addw2 a,R
                    484: **
                    485: ** use R implicitly:  a + R -> R.
                    486: ** However, for moves and triadics, the last operand is only a destination,
                    487: ** not an operand, so having R as the last operand does not impede our
                    488: ** transformation.
                    489: **
                    490: ** In general we don't delete the addw2 (subw2) node but simply move it
                    491: ** past its successor after transforming the operands.  At first this
                    492: ** would seem to be a waste of time.  However, if R is dead after the
                    493: ** second instruction, we can discard the addw2 (subw2).  Thus we
                    494: ** can propagate the addw2 (subw2) through a series of offsets:
                    495: **
                    496: **     addw2 &4,%r0
                    497: **     movw 0(%r0),0(%r1)
                    498: **     movw 4(%r0),4(%r1)
                    499: **
                    500: **             |
                    501: **             V
                    502: **     movw 4(%r0),0(%r1)
                    503: **     addw2 &4,%r0
                    504: **     movw 4(%r0),4(%r1)
                    505: **
                    506: **             |
                    507: **             V
                    508: **     movw 4(%r0),0(%r1)
                    509: **     movw 8(%r0),4(%r1)
                    510: **     addw2 &4,%r0
                    511: **
                    512: ** and the addw2 could be discarded if %r0 is dead now.  Notice that no
                    513: ** particular performance penalty is incurred by doing this transformation
                    514: ** if we fail to discard the addw2 (subw2), but we will win if we can
                    515: ** throw it out.  NOTE, however, that we cannot move the add/sub if
                    516: ** there is a conditional branch or compare following the second instruction,
                    517: ** since we will provide different condition codes from the original sequence.
                    518: */
                    519: /* Begin address arithmetic transformation */
                    520: 
                    521:     if (
                    522:            (cop1 == ADDW2 || cop1 == SUBW2)
                    523:        &&  isnumlit(pf->op1)
                    524:        &&  isreg(pf->op2)
                    525:        &&  strcmp(pf->op2,"%sp") != 0  /* not stack pointer */
                    526:        &&  ! isbr(pl)                  /* don't move add/sub past branch! */
                    527:        )
                    528:     {
                    529:        char * reg = pf->op2;           /* point at register name (R) */
                    530:        int destreg = 0;                /* number of destination operand,
                    531:                                        ** zero if none
                    532:                                        */
                    533:        int idxmask = 0;                /* bit mask of operands to change */
                    534:        long idxval[MAXOPS+1];          /* current indices for each (indexed
                    535:                                        ** 1 to MAXOPS, not 0 to MAXOPS-1)
                    536:                                        */
                    537:        int i;                          /* loop index */
                    538:        long m = atol(pf->op1+1);       /* literal in addw2 &m,R */
                    539:        NODE * nextinst = pl->forw;     /* pointer to inst. after window */
                    540: 
                    541: 
                    542: /* Check for conditional branch or compare following second instruction in
                    543: ** situation where we can't delete the add/sub.  Don't do improvement
                    544: ** if we find one.
                    545: */
                    546: 
                    547:        f = ( isdead(reg,pl) || strcmp(dst(pl),reg) == 0 );
                    548:        if ( (! f) && ( ! isdeadcc(pl) || iscompare(nextinst)) )
                    549:            goto noindex;               /* won't delete and have cond. br. */
                    550:        
                    551:        if (cop1 == SUBW2)
                    552:            m = -m;                     /* negate literal if subtract */
                    553:        
                    554: /* Determine in which instructions we allow ourselves to see R as an
                    555: ** operand (destination) and remember which operand number it is.
                    556: */
                    557: 
                    558:        if (istriadic(pl,&opn,&opst))
                    559:            destreg = 3;                /* in triadics, is third operand */
                    560:        else if (ismove(pl,&src1,&dst1))
                    561:            destreg = 2;                /* in moves, is second */
                    562:        /* in all others, not allowed */
                    563: 
                    564: /* Now we loop through all possible operands in an instruction, looking
                    565: ** for indexed uses of R (i.e., n(R) ).  If we find, instead, a use of
                    566: ** R which is not in the "destreg" position, we cannot do the transform.
                    567: */
                    568: 
                    569:        for (i = MAXOPS; i > 0; i--)
                    570:        {
                    571:            char * t = pl->ops[i];      /* point at new operand */
                    572: 
                    573:            if (t == NULL)
                    574:                continue;               /* disregard null operands */
                    575: 
                    576:            if (isindex(t,reg))         /* this is what we seek */
                    577:            {
                    578:                idxmask |= (1<<i);      /* remember where we saw it */
                    579:                if(*t == '*')
                    580:                        t++;
                    581:                idxval[i] = atol(t);    /* remember current index value
                    582:                                        ** (i.e., n from n(R)
                    583:                                        */
                    584:            }
                    585:            else if (samereg(t,reg) && i != destreg)
                    586:                goto noindex;           /* instruction uses register in
                    587:                                        ** non-transformable way
                    588:                                        */
                    589:        }
                    590: /* We now know there have been only valid uses of R in the second
                    591: ** instruction.  If there are any uses of R at all, transform the
                    592: ** second instruction.
                    593: */
                    594: 
                    595: /* Define maximum size of new operand. */
                    596: 
                    597: #define NEWSIZE        (11+1+3+1+1)            /* for "ddddddddddd(%rn)\0" */
                    598: 
                    599:        if (idxmask == 0)
                    600:            goto noindex;               /* nothing to do if no uses of R */
                    601: 
                    602:        wchange();                      /* we may just move/delete the add */
                    603:        for (i = MAXOPS; i>0; i--)      /* find operands to alter */
                    604:        {
                    605:            char * t;
                    606:            if ((idxmask & (1<<i)) == 0)
                    607:                continue;               /* ignore this operand:  not n(R) */
                    608: 
                    609:            t = pl->ops[i];
                    610:            pl->ops[i] = getspace(NEWSIZE);
                    611:                                        /* get space for new operand */
                    612:            if(*t == '*')
                    613:                (void) sprintf(pl->ops[i],"*%d(%s)",(int)(m+idxval[i]),reg);
                    614:            else
                    615:                (void) sprintf(pl->ops[i],"%d(%s)",(int)(m+idxval[i]),reg);
                    616:                                        /* build new operand string */
                    617:        }
                    618: 
                    619: /* Discard add/sub if R is dead after second instruction, or if that
                    620: ** instruction set a new value.
                    621: */
                    622: 
                    623:        if (f)                          /* conditions permit deleting */
                    624:            { 
                    625:             ldelin(pf);                /* preserve line number info */ 
                    626:             mvlivecc(pf);      /* perserve conditions codes live info */
                    627:             DELNODE(pf); }             /* delete add/sub */
                    628:        else {  
                    629:            lexchin(pf,pl);             /* preserve line number info */ 
                    630:            exchange(pf);               /* otherwise exchange add/sub and
                    631:                                        ** second inst.
                    632:                                        */
                    633:            swplivecc(pf,pl);   /* swaping the condition codes live/dead info */
                    634:        }
                    635:        return(true);
                    636:     }
                    637: noindex:
                    638: /* Address arithmetic, case 2:
                    639: **
                    640: **     addw3 &n,R1,R2
                    641: **     pushw R2                ->      pushaw n(R1)
                    642: ** or
                    643: **
                    644: **     subw3 &n,R1,R2
                    645: **     pushw R2                ->      pushaw -n(R1)
                    646: **
                    647: **     if R2 dead after pushw
                    648: **
                    649: **     (Sigh!  These aren't safe in general, but for the specific cases
                    650: **     where R2 is sp, fp, or ap, we can be sure we're pushing an
                    651: **     address and not the result of an integer computation.  pushaw
                    652: **     doesn't do 32 bit arithmetic.)
                    653: */
                    654: 
                    655:     if (
                    656:            (cop1 == ADDW3 || cop1 == SUBW3)
                    657:        &&  cop2 == PUSHW
                    658:        &&  *pf->op1 == '&'
                    659:        &&  isreg(pf->op2)
                    660:        &&  (
                    661:                strcmp(pf->op2,"%fp") == 0
                    662:            ||  strcmp(pf->op2,"%ap") == 0
                    663:            ||  strcmp(pf->op2,"%sp") == 0
                    664:            )
                    665:        &&  isreg(pf->op3)
                    666:        &&  samereg(pf->op3,pl->op1)
                    667:        &&  isdead(pf->op3,pl)
                    668:        )
                    669:     {
                    670:        /* allocate space for new operand:  room for constant, less room
                    671:        ** for &, plus room for possible sign, plus room for parens and
                    672:        ** register declaration, plus room for null.
                    673:        */
                    674:        char * ts = getspace(   
                    675:                                strlen(pf->op1)-1+1     /* less &, plus sign */
                    676:                                + 1 + strlen(pf->op2) + 1 /* ( reg ) */
                    677:                                + 1                     /* null */
                    678:                            );
                    679:        
                    680:        char * operand = pf->op1 + 1;   /* point past & at operand */
                    681: 
                    682:        int msign = 0;                  /* non-zero if minus sign required */
                    683: 
                    684:        wchange();
                    685: 
                    686:        /* create new operand */
                    687: 
                    688:        if (*operand == '-')
                    689:        {
                    690:            msign = 1;                  /* - sign required */
                    691:            operand++;                  /* skip past - in operand */
                    692:        }
                    693:        if (cop1 == SUBW3)              /* invert sign if op was subtract */
                    694:            msign = 1-msign;
                    695: 
                    696:        (void) sprintf(ts,"%s%s(%s)",
                    697:                (msign != 0 ? "-" : ""),
                    698:                operand,                /* string for constant, no & */
                    699:                pf->op2);
                    700:        lmrgin1(pf,pl,pl);              /* preserve line number info */ 
                    701:        mvlivecc(pf);   /* perserve conditions codes live info */
                    702:        DELNODE(pf);                    /* discard add/sub */
                    703:        chgop(pl,PUSHAW,"pushaw");      /* change op code */
                    704:        pl->op1 = ts;                   /* change operand */
                    705:        return(true);
                    706:     }
                    707: /* Collapse bit test/branch combination
                    708: **
                    709: **     bitw    &2^n,O
                    710: **     je      to              ->      jbc &n,O,to
                    711: **
                    712: **     bitw    &2^n,O
                    713: **     jne     to              ->      jbs &n,O,to
                    714: **
                    715: **     jz is a synonym for je.
                    716: **     jnz is a synonym for jne.
                    717: */
                    718: 
                    719: /* ----------- FLASH -------------
                    720: ** It turns out that these "improvements" aren't:  they are slower than
                    721: ** the sequences they would replace.  If someday that condition changes,
                    722: ** remove the conditionals.
                    723: */
                    724: 
                    725: #ifdef FASTJBCJBS
                    726: 
                    727:     if (
                    728:            cop1 == BITW
                    729:        &&  (
                    730:                (f = (cop2 == JE))
                    731:             || (f = (cop2 == JZ))
                    732:             || cop2 == JNE
                    733:             || cop2 == JNZ
                    734:            )
                    735:        &&  (temp = getbit(pf->op1)) >= 0
                    736:        )
                    737:     {
                    738:        wchange();
                    739:        pl->op3 = pl->op1;              /* shift operands */
                    740:        pl->op2 = pf->op2;
                    741:        /* build new operand: &n */
                    742:        pl->op1 = getspace(1+2+1);      /* space for "&dd\0" */
                    743:        (void) sprintf(pl->op1,"&%d",temp);
                    744:        if (f)                          /* f true for je/jz */
                    745:            chgop(pl,JBC,"jbc");
                    746:        else
                    747:            chgop(pl,JBS,"jbs");
                    748:        
                    749:        lmrgin1(pf,pl,pl);              /* preserve line number info */ 
                    750:        mvlivecc(pf);   /* perserve conditions codes live info */
                    751:        DELNODE(pf);                    /* discard bitw */
                    752:        return(true);
                    753:     }
                    754: 
                    755: #endif /* def FASTJBCJBS */
                    756: 
                    757: #ifdef UCODE50                         /* with 5.0 microcode (3B20) only */
                    758: 
                    759: /* Increment and test improvement
                    760: **
                    761: **     addw2   &n,R
                    762: **     cmpw    R,O             ->      inctst R,&n-1,O
                    763: **
                    764: **     if O doesn't use R (this may be unnecessarily restrictive,
                    765: **     depending on when the effective address of O is calculated,
                    766: **     but it would be a strange use, anyway)
                    767: **
                    768: */
                    769: 
                    770:     if (
                    771:            cop1 == ADDW2
                    772:        &&  cop2 == CMPW
                    773:        &&  isreg(pf->op2)
                    774:        &&  samereg(pl->op1,pf->op2)
                    775:        &&  isnumlit(pf->op1)
                    776:        &&  1 <= (templ = atol(pf->op1+1)) && templ <= 16
                    777:                                        /* can't use isnib here:  allow for
                    778:                                        ** 16, disallow 0
                    779:                                        */
                    780:        &&  ! usesreg(pl->op2,pf->op2)
                    781:        )
                    782:     {
                    783:        wchange();                      /* making a change */
                    784:        chgop(pl,INCTST,"inctst");      /* new op code number, string */
                    785:        pl->op3 = pl->op2;              /* shift operand */
                    786:        pl->op2 = getspace(1+2+1);      /* for "&dd\0" */
                    787:        (void) sprintf(pl->op2,"&%d",(int)(templ-1));
                    788:                                        /* literal in inctmp is 1 less */
                    789:        lmrgin3(pf,pl,pl);              /* preserve line number info */ 
                    790:        DELNODE( pf );                  /* delete ADDW2 */
                    791:        return(true);
                    792:     }
                    793: #endif /* def UCODE50 */
                    794: 
                    795: #ifdef UCODE50                         /* if 5.0 microcode (3B20) only */
                    796: 
                    797: /* Use increment/decrement pointer
                    798: **
                    799: **     llsw2   &1,R1
                    800: **     addw2   R1,R2           ->      incpth R2,R1
                    801: **
                    802: **     llsw2   &2,R1
                    803: **     addw2   R1,R2           ->      incptw R2,R1
                    804: **
                    805: **     llsw2   &1,R1
                    806: **     subw2   R1,R2           ->      decpth R2,R1
                    807: **
                    808: **     llsw2   &2,R1
                    809: **     subw2   R1,R2           ->      decptw R2,R1
                    810: **
                    811: **     if R1 dead after addw2/subw2
                    812: **     if R1 and R2 different
                    813: */
                    814: 
                    815:     if (
                    816:            cop1 == LLSW2
                    817:        &&  (cop2 == ADDW2 || cop2 == SUBW2)
                    818:        &&  isreg(pl->op1)
                    819:        &&  isreg(pl->op2)
                    820:        &&  isdead(pf->op2,pl)
                    821:        &&  samereg(pl->op1,pf->op2)
                    822:        &&  ! samereg(pl->op1,pl->op2)
                    823:        &&  ( 
                    824:                (f = (strcmp(pf->op1,"&2") == 0))
                    825:            ||  strcmp(pf->op1,"&1") == 0
                    826:            )
                    827:        )
                    828:     {
                    829:        wchange();
                    830:        pl->op1 = pl->op2;              /* switch operands */
                    831:        pl->op2 = pf->op2;
                    832: 
                    833: /* select new op code for merged instruction */
                    834: 
                    835:        if (cop2 == ADDW2)              /* do incpt cases */
                    836:        {
                    837:            if (f)                      /* true for word incr. */
                    838:                chgop(pl,INCPTW,"incptw");
                    839:            else
                    840:                chgop(pl,INCPTH,"incpth");
                    841:        }
                    842:        else                            /* decpt case */
                    843:        {
                    844:            if (f)                      /* true for word decr. */
                    845:                chgop(pl,DECPTW,"decptw");
                    846:            else
                    847:                chgop(pl,DECPTH,"decpth");
                    848:        }
                    849: 
                    850:        lmrgin1(pf,pl,pl);              /* preserve line number info */ 
                    851:        DELNODE( pf );                  /* delete shift */
                    852:        return(true);
                    853:     }
                    854: #endif /* def UCODE50 */
                    855: /********************************************************************
                    856: **
                    857: **     Begin improvements that alter code, rather than deleting it.
                    858: **
                    859: ***********************************************************************
                    860: */
                    861: 
                    862: /* Use register in pushw if possible
                    863: **
                    864: **     movw R,O                ->      movw R,O
                    865: **     pushw O                 ->      pushw R
                    866: **
                    867: ** if O is not a register.
                    868: */
                    869: 
                    870:     if (
                    871:             cop1 == MOVW
                    872:        &&   cop2 == PUSHW
                    873:        &&   strcmp(pf->op2,pl->op1) == 0
                    874:        &&   isreg(pf->op1)
                    875:        &&   !isreg(pl->op1)
                    876:        &&   isiros(pf->op2)            /* safe from mmio */
                    877:        )
                    878:     {
                    879:        wchange();
                    880:        makelive((pl->op1 = pf->op1),pl); /* propagate liveness of R */
                    881:        return(true);
                    882:     }
                    883: /* Use register if possible in op2 or op3
                    884: **
                    885: **     movw R,O1               ->      movw R,O1
                    886: **     op2 O1,O2               ->      op2 R,O2
                    887: **
                    888: **     if O1 not a register
                    889: ** or
                    890: **
                    891: **     movw R,O1               ->      movw R,O1
                    892: **     op3 O1,O2,O3            ->      op3 R,O2,O3
                    893: **
                    894: **     if O1 is not a register
                    895: ** or
                    896: **
                    897: **     movw R,O2               ->      movw R,O2
                    898: **     op3 O1,O2,O3            ->      op3 O1,R,O3
                    899: **
                    900: **     if O2 is not a register
                    901: */
                    902: 
                    903:     if (
                    904:            cop1 == MOVW
                    905:        &&  isreg(pf->op1)
                    906:        &&  ! isreg(pf->op2)
                    907:        )
                    908:     {
                    909:        if (
                    910:               (
                    911:                    isdyadic(pl)
                    912:                &&  (f = (strcmp(pf->op2,pl->op1) == 0))
                    913:                &&  (CMPW <= cop2 && cop2 <= UMODW3)
                    914:                &&  ( ismove( pl, &src2, &dst2 ) && src2 == stype(cop1) ||
                    915:                     !ismove( pl, &src2, &dst2 ) && stype(cop2) == stype(cop1)
                    916:                    )
                    917:                &&  isiros(pf->op2)             /* safe from mmio */
                    918:                )
                    919:            ||
                    920:                (
                    921:                    istriadic(pl,&opn,&opst)
                    922:                 && (
                    923:                        (f = (strcmp(pf->op2,pl->op1) == 0))
                    924:                     || strcmp(pf->op2,pl->op2) == 0
                    925:                    )
                    926:                 &&  isiros(pf->op2)            /* safe from mmio */
                    927:                )
                    928:            )
                    929:        {
                    930:            wchange();
                    931:            if (f)                      /* f true if we modify first operand */
                    932:                pl->op1 = pf->op1;
                    933:            else
                    934:                pl->op2 = pf->op1;
                    935:            makelive(pf->op2,pl);       /* propagate liveness into op2/3 */
                    936:            return(true);
                    937:        }
                    938:     }
                    939: /* This transformation propagates a register use back into a triadic.
                    940: **
                    941: **     op3 O1,O2,O3            ->      op3 O1,O2,R
                    942: **     movw O3,R               ->      movw R,O3  (possibly deleted)
                    943: **
                    944: **     if R not used by O3
                    945: **
                    946: **     If O3 is a register that is dead after movw, we can change
                    947: **     this to just the op3.  If O3 is a register that is not dead,
                    948: **     we can't do the transformation, because it will oscillate.
                    949: */
                    950: 
                    951:     if (
                    952:            istriadic(pf,&opn,&opst)
                    953:        &&  cop2 == MOVW
                    954:        &&  isreg(pl->op2)
                    955:        &&  strcmp(pf->op3,pl->op1) == 0
                    956:        &&  ! usesreg(pf->op3,pl->op2)
                    957:        &&  (                           /* avoid oscillation case */
                    958:                ! ( f = isreg(pl->op1) )
                    959:             || isdead(pl->op1,pl)
                    960:             )
                    961:        &&  isiros(pf->op3)             /* safe from mmio */
                    962:        )
                    963:     {
                    964:        wchange();
                    965: 
                    966:        pf->op3 = pl->op2;
                    967:        makelive(pf->op3,pf);           /* make R live after op3 */
                    968: 
                    969:        lmrgin2(pf,pl,pf);              /* preserve line number info */ 
                    970:                                        /* lmrgin2 works here
                    971:                                           because it sets the uniqid of the
                    972:                                           non-result (i.e. pl) to IDVAL */
                    973:        if (f)                          /* true if O3 was a register */
                    974:              { mvlivecc(pl);   /* preserve conditions codes live info */
                    975:              DELNODE(pl); }
                    976:        else                            /* O3 not a register */
                    977:        {
                    978:            pl->op2 = pl->op1;
                    979:            pl->op1 = pf->op3;          /* pf->op3 contains R from first move */
                    980:        }
                    981:        return(true);
                    982:     }
                    983: /* Use register in second of two moves, if possible.
                    984: **
                    985: ** This improvement attempts to propagate a register use, if possible.
                    986: ** We do this in a general way for pairs of moves.  Here's the case
                    987: ** we're considering:
                    988: **
                    989: **             movX R,O1       ->      movX R,O1
                    990: **             movY O1,O2      ->      movY R,O2
                    991: **
                    992: ** We don't bother with this improvement if O1 is already a register.
                    993: **
                    994: ** We can make the identical improvement if "R" is really a nibble.
                    995: **
                    996: ** We can do this when (using earlier terminology) the destination
                    997: ** of movX and the source of movY are the same size.  There are three
                    998: ** sub-cases:
                    999: **
                   1000: **     1.  destination1 == source2 == destination2.
                   1001: **     2.  source1 >= destination1 == source2 .
                   1002: **             (remember, source1 is register or nibble)
                   1003: **     3.  source1 >= destination2.
                   1004: **
                   1005: ** Examples:
                   1006: **
                   1007: **             movbbh R,O1                             s = 1; d = 2
                   1008: **             movthb O1,O2    ->      movb R,O2       s = 2; d = 1
                   1009: **
                   1010: **             movbbh R,O1                             s = 1; d = 2
                   1011: **             movh O1,O2      ->      movbbh R,O2     s = 2; d = 2
                   1012: **
                   1013: */
                   1014: 
                   1015:     if (
                   1016:            ismove(pf, &src1, &dst1)
                   1017:        &&  ismove(pl, &src2, &dst2)
                   1018:        &&  src2 == dst1
                   1019:        &&  ( isreg(pf->op1) || isnib(pf->op1) ) /* R can be reg. or nibble */
                   1020:        &&  ! isreg(pf->op2)            /* this is "don't bother" test */
                   1021:        &&  strcmp(pf->op2, pl->op1) == 0
                   1022:        &&  isiros(pf->op2)             /* safe from mmio */
                   1023:        )
                   1024:     /* fall through to sub-cases */
                   1025:     {
                   1026: 
                   1027:     /* sub-case 1:  source2 and destination2 same */
                   1028: 
                   1029:        if (src2 == dst2)
                   1030:        {
                   1031:            wchange();
                   1032:            chgop(pl,pf->op,pf->opcode); /* copy instruction of first node */
                   1033:            pl->op1 = pf->op1;          /* propagate register/nibble use */
                   1034:            makelive(pl->op1,pl);       /* mark it as live */
                   1035:            return(true);
                   1036:        }
                   1037: 
                   1038:     /* sub-case 2:  source1 >= destination1 */
                   1039: 
                   1040:        if (src1 >= dst1)
                   1041:        {
                   1042:            wchange();
                   1043:            pl->op1 = pf->op1;          /* propagate register/nibble */
                   1044:            makelive(pl->op1,pl);       /* make register live after pl */
                   1045:            return(true);
                   1046:        }
                   1047: 
                   1048:     /* sub-case 3:  source1 >= destination2 */
                   1049: 
                   1050:        if (src1 >= dst2)
                   1051:        {
                   1052:            wchange();
                   1053:            switch (dst2)               /* choose correct new instruction */
                   1054:            {
                   1055:            case 1:
                   1056:                chgop(pl,MOVB,"movb"); break;
                   1057:            case 2:
                   1058:                chgop(pl,MOVH,"movh"); break;
                   1059:            case 4:
                   1060:                chgop(pl,MOVW,"movw"); break;
                   1061:            }
                   1062:            pl->op1 = pf->op1;          /* propagate register/nibble use */
                   1063:            makelive(pl->op1,pl);       /* make this register live here */
                   1064:            return(true);
                   1065:        }
                   1066:     }
                   1067: /* More paired move improvements
                   1068: **
                   1069: ** This improvement propagates the use of a register, if possible from
                   1070: ** one move to a following one.  It also has the potential of killing
                   1071: ** off the liveness of a register.  Example:
                   1072: **
                   1073: **     movX O,R1               ->      movX O,R1
                   1074: **     movY O,R2               ->      movY R1,R2
                   1075: **
                   1076: **     Since we are trying to kill registers off early, these special
                   1077: **     conditions apply if O is a register:
                   1078: **             1)  O must be dead after movY or be the same as R2.
                   1079: **             2)  R1 must be live after movY.
                   1080: **     If O is a register, it must be live after movY or be the same
                   1081: **     register as R2.
                   1082: **     O may not use R1.
                   1083: **
                   1084: **     The size of source1 must be the same as source2,
                   1085: **     and destination1 must be at least as large as source2.
                   1086: */
                   1087: 
                   1088:     if (
                   1089:            ismove(pf,&src1,&src2)
                   1090:        &&  ismove(pl,&src2,&src2)
                   1091:        &&  strcmp(pf->op1,pl->op1) == 0
                   1092:        &&  isreg(pf->op2)
                   1093:        &&  isreg(pl->op2)
                   1094:        &&  ! usesreg(pl->op1,pf->op2)
                   1095:        &&  src1 == src2
                   1096:        &&  src2 <= dst1
                   1097:        &&  (
                   1098:                ! isreg(pl->op1)                /* O not a register */
                   1099:            ||  (
                   1100:                    (
                   1101:                        samereg(pl->op1,pl->op2)/* O same as R2 */
                   1102:                    ||  isdead(pl->op1,pl)      /* O dead after movY */
                   1103:                    )
                   1104:                
                   1105:                &&  ! isdead(pf->op2,pl)        /* R1 live after movY */
                   1106:                )
                   1107:            )
                   1108:        &&  isiros(pf->op1)             /* safe from mmio */
                   1109:        )
                   1110:     {
                   1111:        wchange();
                   1112:        makelive(pl->op1 = pf->op2,pf); /* copy operand, make register live
                   1113:                                        ** after movX
                   1114:                                        */
                   1115:        return(true);
                   1116:     }
                   1117: /* Re-order pairs of instructions to make better use of registers.
                   1118: **
                   1119: ** This improvement reverses a dyadic and a movw to make better use of
                   1120: ** registers.  The canonical sequence is:
                   1121: **
                   1122: **     op2 O1,O2               ->      movw O1,R
                   1123: **     movw O1,R               ->      op2 R,O2
                   1124: **
                   1125: **     if O1 and O2 don't use R
                   1126: **     if R live after movw
                   1127: **     if instruction following movw is not a conditional branch
                   1128: **     (since we're changing the instruction that sets codes)
                   1129: **
                   1130: **     op2 can also be CMPW
                   1131: */
                   1132: 
                   1133:     if (
                   1134:            (     cop1 == CMPW
                   1135:             ||  (   isdyadic(pf) 
                   1136:                  && ! ismove(pf,&src1,&dst1)
                   1137:                 )
                   1138:            )
                   1139:                                /* since moves are handled elsewhere
                   1140:                                ** and this would tend to undo them
                   1141:                                */
                   1142:        &&  cop2 == MOVW
                   1143:        &&  strcmp(pf->op1,pl->op1) == 0
                   1144:        &&  isreg(pl->op2)
                   1145:        &&  ! isdead(pl->op2,pl)
                   1146:        &&  ! usesreg(pf->op1,pl->op2)
                   1147:        &&  ! usesreg(pf->op2,pl->op2)
                   1148:        &&  ! usesvar(pf->op1,pf->op2)  /* O1 cannot use O2 in any way */
                   1149:        &&  isdeadcc( pl )
                   1150:        &&  isiros(pf->op1)             /* safe from mmio */
                   1151:        )
                   1152:     {
                   1153:        wchange();
                   1154:        pf->op1 = pl->op2;              /* copy operand first */
                   1155:        lexchin(pf,pl);         /* preserve line number info */ 
                   1156:        exchange(pf);                   /* switch the two instructions */
                   1157:        swplivecc(pf,pl);    /* switch the live/dead info on condition codes */
                   1158:        makelive(pl->op2,pf);           /* show register as live after op2 */
                   1159:        return(true);
                   1160:     }
                   1161: /* Similar to the above, this transformation reverses a triadic and a
                   1162: ** movw:
                   1163: **
                   1164: **     op3 O1,O2,O3            ->      movw [O1 | O2],R
                   1165: **     movw [O1 | O2],R        ->      op3 [O1 | R], [O2 | R], O3
                   1166: **
                   1167: ** That is, it inserts a register reference into op3.
                   1168: ** R must not be used in O1, O2, or O3.
                   1169: ** O3 cannot be the same as R, nor can O1/O2 use O3 in any way.
                   1170: ** Instruction after movw must not be conditional branch, since we're
                   1171: ** setting different condition codes.
                   1172: ** Don't bother if R dead after movw, since the inst. will go away eventually.
                   1173: */
                   1174: 
                   1175:     if (
                   1176:            istriadic(pf,&opn,&opst)
                   1177:        &&  cop2 == MOVW
                   1178:        &&  isreg(pl->op2)
                   1179:        &&  ! isdead(pl->op2,pl)
                   1180:        &&  (
                   1181:                (f = (strcmp(pl->op1,pf->op1) == 0))
                   1182:            ||  strcmp(pl->op1,pf->op2) == 0
                   1183:            )
                   1184:        &&  ! usesreg(pf->op1,pl->op2)
                   1185:        &&  ! usesreg(pf->op2,pl->op2)
                   1186:        &&  ! usesreg(pf->op3,pl->op2)
                   1187:        &&  ! usesvar(pl->op1,pf->op3)
                   1188:        &&  ! usesvar(pl->op2,pf->op3)
                   1189:        &&  isdeadcc( pl )
                   1190:        &&  isiros(pl->op1)             /* safe from mmio */
                   1191:        )
                   1192:     {
                   1193:        wchange();
                   1194:        if (f)                          /* true if first operand is R ref. */
                   1195:            pf->op1 = pl->op2;
                   1196:        else
                   1197:            pf->op2 = pl->op2;          /* second operand refers to R */
                   1198:        makelive(pl->op2,pf);           /* R now (will be) live after op3
                   1199:                                        ** since we knew it was live after movw
                   1200:                                        */
                   1201:        lexchin(pf,pl);         /* preserve line number info */ 
                   1202:        exchange(pf);                   /* exchange the instructions */
                   1203:        swplivecc(pf,pl);    /* switch the live/dead info on condition codes */
                   1204:        return(true);
                   1205:     }
                   1206: /* Merge successive adds.
                   1207: **
                   1208: ** This improvement occurs in address arithmetic and in some funny
                   1209: ** expressions.
                   1210: **
                   1211: **     addw3 X,Y,R1            ->      addw2 X,R2
                   1212: **     addw2 R1,R2             ->      addw2 Y,R2
                   1213: **
                   1214: **     if R1 dead after addw2, R1 and R2 are different.
                   1215: **     neither X nor Y can use R1
                   1216: **
                   1217: ** Unfortunately, we learn the hard way of special cases we hadn't
                   1218: ** thought of earlier, to wit:
                   1219: **
                   1220: **     addw3 X,R2,R1           ->      addw2 R2,R2
                   1221: **     addw2 R1,R2             ->      addw2 X,R2
                   1222: **
                   1223: ** If X is R2, we can't do this at all!
                   1224: */
                   1225: 
                   1226:     if (
                   1227:            cop1 == ADDW3
                   1228:        &&  cop2 == ADDW2
                   1229:        &&  isdead(pf->op3,pl)          /* also tests register-ness */
                   1230:        &&  samereg(pf->op3,pl->op1)
                   1231:        &&  isreg(pl->op2)
                   1232:        &&  ! samereg(pl->op1,pl->op2)
                   1233:        &&  strcmp(pf->op1,pf->op2) != 0 /* different operands */
                   1234:        &&  ! usesreg(pf->op1,pf->op3)
                   1235:        &&  ! usesreg(pf->op2,pf->op3)
                   1236:        )
                   1237:     {
                   1238:        wchange();
                   1239:        if (! samereg(pl->op2,pf->op2)) /* check special case */
                   1240:            pl->op1 = pf->op2;          /* not special:  move Y to 2nd inst. */
                   1241:        else
                   1242:        {
                   1243:            pl->op1 = pf->op1;          /* special case:  move X to 2nd inst. */
                   1244:            pf->op1 = pf->op2;          /* move R2 over in first */
                   1245:        }
                   1246:        pf->op2 = pl->op2;              /* move ultimate dest. into 1st inst. */
                   1247:        pf->op3 = NULL;                 /* clean up 1st inst. */
                   1248:        chgop(pf,ADDW2,"addw2");        /* change op code number and string */
                   1249:        lmrgin2(pf,pl,pf);              /* preserve line number info */ 
                   1250:                                        /* again this works because pl->uniqid
                   1251:                                          is set to IDVAL */
                   1252:        return(true);
                   1253:     }
                   1254: /* Reverse adds/subtracts of literals and other adds/subtracts.
                   1255: **
                   1256: ** This transformation facilitates other improvements by bubbling
                   1257: ** adds/subtracts of literals downward and other adds/subtracts upwards.
                   1258: **
                   1259: **     addw2   &n,R            ->      addw2   O,R
                   1260: **     addw2   O,R             ->      addw2   &n,R
                   1261: **
                   1262: **     if R not used in O, O not a literal.
                   1263: */
                   1264: 
                   1265:     if (
                   1266:            (cop1 == ADDW2 || cop1 == SUBW2)
                   1267:        &&  (cop2 == ADDW2 || cop2 == SUBW2)
                   1268:        &&  isreg(pf->op2)
                   1269:        &&  samereg(pf->op2,pl->op2)
                   1270:        &&  *pf->op1 == '&'
                   1271:        &&  ! usesreg(pl->op1,pl->op2)
                   1272:        &&  *pl->op1 != '&'
                   1273:        )
                   1274:     {
                   1275:        wchange();
                   1276:        lexchin(pf,pl);         /* preserve line number info */ 
                   1277:        exchange(pf);                   /* just exchange instructions */
                   1278:        swplivecc(pf,pl);    /* switch the live/dead info on condition codes */
                   1279:        return(true);
                   1280:     }
                   1281: /* Reverse adds/subtracts of literals and moves.
                   1282: **
                   1283: ** This transformation facilitates address arithmetic transformations.
                   1284: **
                   1285: **     addw2 &n,R              ->      movX O1,O2
                   1286: **     movX O1,O2              ->      addw2 &n,R
                   1287: **
                   1288: **     if neither O1 nor O2 uses R
                   1289: **     if instruction following movX is not conditional branch, since we
                   1290: **       will set different condition codes
                   1291: */
                   1292: 
                   1293:     if (
                   1294:            (cop1 == ADDW2 || cop2 == SUBW2)
                   1295:        &&  isreg(pf->op2)
                   1296:        &&  strcmp(pf->op2,"%sp") != 0  /* not stack pointer */
                   1297:        &&  isnumlit(pf->op1)           /* only useful with numeric lits. */
                   1298:        &&  ismove(pl,&src1,&dst1)
                   1299:        &&  ! (usesreg(pl->op1,pf->op2) || usesreg(pl->op2,pf->op2))
                   1300:        &&  isdeadcc( pl )
                   1301:        )
                   1302:     {
                   1303:        wchange();
                   1304:        lexchin(pf,pl);         /* preserve line number info */ 
                   1305:        exchange(pf);                   /* interchange instructions */
                   1306:        swplivecc(pf,pl);    /* switch the live/dead info on condition codes */
                   1307:        /* leave live/dead information alone */
                   1308:        return(true);
                   1309:     }
                   1310:     return(false);
                   1311: }

unix.superglobalmegacorp.com

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