home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / sozobon / scsrc20 / top / peep1.c < prev    next >
C/C++ Source or Header  |  1991-02-22  |  5KB  |  243 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.  * Single-instruction peephole optimizations and the overall driver routine.
  14.  */
  15.  
  16. #include "top.h"
  17.  
  18.  
  19. void
  20. peep(bp)
  21. register BLOCK    *bp;
  22. {
  23.     bool    peep1(), peep2(), peep3();
  24.     extern    BLOCK    *fhead;
  25.     register bool    changed;
  26.  
  27.     peep1(bp);
  28.  
  29.     /*
  30.      * Loop until no more changes are made. After each change, do
  31.      * live/dead analysis or the data gets old. In each loop, make
  32.      * at most one change.
  33.      */
  34.     do {
  35.         changed = peep3(bp);
  36.  
  37.         if (!changed)
  38.             changed = peep2(bp);
  39.  
  40.         if (!changed)
  41.             changed = peep1(bp);
  42.  
  43.         rhealth(fhead, FALSE);
  44.  
  45.     } while (changed);
  46. }
  47.  
  48. /*
  49.  * ipeep1(ip) - check for changes to the instruction 'ip'
  50.  */
  51. static    bool
  52. ipeep1(bp, ip)
  53. register BLOCK    *bp;
  54. register INST    *ip;
  55. {
  56.     /*
  57.      * clr.l  Dn            => moveq.l  Dn
  58.      */
  59.     if (ip->opcode == CLR && ip->src.amode == REG &&
  60.         ISD(ip->src.areg) && (ip->flags & LENL)) {
  61.         ip->opcode = MOVEQ;
  62.         ip->dst = ip->src;    /* we'll have two operands now */
  63.         ip->src.amode = IMM;
  64.         ip->src.disp = 0;
  65.         DBG(printf("%d ", __LINE__))
  66.         return TRUE;
  67.     }
  68.  
  69.     /*
  70.      * move.*  #n,Dn        => moveq.l  #n,Dn
  71.      *
  72.      * moveq is always a long operation, but as long as the immediate
  73.      * value is appropriate, we don't care what the original length
  74.      * was. Clearing upper bytes won't matter.
  75.      */
  76.     if (ip->opcode == MOVE && ip->src.amode == IMM && ISD(ip->dst.areg) &&
  77.         D8OK(ip->src.disp)) {
  78.             ip->opcode = MOVEQ;
  79.             ip->flags = LENL;
  80.         DBG(printf("%d ", __LINE__))
  81.             return TRUE;
  82.     }
  83.  
  84.     /*
  85.      * add.x  #n, X         => addq.x  #n, X
  86.      *
  87.      * where 1 <= n <= 8
  88.      */
  89.     if (ip->opcode == ADD && ip->src.amode == IMM &&
  90.         ip->src.disp >= 1 && ip->src.disp <= 8) {
  91.             ip->opcode = ADDQ;
  92.         DBG(printf("%d ", __LINE__))
  93.             return TRUE;
  94.     }
  95.  
  96.     /*
  97.      * sub.x  #n, X         => subq.x  #n, X
  98.      *
  99.      * where 1 <= n <= 8
  100.      */
  101.     if (ip->opcode == SUB && ip->src.amode == IMM &&
  102.         ip->src.disp >= 1 && ip->src.disp <= 8) {
  103.             ip->opcode = SUBQ;
  104.         DBG(printf("%d ", __LINE__))
  105.             return TRUE;
  106.     }
  107.  
  108.     /*
  109.      * movem.x  Reg,-(sp)        => move.x Reg,-(sp)
  110.      */
  111.     if (ip->opcode == MOVEM && ip->src.amode == REG &&
  112.         ip->dst.areg == SP && ip->dst.amode == (REGI|DEC)) {
  113.             ip->opcode = MOVE;
  114.         DBG(printf("%d ", __LINE__))
  115.             return TRUE;
  116.     }
  117.  
  118.     /*
  119.      * movem.x  (sp)+,Reg        => move.x (sp)+,Reg
  120.      */
  121.     if (ip->opcode == MOVEM && ip->dst.amode == REG &&
  122.         ip->src.amode == (REGI|INC) && ip->src.areg == SP) {
  123.             ip->opcode = MOVE;
  124.         DBG(printf("%d ", __LINE__))
  125.             return TRUE;
  126.     }
  127.  
  128.     /*
  129.      *    add[q]    #?, Rn
  130.      *
  131.      * Remove instruction if Rn is dead. This is most often used
  132.      * to eliminate the fixup of SP following a function call when
  133.      * we're just about to return, since the "unlk" clobbers SP
  134.      * anyway.
  135.      */
  136.     if ((ip->opcode == ADDQ || ip->opcode == ADD) && ip->src.amode == IMM &&
  137.          ip->dst.amode == REG) {
  138.  
  139.         if (gflag && (ip->dst.areg == SP))
  140.             goto end1;
  141.  
  142.         if ((ip->live & RM(ip->dst.areg)) == 0) {
  143.                  delinst(bp, ip);
  144.             DBG(printf("%d ", __LINE__))
  145.                  return TRUE;
  146.         }
  147.     }
  148. end1:
  149.  
  150.     /*
  151.      *    move.x    X, X
  152.      *
  153.      *    Delete as long as X isn't INC or DEC
  154.      */
  155.     if ((ip->opcode == MOVE) && opeq(&ip->src, &ip->dst) &&
  156.         ((ip->src.amode & (INC|DEC)) == 0)) {
  157.  
  158.         delinst(bp, ip);
  159.         DBG(printf("%d ", __LINE__))
  160.         return TRUE;
  161.     }
  162.  
  163.     /*
  164.      *    move.x    Rm, Rn
  165.      *
  166.      *    Delete if Rn is dead.
  167.      */
  168.     if (ip->opcode == MOVE &&
  169.          ip->src.amode == REG && ip->dst.amode == REG) {
  170.  
  171.         if ((ip->live & RM(ip->dst.areg)) == 0) {
  172.                  delinst(bp, ip);
  173.             DBG(printf("%d ", __LINE__))
  174.                  return TRUE;
  175.         }
  176.     }
  177.  
  178.  
  179.     /*
  180.      *    cmp.x    #0, X        =>    tst.x    X
  181.      *    beq/bne                beq/bne
  182.      *
  183.      *    Where X is not An
  184.      */
  185.     if (bp->last == ip && (bp->bcode == BEQ || bp->bcode == BNE) &&
  186.         ip->opcode == CMP &&
  187.         ((ip->dst.amode != REG) || !ISA(ip->dst.areg))) {
  188.  
  189.         if (ip->src.amode == IMM && ip->src.disp == 0) {
  190.             ip->opcode = TST;
  191.             ip->src = ip->dst;
  192.             ip->dst.amode = NONE;
  193.             DBG(printf("%d ", __LINE__))
  194.             return TRUE;
  195.         }
  196.     }
  197.  
  198.     /*
  199.      * add.x  #n, Am         => lea  n(Am), Am
  200.      *
  201.      * where 'n' is a valid displacement
  202.      */
  203.     if (ip->opcode == ADD && ip->src.amode == IMM && ip->dst.amode == REG &&
  204.         ISA(ip->dst.areg) && DOK(ip->src.disp)) {
  205.             ip->opcode = LEA;
  206.             ip->flags = 0;
  207.             ip->src.amode = REGID;
  208.             ip->src.areg = ip->dst.areg;
  209.         DBG(printf("%d ", __LINE__))
  210.             return TRUE;
  211.     }
  212.  
  213.     return FALSE;
  214. }
  215.  
  216. /*
  217.  * peep1(bp) - peephole optimizations with a window size of 1
  218.  */
  219. static    bool
  220. peep1(bp)
  221. register BLOCK    *bp;
  222. {
  223.     register INST    *ip;
  224.     register bool    changed = FALSE;
  225.     register bool    bchange;
  226.  
  227.     DBG(printf("p1: "))
  228.     for (; bp != NULL ;bp = bp->next) {
  229.         bchange = FALSE;
  230.         for (ip = bp->first; ip != NULL ;ip = ip->next) {
  231.             if (ipeep1(bp, ip)) {
  232.                 s_peep1++;
  233.                 changed = TRUE;
  234.                 bchange = TRUE;
  235.             }
  236.         }
  237.         if (bchange)
  238.             bprep(bp);
  239.     }
  240.     DBG(printf("\n"); fflush(stdout))
  241.     return changed;
  242. }
  243.