home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / gcc-2.3.3-src.lha / GNU / src / amiga / gcc-2.3.3 / rtlanal.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  39KB  |  1,586 lines

  1. /* Analyze RTL for C-Compiler
  2.    Copyright (C) 1987, 1988, 1991, 1992 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU CC.
  5.  
  6. GNU CC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU CC is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU CC; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. #include "config.h"
  22. #include "rtl.h"
  23.  
  24. void note_stores ();
  25. int reg_set_p ();
  26.  
  27. /* Bit flags that specify the machine subtype we are compiling for.
  28.    Bits are tested using macros TARGET_... defined in the tm.h file
  29.    and set by `-m...' switches.  Must be defined in rtlanal.c.  */
  30.  
  31. int target_flags;
  32.  
  33. /* Return 1 if the value of X is unstable
  34.    (would be different at a different point in the program).
  35.    The frame pointer, arg pointer, etc. are considered stable
  36.    (within one function) and so is anything marked `unchanging'.  */
  37.  
  38. int
  39. rtx_unstable_p (x)
  40.      rtx x;
  41. {
  42.   register RTX_CODE code = GET_CODE (x);
  43.   register int i;
  44.   register char *fmt;
  45.  
  46.   if (code == MEM)
  47.     return ! RTX_UNCHANGING_P (x);
  48.  
  49.   if (code == QUEUED)
  50.     return 1;
  51.  
  52.   if (code == CONST || code == CONST_INT)
  53.     return 0;
  54.  
  55.   if (code == REG)
  56.     return ! (REGNO (x) == FRAME_POINTER_REGNUM
  57.           || REGNO (x) == ARG_POINTER_REGNUM
  58.           || RTX_UNCHANGING_P (x));
  59.  
  60.   fmt = GET_RTX_FORMAT (code);
  61.   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  62.     if (fmt[i] == 'e')
  63.       if (rtx_unstable_p (XEXP (x, i)))
  64.     return 1;
  65.   return 0;
  66. }
  67.  
  68. /* Return 1 if X has a value that can vary even between two
  69.    executions of the program.  0 means X can be compared reliably
  70.    against certain constants or near-constants.
  71.    The frame pointer and the arg pointer are considered constant.  */
  72.  
  73. int
  74. rtx_varies_p (x)
  75.      rtx x;
  76. {
  77.   register RTX_CODE code = GET_CODE (x);
  78.   register int i;
  79.   register char *fmt;
  80.  
  81.   switch (code)
  82.     {
  83.     case MEM:
  84.     case QUEUED:
  85.       return 1;
  86.  
  87.     case CONST:
  88.     case CONST_INT:
  89.     case CONST_DOUBLE:
  90.     case SYMBOL_REF:
  91.     case LABEL_REF:
  92.       return 0;
  93.  
  94.     case REG:
  95.       /* Note that we have to test for the actual rtx used for the frame
  96.      and arg pointers and not just the register number in case we have
  97.      eliminated the frame and/or arg pointer and are using it
  98.      for pseudos.  */
  99.       return ! (x == frame_pointer_rtx || x == arg_pointer_rtx);
  100.  
  101.     case LO_SUM:
  102.       /* The operand 0 of a LO_SUM is considered constant
  103.      (in fact is it related specifically to operand 1).  */
  104.       return rtx_varies_p (XEXP (x, 1));
  105.     }
  106.  
  107.   fmt = GET_RTX_FORMAT (code);
  108.   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  109.     if (fmt[i] == 'e')
  110.       if (rtx_varies_p (XEXP (x, i)))
  111.     return 1;
  112.   return 0;
  113. }
  114.  
  115. /* Return 0 if the use of X as an address in a MEM can cause a trap.  */
  116.  
  117. int
  118. rtx_addr_can_trap_p (x)
  119.      register rtx x;
  120. {
  121.   register enum rtx_code code = GET_CODE (x);
  122.  
  123.   switch (code)
  124.     {
  125.     case SYMBOL_REF:
  126.     case LABEL_REF:
  127.       /* SYMBOL_REF is problematic due to the possible presence of
  128.      a #pragma weak, but to say that loads from symbols can trap is
  129.      *very* costly.  It's not at all clear what's best here.  For
  130.      now, we ignore the impact of #pragma weak.  */
  131.       return 0;
  132.  
  133.     case REG:
  134.       /* As in rtx_varies_p, we have to use the actual rtx, not reg number.  */
  135.       return ! (x == frame_pointer_rtx || x == stack_pointer_rtx
  136.         || x == arg_pointer_rtx);
  137.  
  138.     case CONST:
  139.       return rtx_addr_can_trap_p (XEXP (x, 0));
  140.  
  141.     case PLUS:
  142.       /* An address is assumed not to trap if it is an address that can't
  143.      trap plus a constant integer.  */
  144.       return (rtx_addr_can_trap_p (XEXP (x, 0))
  145.           || GET_CODE (XEXP (x, 1)) != CONST_INT);
  146.  
  147.     case LO_SUM:
  148.       return rtx_addr_can_trap_p (XEXP (x, 1));
  149.     }
  150.  
  151.   /* If it isn't one of the case above, it can cause a trap.  */
  152.   return 1;
  153. }
  154.  
  155. /* Return 1 if X refers to a memory location whose address 
  156.    cannot be compared reliably with constant addresses,
  157.    or if X refers to a BLKmode memory object.  */
  158.  
  159. int
  160. rtx_addr_varies_p (x)
  161.      rtx x;
  162. {
  163.   register enum rtx_code code;
  164.   register int i;
  165.   register char *fmt;
  166.  
  167.   if (x == 0)
  168.     return 0;
  169.  
  170.   code = GET_CODE (x);
  171.   if (code == MEM)
  172.     return GET_MODE (x) == BLKmode || rtx_varies_p (XEXP (x, 0));
  173.  
  174.   fmt = GET_RTX_FORMAT (code);
  175.   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  176.     if (fmt[i] == 'e')
  177.       if (rtx_addr_varies_p (XEXP (x, i)))
  178.     return 1;
  179.   return 0;
  180. }
  181.  
  182. /* Return the value of the integer term in X, if one is apparent;
  183.    otherwise return 0.
  184.    Only obvious integer terms are detected.
  185.    This is used in cse.c with the `related_value' field.*/
  186.  
  187. HOST_WIDE_INT
  188. get_integer_term (x)
  189.      rtx x;
  190. {
  191.   if (GET_CODE (x) == CONST)
  192.     x = XEXP (x, 0);
  193.  
  194.   if (GET_CODE (x) == MINUS
  195.       && GET_CODE (XEXP (x, 1)) == CONST_INT)
  196.     return - INTVAL (XEXP (x, 1));
  197.   if (GET_CODE (x) == PLUS
  198.       && GET_CODE (XEXP (x, 1)) == CONST_INT)
  199.     return INTVAL (XEXP (x, 1));
  200.   return 0;
  201. }
  202.  
  203. /* If X is a constant, return the value sans apparent integer term;
  204.    otherwise return 0.
  205.    Only obvious integer terms are detected.  */
  206.  
  207. rtx
  208. get_related_value (x)
  209.      rtx x;
  210. {
  211.   if (GET_CODE (x) != CONST)
  212.     return 0;
  213.   x = XEXP (x, 0);
  214.   if (GET_CODE (x) == PLUS
  215.       && GET_CODE (XEXP (x, 1)) == CONST_INT)
  216.     return XEXP (x, 0);
  217.   else if (GET_CODE (x) == MINUS
  218.        && GET_CODE (XEXP (x, 1)) == CONST_INT)
  219.     return XEXP (x, 0);
  220.   return 0;
  221. }
  222.  
  223. /* Nonzero if register REG appears somewhere within IN.
  224.    Also works if REG is not a register; in this case it checks
  225.    for a subexpression of IN that is Lisp "equal" to REG.  */
  226.  
  227. int
  228. reg_mentioned_p (reg, in)
  229.      register rtx reg, in;
  230. {
  231.   register char *fmt;
  232.   register int i;
  233.   register enum rtx_code code;
  234.  
  235.   if (in == 0)
  236.     return 0;
  237.  
  238.   if (reg == in)
  239.     return 1;
  240.  
  241.   if (GET_CODE (in) == LABEL_REF)
  242.     return reg == XEXP (in, 0);
  243.  
  244.   code = GET_CODE (in);
  245.  
  246.   switch (code)
  247.     {
  248.       /* Compare registers by number.  */
  249.     case REG:
  250.       return GET_CODE (reg) == REG && REGNO (in) == REGNO (reg);
  251.  
  252.       /* These codes have no constituent expressions
  253.      and are unique.  */
  254.     case SCRATCH:
  255.     case CC0:
  256.     case PC:
  257.       return 0;
  258.  
  259.     case CONST_INT:
  260.       return GET_CODE (reg) == CONST_INT && INTVAL (in) == INTVAL (reg);
  261.       
  262.     case CONST_DOUBLE:
  263.       /* These are kept unique for a given value.  */
  264.       return 0;
  265.     }
  266.  
  267.   if (GET_CODE (reg) == code && rtx_equal_p (reg, in))
  268.     return 1;
  269.  
  270.   fmt = GET_RTX_FORMAT (code);
  271.  
  272.   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  273.     {
  274.       if (fmt[i] == 'E')
  275.     {
  276.       register int j;
  277.       for (j = XVECLEN (in, i) - 1; j >= 0; j--)
  278.         if (reg_mentioned_p (reg, XVECEXP (in, i, j)))
  279.           return 1;
  280.     }
  281.       else if (fmt[i] == 'e'
  282.            && reg_mentioned_p (reg, XEXP (in, i)))
  283.     return 1;
  284.     }
  285.   return 0;
  286. }
  287.  
  288. /* Return 1 if in between BEG and END, exclusive of BEG and END, there is
  289.    no CODE_LABEL insn.  */
  290.  
  291. int
  292. no_labels_between_p (beg, end)
  293.      rtx beg, end;
  294. {
  295.   register rtx p;
  296.   for (p = NEXT_INSN (beg); p != end; p = NEXT_INSN (p))
  297.     if (GET_CODE (p) == CODE_LABEL)
  298.       return 0;
  299.   return 1;
  300. }
  301.  
  302. /* Nonzero if register REG is used in an insn between
  303.    FROM_INSN and TO_INSN (exclusive of those two).  */
  304.  
  305. int
  306. reg_used_between_p (reg, from_insn, to_insn)
  307.      rtx reg, from_insn, to_insn;
  308. {
  309.   register rtx insn;
  310.  
  311.   if (from_insn == to_insn)
  312.     return 0;
  313.  
  314.   for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN (insn))
  315.     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
  316.     && reg_overlap_mentioned_p (reg, PATTERN (insn)))
  317.       return 1;
  318.   return 0;
  319. }
  320.  
  321. /* Nonzero if the old value of X, a register, is referenced in BODY.  If X
  322.    is entirely replaced by a new value and the only use is as a SET_DEST,
  323.    we do not consider it a reference.  */
  324.  
  325. int
  326. reg_referenced_p (x, body)
  327.      rtx x;
  328.      rtx body;