Annotation of researchv9/jerq/sgs/optim/w2opt.c, revision 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.