home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / sozobon / scsrc20 / top / peep3.c < prev    next >
C/C++ Source or Header  |  1991-02-22  |  13KB  |  545 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.  * 3-instruction peephole optimizations
  14.  */
  15.  
  16. #include "top.h"
  17.  
  18.  
  19. /*
  20.  * ipeep3(bp, ip) - look for 3-instruction optimizations at the given inst.
  21.  */
  22. static bool
  23. ipeep3(bp, i1)
  24. register BLOCK    *bp;
  25. register INST    *i1;
  26. {
  27.     register INST    *i2 = i1->next;    /* the next instruction */
  28.     INST    *i3 = i1->next->next;    /* the third instruction */
  29.  
  30.     register int    op1 = i1->opcode;
  31.     register int    op2 = i2->opcode;
  32.     register int    op3 = i3->opcode;
  33.  
  34.     /*
  35.      *    move.l    Am, Dn        =>    lea    N(Am), Ao
  36.      *    add.l    #N, Dn
  37.      *    move.l    Dn, Ao
  38.      *
  39.      *    Also, Dn must be dead after the third instruction.
  40.      */
  41.     if ((op1 == MOVE) && (i1->flags & LENL) &&
  42.         (i1->src.amode == REG) &&
  43.         ISA(i1->src.areg) &&
  44.         (i1->dst.amode == REG) &&
  45.         ISD(i1->dst.areg)) {
  46.  
  47.         if (((op2 == ADD) || (op2 == ADDQ)) &&
  48.             (i2->flags & LENL) &&
  49.             (i2->src.amode == IMM) &&
  50.             DOK(i2->src.disp) &&
  51.             (i2->dst.amode == REG) &&
  52.             (i2->dst.areg == i1->dst.areg)) {
  53.  
  54.             if ((op3 == MOVE) && (i3->flags & LENL) &&
  55.                 (i3->src.amode == REG) &&
  56.                 (i3->src.areg == i1->dst.areg) &&
  57.                 (i3->dst.amode == REG) &&
  58.                 ISA(i3->dst.areg) &&
  59.                 ((i3->live & RM(i3->src.areg)) == 0)) {
  60.  
  61.                 /*
  62.                  * rewrite i1 and delete i2 and i3
  63.                  */
  64.                 i1->opcode = LEA;
  65.                 i1->flags = 0;
  66.                 i1->dst = i3->dst;
  67.  
  68.                 i1->src.amode = REGID;
  69.                 i1->src.disp = i2->src.disp;
  70.  
  71.                     delinst(bp, i2);
  72.                     delinst(bp, i3);
  73.                     DBG(printf("%d ", __LINE__))
  74.                     return TRUE;
  75.             }
  76.         }
  77.     }
  78.  
  79.     /*
  80.      *    move.l    Dm, Dn        =>    move.l    Dm, Ao
  81.      *    add.l    #N, Dn            lea    N(Ao), Ao
  82.      *    move.l    Dn, Ao
  83.      *
  84.      *    Also, Dn must be dead after the third instruction.
  85.      */
  86.     if ((op1 == MOVE) && (i1->flags & LENL) &&
  87.         (i1->src.amode == REG) &&
  88.         ISD(i1->src.areg) &&
  89.         (i1->dst.amode == REG) &&
  90.         ISD(i1->dst.areg)) {
  91.  
  92.         if (((op2 == ADD) || (op2 == ADDQ)) &&
  93.             (i2->flags & LENL) &&
  94.             (i2->src.amode == IMM) &&
  95.             DOK(i2->src.disp) &&
  96.             (i2->dst.amode == REG) &&
  97.             (i2->dst.areg == i1->dst.areg)) {
  98.  
  99.             if ((op3 == MOVE) && (i3->flags & LENL) &&
  100.                 (i3->src.amode == REG) &&
  101.                 (i3->src.areg == i1->dst.areg) &&
  102.                 (i3->dst.amode == REG) &&
  103.                 ISA(i3->dst.areg) &&
  104.                 ((i3->live & RM(i3->src.areg)) == 0)) {
  105.  
  106.                 /*
  107.                  * rewrite i1 and i2 and delete i3
  108.                  */
  109.                 i1->dst.areg = i3->dst.areg;
  110.                 
  111.                 i2->opcode = LEA;
  112.                 i2->flags = 0;
  113.                 i2->dst = i3->dst;
  114.  
  115.                 i2->src.amode = REGID;
  116.                 i2->src.areg = i2->dst.areg;
  117.                 i2->src.disp = i2->src.disp;
  118.  
  119.                     delinst(bp, i3);
  120.                     DBG(printf("%d ", __LINE__))
  121.                     return TRUE;
  122.             }
  123.         }
  124.     }
  125.  
  126.     /*
  127.      *    move.l    Am, Dn        =>    lea    -N(Am), Ao
  128.      *    sub.l    #N, Dn
  129.      *    move.l    Dn, Ao
  130.      *
  131.      *    Also, Dn must be dead after the third instruction.
  132.      */
  133.     if ((op1 == MOVE) && (i1->flags & LENL) &&
  134.         (i1->src.amode == REG) &&
  135.         ISA(i1->src.areg) &&
  136.         (i1->dst.amode == REG) &&
  137.         ISD(i1->dst.areg)) {
  138.  
  139.         if (((op2 == SUB) || (op2 == ADDQ)) &&
  140.             (i2->flags & LENL) &&
  141.             (i2->src.amode == IMM) &&
  142.             DOK(i2->src.disp) &&
  143.             (i2->dst.amode == REG) &&
  144.             (i2->dst.areg == i1->dst.areg)) {
  145.  
  146.             if ((op3 == MOVE) && (i3->flags & LENL) &&
  147.                 (i3->src.amode == REG) &&
  148.                 (i3->src.areg == i1->dst.areg) &&
  149.                 (i3->dst.amode == REG) &&
  150.                 ISA(i3->dst.areg) &&
  151.                 ((i3->live & RM(i3->src.areg)) == 0)) {
  152.  
  153.                 /*
  154.                  * rewrite i1 and delete i2 and i3
  155.                  */
  156.                 i1->opcode = LEA;
  157.                 i1->flags = 0;
  158.                 i1->dst = i3->dst;
  159.  
  160.                 i1->src.amode = REGID;
  161.                 i1->src.disp = -i2->src.disp;
  162.  
  163.                     delinst(bp, i2);
  164.                     delinst(bp, i3);
  165.                     DBG(printf("%d ", __LINE__))
  166.                     return TRUE;
  167.             }
  168.         }
  169.     }
  170.  
  171.     /*
  172.      *    move.l    Am, Dn        =>    lea    0(Am, Do), Ap
  173.      *    add.x    Do, Dn
  174.      *    move.l    Dn, Ap
  175.      *
  176.      *    The second instruction can be either a word or long add.
  177.      *    Also, Dn must be dead after the third instruction.
  178.      */
  179.     if ((op1 == MOVE) && (i1->flags & LENL) &&
  180.         (i1->src.amode == REG) &&
  181.         ISA(i1->src.areg) &&
  182.         (i1->dst.amode == REG) &&
  183.         ISD(i1->dst.areg)) {
  184.  
  185.         if (((op2 == ADD) || (op2 == ADDQ)) &&
  186.             (i2->flags & (LENL|LENW)) &&
  187.             (i2->src.amode == REG) &&
  188.             ISD(i2->src.areg) && (i1->dst.areg != i2->src.areg) &&
  189.             (i2->dst.amode == REG) &&
  190.             (i2->dst.areg == i1->dst.areg)) {
  191.  
  192.             if ((op3 == MOVE) && (i3->flags & LENL) &&
  193.                 (i3->src.amode == REG) &&
  194.                 (i3->src.areg == i1->dst.areg) &&
  195.                 (i3->dst.amode == REG) &&
  196.                 ISA(i3->dst.areg) &&
  197.                 ((i3->live & RM(i3->src.areg)) == 0)) {
  198.  
  199.                 /*
  200.                  * rewrite i1 and delete i2 and i3
  201.                  */
  202.                 i1->opcode = LEA;
  203.                 i1->flags = 0;
  204.                 i1->dst = i3->dst;
  205.  
  206.                 i1->src.amode = REGIDX;
  207.                 if (i2->flags & LENL)
  208.                     i1->src.amode |= XLONG;
  209.                 i1->src.ireg = i2->src.areg;
  210.                 i1->src.disp = 0;
  211.  
  212.                     delinst(bp, i2);
  213.                     delinst(bp, i3);
  214.                     DBG(printf("%d ", __LINE__))
  215.                     return TRUE;
  216.             }
  217.         }
  218.     }
  219.  
  220.     /*
  221.      *    move.l    X(Am), Dn    =>    move.l    X(Am), Ao
  222.      *    add.l    #N, Dn
  223.      *    move.l    Dn, Ao            lea    N(Ao), Ao
  224.      *
  225.      *    Also, Dn must be dead after the third instruction.
  226.      */
  227.     if ((op1 == MOVE) && (i1->flags & LENL) &&
  228.         (i1->src.amode == REGI || i1->src.amode == REGID) &&
  229.         (i1->dst.amode == REG) &&
  230.         ISD(i1->dst.areg)) {
  231.  
  232.         if (((op2 == ADD) || (op2 == ADDQ)) &&
  233.             (i2->flags & LENL) &&
  234.             (i2->src.amode == IMM) &&
  235.             DOK(i2->src.disp) &&
  236.             (i2->dst.amode == REG) &&
  237.             (i2->dst.areg == i1->dst.areg)) {
  238.  
  239.             if ((op3 == MOVE) && (i3->flags & LENL) &&
  240.                 (i3->src.amode == REG) &&
  241.                 (i3->src.areg == i1->dst.areg) &&
  242.                 (i3->dst.amode == REG) &&
  243.                 ISA(i3->dst.areg) &&
  244.                 ((i3->live & RM(i3->src.areg)) == 0)) {
  245.  
  246.                 /*
  247.                  * rewrite i1 and i3 and delete i2
  248.                  */
  249.                 i1->dst = i3->dst;
  250.  
  251.                 i3->opcode = LEA;
  252.                 i3->flags = 0;
  253.                 i3->src.amode = REGID;
  254.                 i3->src.areg = i3->dst.areg;
  255.                 i3->src.disp = i2->src.disp;
  256.  
  257.                     delinst(bp, i2);
  258.                     DBG(printf("%d ", __LINE__))
  259.                     return TRUE;
  260.             }
  261.         }
  262.     }
  263.  
  264.     /*
  265.      *    move.x    X, Dn        =>    move.x    X, Do
  266.      *    ext.y    Dn            ext.y    Do
  267.      *    move.y    Dn, Do
  268.      *
  269.      *    Where Dn is dead.
  270.      */
  271.     if ((op1 == MOVE)&&(op2 == EXT)&&(op3 == MOVE)&&
  272.         (i1->dst.amode == REG) && ISD(i1->dst.areg) &&
  273.         (i2->src.amode == REG) && (i3->src.amode == REG) &&
  274.         (i3->dst.amode == REG) && ISD(i3->dst.areg) &&
  275.         (i1->dst.areg == i2->src.areg) && (i1->dst.areg == i3->src.areg) &&
  276.         (i2->flags == i3->flags)) {
  277.  
  278.         if ((i3->live & RM(i3->src.areg)) == 0) {
  279.             i1->dst.areg = i3->dst.areg;
  280.             i2->src.areg = i3->dst.areg;
  281.  
  282.                 delinst(bp, i3);
  283.                 DBG(printf("%d ", __LINE__))
  284.                 return TRUE;
  285.         }
  286.     }
  287.  
  288.     /*
  289.      *    move.l    X, Dm        =>    move.l    X, An
  290.      *    INST                INST
  291.      *    move.l    Dm, An            ...deleted...
  292.      *
  293.      *    where INST doesn't modify Dm, and Dm is dead after i3
  294.      */
  295.     if ((op1 == MOVE) && (op3 == MOVE) &&
  296.         (i1->dst.amode == REG) && ISD(i1->dst.areg) &&
  297.         (i3->src.amode == REG) && (i1->dst.areg == i3->src.areg) &&
  298.         (i3->dst.amode == REG) && ISA(i3->dst.areg) &&
  299.         !uses(i2, i3->src.areg)) {
  300.  
  301.         if ((i3->live & i3->src.areg) == 0) {
  302.             i1->dst.areg = i3->dst.areg;
  303.             delinst(bp, i3);
  304.  
  305.                 DBG(printf("%d ", __LINE__))
  306.             return TRUE;
  307.         }
  308.     }
  309.  
  310.     /*
  311.      *    move.l    Am, An            ...deleted...
  312.      *    addq.l    #1, Am            ...deleted...
  313.      *    ... stuff ...            ... stuff ...
  314.      *    ???.b    ..(An)..    =>    ???.b    ..(Am)+..
  315.      *
  316.      *    An must be dead after the last instruction. Nothing in
  317.      *    "stuff" can modify Am.
  318.      */
  319.     if ((op1 == MOVE) && (i1->flags & LENL) &&
  320.         (i1->src.amode == REG) && ISA(i1->src.areg) &&
  321.         (i1->dst.amode == REG) && ISA(i1->dst.areg)) {
  322.  
  323.         int    rm = i1->src.areg;
  324.         int    rn = i1->dst.areg;
  325.  
  326.         if (((op2 == ADD) || (op2 == ADDQ)) &&
  327.             (i2->flags & LENL) &&
  328.             (i2->src.amode == IMM) && (i2->src.disp == 1) &&
  329.             (i2->dst.amode == REG) &&
  330.             (i2->dst.areg == rm)) {
  331.  
  332.             while (i3 != NULL) {
  333.                 if (sets(i3, rm))
  334.                     goto end7;
  335.  
  336.                 if (i3->src.amode==REGI && i3->src.areg==rn) {
  337.                     if (i3->live & RM(rn))
  338.                         goto end7;
  339.  
  340.                     if ((i3->flags & LENB) == 0)
  341.                         goto end7;
  342.  
  343.                     i3->src.amode |= INC;
  344.                     i3->src.areg = rm;
  345.  
  346.                         delinst(bp, i1);
  347.                         delinst(bp, i2);
  348.                         DBG(printf("%d ", __LINE__))
  349.                         return TRUE;
  350.                 }
  351.                 if (i3->dst.amode==REGI && i3->dst.areg==rn) {
  352.                     if (i3->live & RM(rn))
  353.                         goto end7;
  354.  
  355.                     if ((i3->flags & LENB) == 0)
  356.                         goto end7;
  357.  
  358.                     i3->dst.amode |= INC;
  359.                     i3->dst.areg = rm;
  360.  
  361.                         delinst(bp, i1);
  362.                         delinst(bp, i2);
  363.                         DBG(printf("%d ", __LINE__))
  364.                         return TRUE;
  365.                 }
  366.  
  367.                 if (i3->next == NULL)
  368.                     goto end7;
  369.                 else
  370.                     i3 = i3->next;
  371.  
  372.             }
  373.         }
  374.     }
  375. end7:
  376.  
  377.     /*
  378.      *    move.l    Am, An
  379.      *    addq.l    #2, Am
  380.      *    ... stuff ...
  381.      *    ???.w    ..(An)..    =>    ???.w    ..(Am)+..
  382.      *
  383.      *    An must be dead after the last instruction. Nothing in
  384.      *    "stuff" can modify Am.
  385.      */
  386.     if ((op1 == MOVE) && (i1->flags & LENL) &&
  387.         (i1->src.amode == REG) && ISA(i1->src.areg) &&
  388.         (i1->dst.amode == REG) && ISA(i1->dst.areg)) {
  389.  
  390.         int    rm = i1->src.areg;
  391.         int    rn = i1->dst.areg;
  392.  
  393.         if (((op2 == ADD) || (op2 == ADDQ)) &&
  394.             (i2->flags & LENL) &&
  395.             (i2->src.amode == IMM) && (i2->src.disp == 2) &&
  396.             (i2->dst.amode == REG) &&
  397.             (i2->dst.areg == rm)) {
  398.  
  399.             while (i3 != NULL) {
  400.                 if (sets(i3, rm))
  401.                     goto end9;
  402.  
  403.                 if (i3->src.amode==REGI && i3->src.areg==rn) {
  404.                     if (i3->live & RM(rn))
  405.                         goto end9;
  406.  
  407.                     if ((i3->flags & LENW) == 0)
  408.                         goto end9;
  409.  
  410.                     i3->src.amode |= INC;
  411.                     i3->src.areg = rm;
  412.  
  413.                         delinst(bp, i1);
  414.                         delinst(bp, i2);
  415.                         DBG(printf("%d ", __LINE__))
  416.                         return TRUE;
  417.                 }
  418.                 if (i3->dst.amode==REGI && i3->dst.areg==rn) {
  419.                     if (i3->live & RM(rn))
  420.                         goto end9;
  421.  
  422.                     if ((i3->flags & LENW) == 0)
  423.                         goto end9;
  424.  
  425.                     i3->dst.amode |= INC;
  426.                     i3->dst.areg = rm;
  427.  
  428.                         delinst(bp, i1);
  429.                         delinst(bp, i2);
  430.                         DBG(printf("%d ", __LINE__))
  431.                         return TRUE;
  432.                 }
  433.  
  434.                 if (i3->next == NULL)
  435.                     goto end9;
  436.                 else
  437.                     i3 = i3->next;
  438.  
  439.             }
  440.         }
  441.     }
  442. end9:
  443.  
  444.     /*
  445.      *    move.l    Am, An
  446.      *    addq.l    #4, Am
  447.      *    ... stuff ...
  448.      *    ???.l    ..(An)..    =>    ???.l    ..(Am)+..
  449.      *
  450.      *    An must be dead after the last instruction. Nothing in
  451.      *    "stuff" can modify Am.
  452.      */
  453.     if ((op1 == MOVE) && (i1->flags & LENL) &&
  454.         (i1->src.amode == REG) && ISA(i1->src.areg) &&
  455.         (i1->dst.amode == REG) && ISA(i1->dst.areg)) {
  456.  
  457.         int    rm = i1->src.areg;
  458.         int    rn = i1->dst.areg;
  459.  
  460.         if (((op2 == ADD) || (op2 == ADDQ)) &&
  461.             (i2->flags & LENL) &&
  462.             (i2->src.amode == IMM) && (i2->src.disp == 4) &&
  463.             (i2->dst.amode == REG) &&
  464.             (i2->dst.areg == rm)) {
  465.  
  466.             while (i3 != NULL) {
  467.                 if (sets(i3, rm))
  468.                     goto end11;
  469.  
  470.                 if (i3->src.amode==REGI && i3->src.areg==rn) {
  471.                     if (i3->live & RM(rn))
  472.                         goto end11;
  473.  
  474.                     if ((i3->flags & LENL) == 0)
  475.                         goto end11;
  476.  
  477.                     i3->src.amode |= INC;
  478.                     i3->src.areg = rm;
  479.  
  480.                         delinst(bp, i1);
  481.                         delinst(bp, i2);
  482.                         DBG(printf("%d ", __LINE__))
  483.                         return TRUE;
  484.                 }
  485.                 if (i3->dst.amode==REGI && i3->dst.areg==rn) {
  486.                     if (i3->live & RM(rn))
  487.                         goto end11;
  488.  
  489.                     if ((i3->flags & LENL) == 0)
  490.                         goto end11;
  491.  
  492.                     i3->dst.amode |= INC;
  493.                     i3->dst.areg = rm;
  494.  
  495.                         delinst(bp, i1);
  496.                         delinst(bp, i2);
  497.                         DBG(printf("%d ", __LINE__))
  498.                         return TRUE;
  499.                 }
  500.  
  501.                 if (i3->next == NULL)
  502.                     goto end11;
  503.                 else
  504.                     i3 = i3->next;
  505.  
  506.             }
  507.         }
  508.     }
  509. end11:
  510.  
  511.     return FALSE;
  512. }
  513.  
  514. /*
  515.  * peep3(bp) - scan blocks starting at 'bp'
  516.  */
  517. bool
  518. peep3(bp)
  519. register BLOCK    *bp;
  520. {
  521.     register INST    *ip;
  522.     register bool    changed = FALSE;
  523.  
  524.     DBG(printf("p3: "))
  525.     for (; bp != NULL ;bp = bp->next) {
  526.         ip = bp->first;
  527.         while (ip!=NULL && ip->next != NULL && ip->next->next != NULL) {
  528.             if (ipeep3(bp, ip)) {
  529.                 s_peep3++;
  530.                 bprep(bp);
  531.                 changed = TRUE;
  532.                 /*
  533.                  * If we had a match, then any instruction
  534.                  * could have been deleted, so the safe thing
  535.                  * to do is to go to the next block.
  536.                  */
  537.                 break;
  538.             } else
  539.                 ip = ip->next;
  540.         }
  541.     }
  542.     DBG(printf("\n"); fflush(stdout))
  543.     return changed;
  544. }
  545.