home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 6 / FreshFish_September1994.bin / new / dev / c / hce / hcesource / top / source / peep2.c < prev    next >
C/C++ Source or Header  |  1992-09-02  |  18KB  |  837 lines

  1. /* Copyright (c) 1988,1991 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. /*
  20.  * ipeep2(bp, i1) - look for 2-instruction optimizations at the given inst.
  21.  */
  22. static    bool
  23. ipeep2(bp, i1)
  24. BLOCK    *bp;
  25. register INST    *i1;
  26. {
  27.     register INST    *i2;        /* the next instruction */
  28.     register INST    *ti2;        /* "temporary" next inst */
  29.  
  30.     register int    op1, op2;    /* opcodes, for speed */
  31.     register int    sm1, dm1;    /* src, dst amode inst. 1 */
  32.     register int    dr1;        /* dest. reg. inst. 1 */
  33.  
  34.     i2  = i1->next;
  35.     op1 = i1->opcode;
  36.     op2 = i2->opcode;
  37.  
  38.     sm1 = i1->src.amode;
  39.     dm1 = i1->dst.amode;
  40.     dr1 = i1->dst.areg;
  41.  
  42.     /*
  43.      * Avoid stack fix-ups after a call if possible.
  44.      */
  45.  
  46.     if (gflag)                /* V2 */
  47.         goto skip_stack_stuff;        /* V2 */
  48.  
  49.     /*
  50.      *    addq    #4,sp
  51.      *    ... stuff that doesn't use SP ...
  52.      *    move.l    ?,-(sp)        =>    move.l    ?,(sp)
  53.      */
  54.     if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 4 &&
  55.         dm1 == REG && dr1 == SP) {
  56.  
  57.         ti2 = i2;
  58.         while (!uses(ti2, SP)) {
  59.             if (ti2->next == NULL)
  60.                 goto end2;
  61.             ti2 = ti2->next;
  62.         }
  63.  
  64.         if (ti2->opcode == MOVE && ti2->flags == LENL &&
  65.             ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) {
  66.                 ti2->dst.amode = REGI;
  67.                 delinst(bp, i1);
  68.                 DBG(printf("%d ", __LINE__))
  69.                 return TRUE;
  70.         }
  71.     }
  72. end2:
  73.  
  74.     /*
  75.      *    addq    #2,sp
  76.      *    ... stuff that doesn't use SP ...
  77.      *    move.w    ?,-(sp)        =>    move.w    ?,(sp)
  78.      */
  79.     if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 2 &&
  80.         dm1 == REG && dr1 == SP) {
  81.  
  82.         ti2 = i2;
  83.         while (!uses(ti2, SP)) {
  84.             if (ti2->next == NULL)
  85.                 goto end3;
  86.             ti2 = ti2->next;
  87.         }
  88.  
  89.         if (ti2->opcode == MOVE && ti2->flags == LENW &&
  90.             ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) {
  91.                 ti2->dst.amode = REGI;
  92.                 delinst(bp, i1);
  93.                 DBG(printf("%d ", __LINE__))
  94.                 return TRUE;
  95.         }
  96.     }
  97. end3:
  98.  
  99. skip_stack_stuff:    /* V2 */
  100.  
  101.     /*
  102.      * Avoid "tst" instructions following instructions that
  103.      * set the Z flag.
  104.      */
  105.  
  106.     /*
  107.      *    move.x    X, Y        =>    move.x    X, Y
  108.      *    tst.x    X or Y            ...deleted...
  109.      *    beq/bne                beq/bne
  110.      *
  111.      *    Where Y is not An, because "movea" doesn't set the
  112.      *    zero flag.
  113.      */
  114.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  115.         op1 == MOVE && op2 == TST &&
  116.         i1->flags == i2->flags) {
  117.  
  118.         /*
  119.          * If pre-decrement is set on the dest. of the move,
  120.          * don't let that screw up the operand comparison.
  121.          */
  122.         if (dm1 & DEC)
  123.             dm1 &= ~DEC;
  124.  
  125.         if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) {
  126.             if (dm1 != REG || ISD(dr1)) {
  127.                     delinst(bp, i2);
  128.                     DBG(printf("%d ", __LINE__))
  129.                     return TRUE;
  130.             }
  131.         }
  132.     }
  133.  
  134.     /*
  135.      *    and.x    X, Y        =>    and.x    X, Y
  136.      *    tst.x    X or Y            ...deleted...
  137.      *    beq/bne                beq/bne
  138.      *
  139.      *    Where Y is not An, because "movea" doesn't set the
  140.      *    zero flag.
  141.      */
  142.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  143.         op1 == AND && op2 == TST &&
  144.         i1->flags == i2->flags) {
  145.  
  146.         /*
  147.          * If pre-decrement is set on the dest. of the move,
  148.          * don't let that screw up the operand comparison.
  149.          */
  150.         if (dm1 & DEC)
  151.             dm1 &= ~DEC;
  152.  
  153.         if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) {
  154.             if (dm1 != REG || ISD(dr1)) {
  155.                     delinst(bp, i2);
  156.                     DBG(printf("%d ", __LINE__))
  157.                     return TRUE;
  158.             }
  159.         }
  160.     }
  161.  
  162.     /*
  163.      *    ext.x    Dn        =>    ext.x    Dn
  164.      *    tst.x    Dn            ...deleted...
  165.      *    beq/bne                beq/bne
  166.      *
  167.      *    Where Y is not An, because "movea" doesn't set the
  168.      *    zero flag.
  169.      */
  170.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  171.         op1 == EXT && op2 == TST &&
  172.         i1->flags == i2->flags) {
  173.  
  174.         if (sm1 == REG && ISD(i1->src.areg) &&
  175.             i2->src.amode == REG && i1->src.areg == i2->src.areg) {
  176.                 delinst(bp, i2);
  177.                 DBG(printf("%d ", __LINE__))
  178.                 return TRUE;
  179.         }
  180.     }
  181.  
  182.     /*
  183.      *    move.?    X, Dn        =>    move.?    X, Dn
  184.      *    ext.?    Dn            ...deleted...
  185.      *    beq/bne                beq/bne
  186.      *
  187.      *    Where Dn is dead after the "ext".
  188.      */
  189.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  190.         op1 == MOVE && op2 == EXT) {
  191.  
  192.         if (dm1 == REG && ISD(dr1) &&
  193.             i2->src.amode == REG && dr1 == i2->src.areg) {
  194.             if ((i2->live & RM(i2->src.areg)) == 0) {
  195.                 delinst(bp, i2);
  196.                     DBG(printf("%d ", __LINE__))
  197.                  return TRUE;
  198.             }
  199.         }
  200.     }
  201.  
  202.     /*
  203.      *    ext.l    Dm        =>    ...deleted...
  204.      *    tst.l    Dm            tst.w    Dm
  205.      *
  206.      *    where Dm is dead after the "tst".
  207.      */
  208.     if (op1 == EXT && op2 == TST &&
  209.         ((i1->flags & LENL) != 0) &&  ((i2->flags & LENL) != 0) &&
  210.         (i1->src.areg == i2->src.areg) && ISD(i1->src.areg)) {
  211.  
  212.         if ((i2->live & RM(i2->src.areg)) == 0) {
  213.             i2->flags = LENW;
  214.             delinst(bp, i1);
  215.                 DBG(printf("%d ", __LINE__))
  216.             return TRUE;
  217.         }
  218.     }
  219.  
  220.     /*
  221.      *    ext.l    Dm        =>    ...deleted...
  222.      *    ???    N(An,Dm.l), ??        ???    N(An,Dm.w), ??
  223.      *
  224.      *    Where Dm is dead
  225.      */
  226.     if ((op1 == EXT) && (i1->flags & LENL) &&
  227.         (i2->src.amode == (REGIDX|XLONG)) &&
  228.         (i1->src.areg == i2->src.ireg)) {
  229.  
  230.         if ((i2->live & RM(i1->src.areg)) == 0) {
  231.             i2->src.amode &= ~XLONG;
  232.             delinst(bp, i1);
  233.                 DBG(printf("%d ", __LINE__))
  234.             return TRUE;
  235.         }
  236.     }
  237.  
  238.     /*
  239.      *    ext.l    Dm        =>    ...deleted...
  240.      *    ???    ??, N(An,Dm.l)        ???    ??, N(An,Dm.w)
  241.      *
  242.      *    Where Dm is dead
  243.      */
  244.     if ((op1 == EXT) && (i1->flags & LENL) &&
  245.         (i2->dst.amode == (REGIDX|XLONG)) &&
  246.         (i1->src.areg == i2->dst.ireg)) {
  247.  
  248.         if ((i2->live & RM(i1->src.areg)) == 0) {
  249.             i2->dst.amode &= ~XLONG;
  250.             delinst(bp, i1);
  251.                 DBG(printf("%d ", __LINE__))
  252.             return TRUE;
  253.         }
  254.     }
  255.  
  256.     /*
  257.      * Avoid intermediate registers.
  258.      */
  259.  
  260.     /*
  261.      *    move.x    X, Dm        =>    INST.x    X, Dn
  262.      *    INST.x    Dm, Dn
  263.      *
  264.      *    where Dm is dead, and INST is one of: add, sub, and, or, cmp
  265.      */
  266.     if ((op1 == MOVE) &&
  267.         ((op2==ADD)||(op2==SUB)||(op2==AND)||(op2==OR)||(op2==CMP)) &&
  268.         (i1->flags == i2->flags) &&
  269.         (dm1 == REG) && ISD(dr1) &&
  270.         (i2->src.amode == REG) && ISD(i2->src.areg) &&
  271.         (dr1 == i2->src.areg) &&
  272.         (i2->dst.amode == REG) && ISD(i2->dst.areg)) {
  273.  
  274.         if ((i2->live & RM(i2->src.areg)) == 0) {
  275.  
  276.             i1->opcode = i2->opcode;
  277.             i1->dst.areg = i2->dst.areg;
  278.  
  279.             delinst(bp, i2);
  280.                 DBG(printf("%d ", __LINE__))
  281.             return TRUE;
  282.         }
  283.     }
  284.  
  285.     /*
  286.      * Silly moves
  287.      */
  288.  
  289.     /*
  290.      *    move.x    X, Y        =>    move.x    X, Y
  291.      *    move.x    Y, X
  292.      */
  293.     if ((op1 == MOVE) && (op2 == MOVE) &&
  294.         (i1->flags == i2->flags) &&
  295.         opeq(&i1->src, &i2->dst) && opeq(&i1->dst, &i2->src) &&
  296.         ((i1->src.amode & (INC|DEC)) == 0) &&
  297.         ((i1->dst.amode & (INC|DEC)) == 0)) {
  298.  
  299.              delinst(bp, i2);
  300.             DBG(printf("%d ", __LINE__))
  301.              return TRUE;
  302.     }
  303.  
  304.     /*
  305.      *    move.x    X, Y        =>    move.x    X, Rn
  306.      *    move.x    Y, Rn            move.x    Rn, Y
  307.      *
  308.      *    where Y isn't INC or DEC, and isn't register direct
  309.      *    and Y doesn't depend on Rn
  310.      */
  311.     if ((op1 == MOVE) && (op2 == MOVE) && (i2->dst.amode == REG) &&
  312.         opeq(&i1->dst, &i2->src) && ((i1->dst.amode & (INC|DEC)) == 0) &&
  313.         (i1->flags == i2->flags) && (i1->dst.amode != REG) &&
  314.         !uses(i1, i2->dst.areg)) {
  315.  
  316.         freeop(&i1->dst);
  317.         i1->dst = i2->dst;
  318.         i2->dst = i2->src;
  319.         i2->src = i1->dst;
  320.  
  321.         DBG(printf("%d ", __LINE__))
  322.         return TRUE;
  323.     }
  324.  
  325.  
  326.     /*
  327.      *    move.x    Dm, X        =>    move.x    Dm, X
  328.      *    move.x    X, Y            move.x    Dm, Y
  329.      *
  330.      * Where 'x' is the same, and 'X' has no side-effects.
  331.      */
  332.     if ((op1 == MOVE) && (op2 == MOVE) &&
  333.         (sm1 == REG) && ISD(i1->src.areg) &&
  334.         (i1->flags == i2->flags) && opeq(&i1->dst, &i2->src) &&
  335.         ((dm1 & (DEC|INC)) == 0)) {
  336.  
  337.         freeop(&i2->src);
  338.         i2->src = i1->src;
  339.            DBG(printf("%d ", __LINE__))
  340.             return TRUE;
  341.     }
  342.  
  343.     /*
  344.      *    move.?    Rm, Rn        =>    move.?    Rm, Rn
  345.      *    ... stuff ...            ... stuff ...
  346.      *    move.?    Rm, Rn
  347.      *
  348.      *    where "stuff" doesn't set Rm or Rn. Also make sure that
  349.      *    the second move isn't followed by a conditional branch.
  350.      *    In that case leave everything alone since the branch
  351.      *    probably relies on flags set by the move.
  352.      */
  353.     if ((op1 == MOVE) && (sm1 == REG) && (dm1 == REG)) {
  354.         int    s1 = i1->src.areg;    /* source reg of inst. 1 */
  355.