home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / language / sozobon2 / peep2.c < prev    next >
C/C++ Source or Header  |  1993-10-23  |  19KB  |  831 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Tony Andrews
  2.  * Patched -- PvO -- see file patch *
  3.  *
  4.  * Permission is granted to anyone to use this software for any purpose
  5.  * on any computer system, and to redistribute it freely, with the
  6.  * following restrictions:
  7.  * 1) No charge may be made other than reasonable charges for reproduction.
  8.  * 2) Modified versions must be clearly marked as such.
  9.  * 3) The authors are not responsible for any harmful consequences
  10.  *    of using this software, even if they result from defects in it.
  11.  */
  12.  
  13. /*
  14.  * 2-instruction peephole optimizations
  15.  */
  16.  
  17. #include "top.h"
  18.  
  19.  
  20. /*
  21.  * ipeep2(bp, i1) - look for 2-instruction optimizations at the given inst.
  22.  */
  23. static    bool
  24. ipeep2(bp, i1)
  25. BLOCK    *bp;
  26. register INST    *i1;
  27. {
  28.     register INST    *i2;        /* the next instruction */
  29.     register INST    *ti2;        /* "temporary" next inst */
  30.  
  31.     register int    op1, op2;    /* opcodes, for speed */
  32.     register int    sm1, dm1;    /* src, dst amode inst. 1 */
  33.     register int    dr1;        /* dest. reg. inst. 1 */
  34.  
  35.     i2  = i1->next;
  36.     op1 = i1->opcode;
  37.     op2 = i2->opcode;
  38.  
  39.     sm1 = i1->src.amode;
  40.     dm1 = i1->dst.amode;
  41.     dr1 = i1->dst.areg;
  42.  
  43.     /*
  44.      * Avoid stack fix-ups after a call if possible.
  45.      */
  46.  
  47.     /*
  48.      *    addq    #4,sp
  49.      *    ... stuff that doesn't use SP ...
  50.      *    move.l    ?,-(sp)        =>    move.l    ?,(sp)
  51.      */
  52.     if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 4 &&
  53.         dm1 == REG && dr1 == SP) {
  54.  
  55.         ti2 = i2;
  56.         while (!uses(ti2, SP)) {
  57.             if (ti2->next == NULL)
  58.                 goto end2;
  59.             ti2 = ti2->next;
  60.         }
  61.  
  62.         if (ti2->opcode == MOVE && ti2->flags == LENL &&
  63.             ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) {
  64.                 ti2->dst.amode = REGI;
  65.                 delinst(bp, i1);
  66.                 DBG(printf("%d ", __LINE__))
  67.                 return TRUE;
  68.         }
  69.     }
  70. end2:
  71.  
  72.     /*
  73.      *    addq    #2,sp
  74.      *    ... stuff that doesn't use SP ...
  75.      *    move.w    ?,-(sp)        =>    move.w    ?,(sp)
  76.      */
  77.     if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 2 &&
  78.         dm1 == REG && dr1 == SP) {
  79.  
  80.         ti2 = i2;
  81.         while (!uses(ti2, SP)) {
  82.             if (ti2->next == NULL)
  83.                 goto end3;
  84.             ti2 = ti2->next;
  85.         }
  86.  
  87.         if (ti2->opcode == MOVE && ti2->flags == LENW &&
  88.             ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) {
  89.                 ti2->dst.amode = REGI;
  90.                 delinst(bp, i1);
  91.                 DBG(printf("%d ", __LINE__))
  92.                 return TRUE;
  93.         }
  94.     }
  95. end3:
  96.  
  97.     /*
  98.      * Avoid "tst" instructions following instructions that
  99.      * set the Z flag.
  100.      */
  101.  
  102.     /*
  103.      *    move.x    X, Y        =>    move.x    X, Y
  104.      *    tst.x    X or Y            ...deleted...
  105.      *    beq/bne                beq/bne
  106.      *
  107.      *    Where Y is not An, because "movea" doesn't set the
  108.      *    zero flag.
  109.      */
  110.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  111.         op1 == MOVE && op2 == TST &&
  112.         i1->flags == i2->flags) {
  113.  
  114.         /*
  115.          * If pre-decrement is set on the dest. of the move,
  116.          * don't let that screw up the operand comparison.
  117.          */
  118.         if (dm1 & DEC)
  119.             dm1 &= ~DEC;
  120.  
  121.         if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) {
  122.             if (dm1 != REG || ISD(dr1)) {
  123.                     delinst(bp, i2);
  124.                     DBG(printf("%d ", __LINE__))
  125.                     return TRUE;
  126.             }
  127.         }
  128.     }
  129.  
  130.     /*
  131.      *    and.x    X, Y        =>    and.x    X, Y
  132.      *    tst.x    X or Y            ...deleted...
  133.      *    beq/bne                beq/bne
  134.      *
  135.      *    Where Y is not An, because "movea" doesn't set the
  136.      *    zero flag.
  137.      */
  138.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  139.         op1 == AND && op2 == TST &&
  140.         i1->flags == i2->flags) {
  141.  
  142.         /*
  143.          * If pre-decrement is set on the dest. of the move,
  144.          * don't let that screw up the operand comparison.
  145.          */
  146.         if (dm1 & DEC)
  147.             dm1 &= ~DEC;
  148.  
  149.         if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) {
  150.             if (dm1 != REG || ISD(dr1)) {
  151.                     delinst(bp, i2);
  152.                     DBG(printf("%d ", __LINE__))
  153.                     return TRUE;
  154.             }
  155.         }
  156.     }
  157.  
  158.     /*
  159.      *    ext.x    Dn        =>    ext.x    Dn
  160.      *    tst.x    Dn            ...deleted...
  161.      *    beq/bne                beq/bne
  162.      *
  163.      *    Where Y is not An, because "movea" doesn't set the
  164.      *    zero flag.
  165.      */
  166.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  167.         op1 == EXT && op2 == TST &&
  168.         i1->flags == i2->flags) {
  169.  
  170.         if (sm1 == REG && ISD(i1->src.areg) &&
  171.             i2->src.amode == REG && i1->src.areg == i2->src.areg) {
  172.                 delinst(bp, i2);
  173.                 DBG(printf("%d ", __LINE__))
  174.                 return TRUE;
  175.         }
  176.     }
  177.  
  178.     /*
  179.      *    move.?    X, Dn        =>    move.?    X, Dn
  180.      *    ext.?    Dn            ...deleted...
  181.      *    beq/bne                beq/bne
  182.      *
  183.      *    Where Dn is dead after the "ext".
  184.      */
  185.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  186.         op1 == MOVE && op2 == EXT) {
  187.  
  188.         if (dm1 == REG && ISD(dr1) &&
  189.             i2->src.amode == REG && dr1 == i2->src.areg) {
  190.             if ((i2->live & RM(i2->src.areg)) == 0) {
  191.                 delinst(bp, i2);
  192.                     DBG(printf("%d ", __LINE__))
  193.                  return TRUE;
  194.             }
  195.         }
  196.     }
  197.  
  198.     /*
  199.      *    ext.l    Dm        =>    ...deleted...
  200.      *    tst.l    Dm            tst.w    Dm
  201.      *
  202.      *    where Dm is dead after the "tst".
  203.      */
  204.     if (op1 == EXT && op2 == TST &&
  205.         ((i1->flags & LENL) != 0) &&  ((i2->flags & LENL) != 0) &&
  206.         (i1->src.areg == i2->src.areg) && ISD(i1->src.areg)) {
  207.  
  208.         if ((i2->live & RM(i2->src.areg)) == 0) {
  209.             i2->flags = LENW;
  210.             delinst(bp, i1);
  211.                 DBG(printf("%d ", __LINE__))
  212.             return TRUE;
  213.         }
  214.     }
  215.  
  216.     /*
  217.      *    ext.l    Dm        =>    ...deleted...
  218.      *    ???    N(An,Dm.l), ??        ???    N(An,Dm.w), ??
  219.      *
  220.      *    Where Dm is dead
  221.      */
  222.     if ((op1 == EXT) && (i1->flags & LENL) &&
  223.         (i2->src.amode == (REGIDX|XLONG)) &&
  224.         (i1->src.areg == i2->src.ireg)) {
  225.  
  226.         if ((i2->live & RM(i1->src.areg)) == 0) {
  227.             i2->src.amode &= ~XLONG;
  228.             delinst(bp, i1);
  229.                 DBG(printf("%d ", __LINE__))
  230.             return TRUE;
  231.         }
  232.     }
  233.  
  234.     /*
  235.      *    ext.l    Dm        =>    ...deleted...
  236.      *    ???    ??, N(An,Dm.l)        ???    ??, N(An,Dm.w)
  237.      *
  238.      *    Where Dm is dead
  239.      */
  240.     if ((op1 == EXT) && (i1->flags & LENL) &&
  241.         (i2->dst.amode == (REGIDX|XLONG)) &&
  242.         (i1->src.areg == i2->dst.ireg)) {
  243.  
  244.         if ((i2->live & RM(i1->src.areg)) == 0) {
  245.             i2->dst.amode &= ~XLONG;
  246.             delinst(bp, i1);
  247.                 DBG(printf("%d ", __LINE__))
  248.             return TRUE;
  249.         }
  250.     }
  251.  
  252.     /*
  253.      * Avoid intermediate registers.
  254.      */
  255.  
  256.     /*
  257.      *    move.x    X, Dm        =>    INST.x    X, Dn
  258.      *    INST.x    Dm, Dn
  259.      *
  260.      *    where Dm is dead, and INST is one of: add, sub, and, or, cmp
  261.      */
  262.     if ((op1 == MOVE) &&
  263.         ((op2==ADD)||(op2==SUB)||(op2==AND)||(op2==OR)||(op2==CMP)) &&
  264.         (i1->flags == i2->flags) &&
  265.         (dm1 == REG) && ISD(dr1) &&
  266.         (i2->src.amode == REG) && ISD(i2->src.areg) &&
  267.         (dr1 == i2->src.areg) &&
  268.         (i2->dst.amode == REG) && ISD(i2->dst.areg)) {
  269.  
  270.         if ((i2->live & RM(i2->src.areg)) == 0) {
  271.  
  272.             i1->opcode = i2->opcode;
  273.             i1->dst.areg = i2->dst.areg;
  274.  
  275.             delinst(bp, i2);
  276.                 DBG(printf("%d ", __LINE__))
  277.             return TRUE;
  278.         }
  279.     }
  280.  
  281.     /*
  282.      * Silly moves
  283.      */
  284.  
  285.     /*
  286.      *    move.x    X, Y        =>    move.x    X, Y
  287.      *    move.x    Y, X
  288.      */
  289.     if ((op1 == MOVE) && (op2 == MOVE) &&
  290.         (i1->flags == i2->flags) &&
  291.         opeq(&i1->src, &i2->dst) && opeq(&i1->dst, &i2->src) &&
  292.         ((i1->src.amode & (INC|DEC)) == 0) &&
  293.         ((i1->dst.amode & (INC|DEC)) == 0)) {
  294.  
  295.              delinst(bp, i2);
  296.             DBG(printf("%d ", __LINE__))
  297.              return TRUE;
  298.     }
  299.  
  300.     /*
  301.      *    move.x    X, Y        =>    move.x    X, Rn
  302.      *    move.x    Y, Rn            move.x    Rn, Y
  303.      *
  304.      *    where Y isn't INC or DEC, and isn't register direct
  305.      */
  306.     if ((op1 == MOVE) && (op2 == MOVE) && (i2->dst.amode == REG) &&
  307.         opeq(&i1->dst, &i2->src) && ((i1->dst.amode & (INC|DEC)) == 0) &&
  308.         (i1->flags == i2->flags) && (i1->dst.amode != REG) &&
  309.         !uses(i1, i2->dst.areg)) {
  310.  
  311.         freeop(&i1->dst);
  312.         i1->dst = i2->dst;
  313.         i2->dst = i2->src;
  314.         i2->src = i1->dst;
  315.  
  316.             DBG(printf("%d ", __LINE__))
  317.         return TRUE;
  318.     }
  319.  
  320.     /*
  321.      *    move.x    Dm, X        =>    move.x    Dm, X
  322.      *    move.x    X, Y            move.x    Dm, Y
  323.      *
  324.      * Where 'x' is the same, and 'X' has no side-effects.
  325.      */
  326.     if ((op1 == MOVE) && (op2 == MOVE) &&
  327.         (sm1 == REG) && ISD(i1->src.areg) &&
  328.         (i1->flags == i2->flags) && opeq(&i1->dst, &i2->src) &&
  329.         ((dm1 & (DEC|INC)) == 0)) {
  330.  
  331.  
  332.         freeop(&i2->src);
  333.         i2->src = i1->src;
  334.             DBG(printf("%d ", __LINE__))
  335.              return TRUE;
  336.     }
  337.  
  338.     /*
  339.      *    move.?    Rm, Rn        =>    move.?    Rm, Rn
  340.      *    ... stuff ...            ... stuff ...
  341.      *    move.?    Rm, Rn
  342.      *
  343.      *    where "stuff" doesn't set Rm or Rn. Also make sure that
  344.      *    the second move isn't followed by a conditional branch.
  345.      *    In that case leave everything alone since the branch
  346.      *    probably relies on flags set by the move.
  347.      */
  348.     if ((op1 == MOVE) && (sm1 == REG) && (dm1 == REG)) {
  349.         int    s1 = i1->src.areg;    /* source reg of inst. 1 */
  350.  
  351.         ti2 = i2;
  352.         while (ti2 != NULL && !sets(ti2, s1) && !sets(ti2, dr1)) {
  353.  
  354.             if ((ti2->opcode==MOVE) && (i1->flags==ti2->flags) &&
  355.                 (ti2->src.amode==REG) && (ti2->dst.amode==REG) &&
  356.                 (i1->src.areg == ti2->src.areg) &&
  357.                 (i1->dst.areg == ti2->dst.areg) &&
  358.                 ((bp->last != ti2) || (bp->bcond == NULL)) ) {
  359.  
  360.                      delinst(bp, ti2);
  361.                     DBG(printf("%d ", __LINE__))
  362.                      return TRUE;
  363.             }
  364.             ti2 = ti2->next;
  365.         }
  366.     }
  367.  
  368.     /*
  369.      *    move.l    Am, Dn        =>    move.l    Am, Ao
  370.      *    ... stuff ...            ... stuff ...
  371.      *    move.l    Dn, Ao
  372.      *
  373.      *    where "stuff" doesn't set Dn.
  374.      */
  375.     if ((op1 == MOVE) && (i1->flags == LENL) &&
  376.         (sm1 == REG) && ISA(i1->src.areg) &&
  377.         (dm1 == REG) && ISD(dr1)) {
  378.  
  379.         ti2 = i2;
  380.         while (!sets(ti2, dr1)) {
  381.  
  382.             if ((ti2->opcode == MOVE) && (ti2->flags == LENL) &&
  383.                 (ti2->src.amode == REG) && ISD(ti2->src.areg) &&
  384.                 (ti2->dst.amode == REG) && ISA(ti2->dst.areg) &&
  385.                 (dr1 == ti2->src.areg)) {
  386.     
  387.                 /*
  388.                  * If the intermediate register isn't dead,
  389.                  * then we have to keep using it.
  390.                  */
  391.                 if ((ti2->live & RM(ti2->src.areg)) != 0)
  392.                     goto end14;
  393.     
  394.                 i1->dst.areg = ti2->dst.areg;
  395.     
  396.                      delinst(bp, ti2);
  397.                     DBG(printf("%d ", __LINE__))
  398.                      return TRUE;
  399.             }
  400.  
  401.             if (ti2->next == NULL)
  402.                 goto end14;
  403.  
  404.             ti2 = ti2->next;
  405.         }
  406.     }
  407. end14:
  408.  
  409.     /*
  410.      *    move.l    Dm, An        =>    move.l    Dm, Ao
  411.      *    lea    (An), Ao
  412.      *
  413.      *    where An is dead
  414.      */
  415.     if ((op1 == MOVE) && (op2 == LEA) &&
  416.         (sm1 == REG) && ISD(i1->src.areg) &&
  417.         (dm1 == REG) && ISA(dr1) &&
  418.         (i2->src.amode == REGI) && (i2->dst.amode == REG) &&
  419.         ISA(i2->dst.areg) && (dr1 == i2->src.areg)) {
  420.  
  421.         if ((i2->live & RM(i2->src.areg)) == 0) {
  422.  
  423.             i1->dst.areg = i2->dst.areg;
  424.  
  425.             delinst(bp, i2);
  426.                 DBG(printf("%d ", __LINE__))
  427.             return TRUE;
  428.         }
  429.     }
  430.  
  431.     /*
  432.      *    lea    X, An        =>    lea    X, Ao
  433.      *    lea    (An), Ao
  434.      *
  435.      *    where An is dead
  436.      */
  437.     if ((op1 == LEA) && (op2 == LEA) &&
  438.         (i2->src.amode == REGI) && (dr1 == i2->src.areg)) {
  439.  
  440.         if ((i2->live & RM(i2->src.areg)) == 0) {
  441.  
  442.             i1->dst.areg = i2->dst.areg;
  443.  
  444.             delinst(bp, i2);
  445.                 DBG(printf("%d ", __LINE__))
  446.             return TRUE;
  447.         }
  448.     }
  449.  
  450.     /*
  451.      *    lea    N(Am), Am    =>
  452.      *    ?    (Am)[,...]        ?    N(Am)[,...]
  453.      *
  454.      *    Where Am is either dead after the second instruction or
  455.      *    is a direct destination of the second instruction.
  456.      */
  457.     if ((op1 == LEA) && (i1->src.amode == REGID) &&
  458.         (i1->src.areg == i1->dst.areg) &&
  459.         (i2->src.amode == REGI) && (i1->dst.areg == i2->src.areg)) {
  460.  
  461.         if (((i2->live & RM(i2->src.areg)) == 0) ||
  462.            ((i2->dst.amode == REG) && (i2->dst.areg == i2->src.areg))) {
  463.             i2->src.amode = REGID;
  464.             i2->src.disp = i1->src.disp;
  465.             delinst(bp, i1);
  466.                 DBG(printf("%d ", __LINE__))
  467.             return TRUE;
  468.         }
  469.     }
  470.  
  471.     /*
  472.      *    lea    N(Am), Am    =>
  473.      *    ?    X, (Am)            ?    X, N(Am)
  474.      *
  475.      *    Where X doesn't reference Am, and Am is dead after the
  476.      *    second instruction.
  477.      */
  478.     if ((op1 == LEA) && (i1->src.amode == REGID) &&
  479.         (i1->src.areg == i1->dst.areg) &&
  480.         (i2->dst.amode == REGI) && (i1->dst.areg == i2->dst.areg)) {
  481.  
  482.         if (((i2->live & RM(i2->dst.areg)) == 0) &&
  483.             ((i2->src.amode == IMM) || (i2->src.amode == ABS) ||
  484.              (i2->src.areg != i2->dst.areg))) {
  485.             i2->dst.amode = REGID;
  486.             i2->dst.disp = i1->src.disp;
  487.             delinst(bp, i1);
  488.                 DBG(printf("%d ", __LINE__))
  489.             return TRUE;
  490.         }
  491.     }
  492.  
  493.     /*
  494.      *    lea    X, Am        =>    ...deleted...
  495.      *    clr.x    (Am)            clr.x    X
  496.      *
  497.      *    where Am is dead
  498.      */
  499.     if ((op1 == LEA) && (op2 == CLR) && i2->src.amode == REGI &&
  500.         (i1->dst.areg == i2->src.areg)) {
  501.  
  502.         if ((i2->live & RM(i2->src.areg)) == 0) {
  503.             i2->src = i1->src;
  504.     
  505.             delinst(bp, i1);
  506.                 DBG(printf("%d ", __LINE__))
  507.             return TRUE;
  508.         }
  509.     }
  510.  
  511.     /*
  512.      *    lea    X, Am        =>    ...deleted...
  513.      *    move.x    Y, (Am)            move.x    Y, X
  514.      *
  515.      *    where Am is dead
  516.      */
  517.     if ((op1 == LEA) && (op2 == MOVE) && i2->dst.amode == REGI &&
  518.         (i1->dst.areg == i2->dst.areg)) {
  519.  
  520.         if ((i2->live & RM(i2->dst.areg)) == 0) {
  521.             i2->dst = i1->src;
  522.  
  523.             delinst(bp, i1);
  524.                 DBG(printf("%d ", __LINE__))
  525.             return TRUE;
  526.         }
  527.     }
  528.  
  529.     /*
  530.      *    lea    X, Am        =>    ...deleted...
  531.      *    move.x    (Am), Y            move.x    X, Y
  532.      *
  533.      *    where Am is dead
  534.      */
  535.     if ((op1 == LEA) && (op2 == MOVE) && i2->src.amode == REGI &&
  536.         (i1->dst.areg == i2->src.areg)) {
  537.  
  538.         if ((i2->live & RM(i2->src.areg)) == 0) {
  539.             i2->src = i1->src;
  540.  
  541.             delinst(bp, i1);
  542.                 DBG(printf("%d ", __LINE__))
  543.             return TRUE;
  544.         }
  545.     }
  546.  
  547.     /*
  548.      *    move.x    Dm, X        =>    move.x    Dm, X
  549.      *    cmp.x    #N, X            cmp.x    #N, Dm
  550.      *
  551.      *    Where X isn't register direct.
  552.      *
  553.      *    Since X generally references memory, we can compare
  554.      *    with the register faster.
  555.      */
  556.     if ((op1 == MOVE) && (op2 == CMP) &&
  557.         (i1->flags == i2->flags) && (i2->src.amode == IMM) &&
  558.         (sm1 == REG) && ISD(i1->src.areg) && (dm1 != REG) &&
  559.         opeq(&i1->dst, &i2->dst) && ((dm1 & (INC|DEC)) == 0)) {
  560.  
  561.         freeop(&i2->dst);
  562.         i2->dst.amode = REG;
  563.         i2->dst.areg = i1->src.areg;
  564.  
  565.             DBG(printf("%d ", __LINE__))
  566.         return TRUE;
  567.     }
  568.  
  569.  
  570.     /*
  571.      * Try to use register indirect w/ displacement and/or index
  572.      */
  573.  
  574.     /*
  575.      *    add.l    Am, Dn        =>    lea    0(Am,Dn.l), Ao
  576.      *    move.l    Dn, Ao
  577.      *
  578.      *    where Dn is dead
  579.      */
  580.     if ((op1 == ADD) && (op2 == MOVE) &&
  581.         (sm1 == REG) && ISA(i1->src.areg) &&
  582.         (dm1 == REG) && ISD(dr1) &&
  583.         (i2->src.amode == REG) && ISD(i2->src.areg) &&
  584.         (i2->dst.amode == REG) && ISA(i2->dst.areg) &&
  585.         (dr1 == i2->src.areg) &&
  586.         (i1->flags & LENL) && (i2->flags & LENL)) {
  587.  
  588.         if ((i2->live & RM(i2->src.areg)) == 0) {
  589.  
  590.             i2->opcode = LEA;
  591.             i2->flags = 0;
  592.  
  593.             i2->src.amode = REGIDX|XLONG;
  594.             i2->src.disp = 0;
  595.             i2->src.areg = i1->src.areg;
  596.             i2->src.ireg = dr1;
  597.  
  598.                 delinst(bp, i1);
  599.                 DBG(printf("%d ", __LINE__))
  600.                 return TRUE;
  601.         }
  602.     }
  603.  
  604.     /*
  605.      *    add.l    Dm, An        =>    move.x    0(An,Dm.l), Do
  606.      *    move.x    (An), Do
  607.      *
  608.      *    where An is dead
  609.      */
  610.     if ((op1 == ADD) && (op2 == MOVE) &&
  611.         (sm1 == REG) && ISD(i1->src.areg) &&
  612.         (dm1 == REG) && ISA(dr1) &&
  613.         (i2->src.amode == REGI)&& ISA(i2->src.areg) &&
  614.         (i2->dst.amode == REG) && ISD(i2->dst.areg) &&
  615.         (dr1 == i2->src.areg) && (i1->flags & LENL)) {
  616.  
  617.         if ((i2->live & RM(i2->src.areg)) == 0) {
  618.  
  619.             i2->src.amode = REGIDX|XLONG;
  620.             i2->src.disp = 0;
  621.             i2->src.ireg = i1->src.areg;
  622.  
  623.                 delinst(bp, i1);
  624.                 DBG(printf("%d ", __LINE__))
  625.                 return TRUE;
  626.         }
  627.     }
  628.  
  629.     /*
  630.      *    lea    N(Am), An    =>    lea    N(Am,Do.l), An
  631.      *    add.l    Do, An
  632.      *
  633.      */
  634.     if ((op1 == LEA) && (op2 == ADD) &&
  635.         (sm1 == REGID) &&
  636.         (i2->src.amode == REG) && ISD(i2->src.areg) &&
  637.         (i2->dst.amode == REG) && ISA(i2->dst.areg) &&
  638.         (dr1 == i2->dst.areg) && D8OK(i1->src.disp)) {
  639.  
  640.         i1->src.amode = REGIDX|XLONG;
  641.         i1->src.ireg = i2->src.areg;
  642.         delinst(bp, i2);
  643.             DBG(printf("%d ", __LINE__))
  644.         return TRUE;
  645.     }
  646.  
  647.  
  648.  
  649.     /*
  650.      * Try to use the pre-decrement and post-increment modes
  651.      * whenever possible.
  652.      */
  653.  
  654.     /*
  655.      *    sub.l    #1, Am
  656.      *    ... stuff ...
  657.      *    ???.b    ..(Am)..    =>    ???.b    ..-(Am)..
  658.      *
  659.      *    Nothing in "stuff" can refer to Am.
  660.      */
  661.     if ((op1 == SUB) && (i1->flags & LENL) &&
  662.         (sm1 == IMM) && (i1->src.disp == 1) &&
  663.         (dm1 == REG) && ISA(dr1)) {
  664.  
  665.         while (i2 != NULL) {
  666.  
  667.             if (i2->src.amode == REGI && i2->src.areg == dr1) {
  668.  
  669.                 if ((i2->flags & LENB) == 0)
  670.                     goto end24;
  671.  
  672.                 i2->src.amode |= DEC;
  673.  
  674.                     delinst(bp, i1);
  675.                     DBG(printf("%d ", __LINE__))
  676.                     return TRUE;
  677.             }
  678.             if (i2->dst.amode == REGI && i2->dst.areg == dr1) {
  679.  
  680.                 if ((i2->flags & LENB) == 0)
  681.                     goto end24;
  682.  
  683.                 i2->dst.amode |= DEC;
  684.  
  685.                     delinst(bp, i1);
  686.                     DBG(printf("%d ", __LINE__))
  687.                     return TRUE;
  688.             }
  689.             if (uses(i2, dr1))
  690.                 goto end24;
  691.  
  692.             if (i2->next == NULL)
  693.                 goto end24;
  694.             else
  695.                 i2 = i2->next;
  696.  
  697.         }
  698.     }
  699. end24:
  700.  
  701.     /*
  702.      *    sub.l    #2, Am
  703.      *    ... stuff ...
  704.      *    ???.w    ..(Am)..    =>    ???.w    ..-(Am)..
  705.      *
  706.      *    Nothing in "stuff" can refer to Am.
  707.      */
  708.     if ((op1 == SUB) && (i1->flags & LENL) &&
  709.         (sm1 == IMM) && (i1->src.disp == 2) &&
  710.         (dm1 == REG) && ISA(dr1)) {
  711.  
  712.         while (i2 != NULL) {
  713.  
  714.             if (i2->src.amode == REGI && i2->src.areg == dr1) {
  715.  
  716.                 if ((i2->flags & LENW) == 0)
  717.                     goto end26;
  718.  
  719.                 i2->src.amode |= DEC;
  720.  
  721.                     delinst(bp, i1);
  722.                     DBG(printf("%d ", __LINE__))
  723.                     return TRUE;
  724.             }
  725.             if (i2->dst.amode == REGI && i2->dst.areg == dr1) {
  726.  
  727.                 if ((i2->flags & LENW) == 0)
  728.                     goto end26;
  729.  
  730.                 i2->dst.amode |= DEC;
  731.  
  732.                     delinst(bp, i1);
  733.                     DBG(printf("%d ", __LINE__))
  734.                     return TRUE;
  735.             }
  736.  
  737.             if (uses(i2, dr1))
  738.                 goto end26;
  739.  
  740.             if (i2->next == NULL)
  741.                 goto end26;
  742.             else
  743.                 i2 = i2->next;
  744.  
  745.         }
  746.     }
  747. end26:
  748.  
  749.     /*
  750.      *    sub.l    #4, Am
  751.      *    ... stuff ...
  752.      *    ???.l    ..(Am)..    =>    ???.l    ..-(Am)..
  753.      *
  754.      *    Nothing in "stuff" can refer to Am.
  755.      */
  756.     if ((op1 == SUB) && (i1->flags & LENL) &&
  757.         (sm1 == IMM) && (i1->src.disp == 4) &&
  758.         (dm1 == REG) && ISA(dr1)) {
  759.  
  760.         while (i2 != NULL) {
  761.  
  762.             if (i2->src.amode == REGI && i2->src.areg == dr1) {
  763.  
  764.                 if ((i2->flags & LENL) == 0)
  765.                     goto end28;
  766.  
  767.                 i2->src.amode |= DEC;
  768.  
  769.                     delinst(bp, i1);
  770.                     DBG(printf("%d ", __LINE__))
  771.                     return TRUE;
  772.             }
  773.             if (i2->dst.amode == REGI && i2->dst.areg == dr1) {
  774.  
  775.                 if ((i2->flags & LENL) == 0)
  776.                     goto end28;
  777.  
  778.                 i2->dst.amode |= DEC;
  779.  
  780.                     delinst(bp, i1);
  781.                     DBG(printf("%d ", __LINE__))
  782.                     return TRUE;
  783.             }
  784.  
  785.             if (uses(i2, dr1))
  786.                 goto end28;
  787.  
  788.             if (i2->next == NULL)
  789.                 goto end28;
  790.             else
  791.                 i2 = i2->next;
  792.  
  793.         }
  794.     }
  795. end28:
  796.  
  797.     return FALSE;
  798. }
  799.  
  800. /*
  801.  * peep2(bp) - scan blocks starting at 'bp'
  802.  */
  803. bool
  804. peep2(bp)
  805. register BLOCK    *bp;
  806. {
  807.     register INST    *ip;
  808.     register bool    changed = FALSE;
  809.  
  810.     DBG(printf("p2 :"))
  811.  
  812.     for (; bp != NULL ;bp = bp->next) {
  813.         for (ip = bp->first; ip != NULL && ip->next != NULL ;) {
  814.             if (ipeep2(bp, ip)) {
  815.                 changed = TRUE;
  816.                 s_peep2++;
  817.                 bprep(bp);
  818.                 /*
  819.                  * If we had a match, then either instruction
  820.                  * may have been deleted, so the safe thing to
  821.                  * do is to go to the next block.
  822.                  */
  823.                 break;
  824.             } else
  825.                 ip = ip->next;
  826.         }
  827.     }
  828.     DBG(printf("\n"); fflush(stdout))
  829.     return changed;
  830. }
  831.