re PR debug/66691 (ICE on valid code at -O3 with -g enabled in simplify_subreg, at...
[gcc.git] / gcc / rtlanal.c
index 513feeb577b77d804061157c800e95d262ef2603..86b3b622f89384afb3823b0215de9579da96d96b 100644 (file)
@@ -32,18 +32,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm_p.h"
 #include "flags.h"
 #include "regs.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "machmode.h"
-#include "input.h"
 #include "function.h"
 #include "predict.h"
 #include "basic-block.h"
 #include "df.h"
 #include "symtab.h"
-#include "wide-int.h"
-#include "inchash.h"
 #include "tree.h"
 #include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
 #include "addresses.h"
@@ -104,7 +97,10 @@ generic_subrtx_iterator <T>::add_single_to_queue (array_type &array,
          return base;
        }
       gcc_checking_assert (i == LOCAL_ELEMS);
-      vec_safe_grow (array.heap, i + 1);
+      /* A previous iteration might also have moved from the stack to the
+        heap, in which case the heap array will already be big enough.  */
+      if (vec_safe_length (array.heap) <= i)
+       vec_safe_grow (array.heap, i + 1);
       base = array.heap->address ();
       memcpy (base, array.stack, sizeof (array.stack));
       base[LOCAL_ELEMS] = x;
@@ -1197,7 +1193,7 @@ record_hard_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
 /* Examine INSN, and compute the set of hard registers written by it.
    Store it in *PSET.  Should only be called after reload.  */
 void
-find_all_hard_reg_sets (const_rtx insn, HARD_REG_SET *pset, bool implicit)
+find_all_hard_reg_sets (const rtx_insn *insn, HARD_REG_SET *pset, bool implicit)
 {
   rtx link;
 
@@ -1368,7 +1364,7 @@ set_noop_p (const_rtx set)
    value to itself.  */
 
 int
-noop_move_p (const_rtx insn)
+noop_move_p (const rtx_insn *insn)
 {
   rtx pat = PATTERN (insn);
 
@@ -1442,9 +1438,8 @@ refers_to_regno_p (unsigned int regno, unsigned int endregno, const_rtx x,
         clobber a virtual register.  In fact, we could be more precise,
         but it isn't worth it.  */
       if ((x_regno == STACK_POINTER_REGNUM
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-          || x_regno == ARG_POINTER_REGNUM
-#endif
+          || (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+              && x_regno == ARG_POINTER_REGNUM)
           || x_regno == FRAME_POINTER_REGNUM)
          && regno >= FIRST_VIRTUAL_REGISTER && regno <= LAST_VIRTUAL_REGISTER)
        return true;
@@ -2015,7 +2010,7 @@ find_reg_fusage (const_rtx insn, enum rtx_code code, const_rtx datum)
 
       if (regno < FIRST_PSEUDO_REGISTER)
        {
-         unsigned int end_regno = END_HARD_REGNO (datum);
+         unsigned int end_regno = END_REGNO (datum);
          unsigned int i;
 
          for (i = regno; i < end_regno; i++)
@@ -2049,7 +2044,7 @@ find_regno_fusage (const_rtx insn, enum rtx_code code, unsigned int regno)
       if (GET_CODE (op = XEXP (link, 0)) == code
          && REG_P (reg = XEXP (op, 0))
          && REGNO (reg) <= regno
-         && END_HARD_REGNO (reg) > regno)
+         && END_REGNO (reg) > regno)
        return 1;
     }
 
@@ -2117,7 +2112,7 @@ add_int_reg_note (rtx insn, enum reg_note kind, int datum)
 /* Add a register note like NOTE to INSN.  */
 
 void
-add_shallow_copy_of_reg_note (rtx insn, rtx note)
+add_shallow_copy_of_reg_note (rtx_insn *insn, rtx note)
 {
   if (GET_CODE (note) == INT_LIST)
     add_int_reg_note (insn, REG_NOTE_KIND (note), XINT (note, 0));
@@ -2159,7 +2154,7 @@ remove_note (rtx insn, const_rtx note)
 /* Remove REG_EQUAL and/or REG_EQUIV notes if INSN has such notes.  */
 
 void
-remove_reg_equal_equiv_notes (rtx insn)
+remove_reg_equal_equiv_notes (rtx_insn *insn)
 {
   rtx *loc;
 
@@ -2205,16 +2200,16 @@ remove_reg_equal_equiv_notes_for_regno (unsigned int regno)
    return 1 if it is found.  A simple equality test is used to determine if
    NODE matches.  */
 
-int
-in_expr_list_p (const_rtx listp, const_rtx node)
+bool
+in_insn_list_p (const rtx_insn_list *listp, const rtx_insn *node)
 {
   const_rtx x;
 
   for (x = listp; x; x = XEXP (x, 1))
     if (node == XEXP (x, 0))
-      return 1;
+      return true;
 
-  return 0;
+  return false;
 }
 
 /* Search LISTP (an EXPR_LIST) for an entry whose first operand is NODE and
@@ -2226,7 +2221,7 @@ void
 remove_node_from_expr_list (const_rtx node, rtx_expr_list **listp)
 {
   rtx_expr_list *temp = *listp;
-  rtx prev = NULL_RTX;
+  rtx_expr_list *prev = NULL;
 
   while (temp)
     {
@@ -2255,7 +2250,7 @@ void
 remove_node_from_insn_list (const rtx_insn *node, rtx_insn_list **listp)
 {
   rtx_insn_list *temp = *listp;
-  rtx prev = NULL;
+  rtx_insn_list *prev = NULL;
 
   while (temp)
     {
@@ -2914,7 +2909,8 @@ rtx_referenced_p (const_rtx x, const_rtx body)
 bool
 tablejump_p (const rtx_insn *insn, rtx *labelp, rtx_jump_table_data **tablep)
 {
-  rtx label, table;
+  rtx label;
+  rtx_insn *table;
 
   if (!JUMP_P (insn))
     return false;
@@ -2990,7 +2986,7 @@ computed_jump_p_1 (const_rtx x)
    we can recognize them by a (use (label_ref)).  */
 
 int
-computed_jump_p (const_rtx insn)
+computed_jump_p (const rtx_insn *insn)
 {
   int i;
   if (JUMP_P (insn))
@@ -3136,17 +3132,16 @@ regno_use_in (unsigned int regno, rtx x)
 }
 
 /* Return a value indicating whether OP, an operand of a commutative
-   operation, is preferred as the first or second operand.  The higher
-   the value, the stronger the preference for being the first operand.
-   We use negative values to indicate a preference for the first operand
-   and positive values for the second operand.  */
+   operation, is preferred as the first or second operand.  The more
+   positive the value, the stronger the preference for being the first
+   operand.  */
 
 int
 commutative_operand_precedence (rtx op)
 {
   enum rtx_code code = GET_CODE (op);
 
-  /* Constants always come the second operand.  Prefer "nice" constants.  */
+  /* Constants always become the second operand.  Prefer "nice" constants.  */
   if (code == CONST_INT)
     return -8;
   if (code == CONST_WIDE_INT)
@@ -3440,6 +3435,22 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
          info->offset = offset / regsize_xmode;
          return;
        }
+      /* Quick exit for the simple and common case of extracting whole
+        subregisters from a multiregister value.  */
+      /* ??? It would be better to integrate this into the code below,
+        if we can generalize the concept enough and figure out how
+        odd-sized modes can coexist with the other weird cases we support.  */
+      if (!rknown
+         && WORDS_BIG_ENDIAN == REG_WORDS_BIG_ENDIAN
+         && regsize_xmode == regsize_ymode
+         && (offset % regsize_ymode) == 0)
+       {
+         info->representable_p = true;
+         info->nregs = nregs_ymode;
+         info->offset = offset / regsize_ymode;
+         gcc_assert (info->offset + info->nregs <= nregs_xmode);
+         return;
+       }
     }
 
   /* Lowpart subregs are otherwise valid.  */
@@ -5019,7 +5030,6 @@ canonicalize_condition (rtx_insn *insn, rtx cond, int reverse,
       /* Set nonzero when we find something of interest.  */
       rtx x = 0;
 
-#ifdef HAVE_cc0
       /* If comparison with cc0, import actual comparison from compare
         insn.  */
       if (op0 == cc0_rtx)
@@ -5035,7 +5045,6 @@ canonicalize_condition (rtx_insn *insn, rtx cond, int reverse,
          if (earliest)
            *earliest = prev;
        }
-#endif
 
       /* If this is a COMPARE, pick up the two things being compared.  */
       if (GET_CODE (op0) == COMPARE)