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

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