re PR debug/66691 (ICE on valid code at -O3 with -g enabled in simplify_subreg, at...
[gcc.git] / gcc / rtlanal.c
index e95be62bc8118923b76c4a3f2cdf473e5ed4b8c2..86b3b622f89384afb3823b0215de9579da96d96b 100644 (file)
@@ -1,5 +1,5 @@
 /* Analyze RTL for GNU compiler.
-   Copyright (C) 1987-2014 Free Software Foundation, Inc.
+   Copyright (C) 1987-2015 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -33,7 +33,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "regs.h"
 #include "function.h"
+#include "predict.h"
+#include "basic-block.h"
 #include "df.h"
+#include "symtab.h"
 #include "tree.h"
 #include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
 #include "addresses.h"
@@ -46,21 +49,17 @@ static bool covers_regno_no_parallel_p (const_rtx, unsigned int);
 static int computed_jump_p_1 (const_rtx);
 static void parms_set (rtx, const_rtx, void *);
 
-static unsigned HOST_WIDE_INT cached_nonzero_bits (const_rtx, enum machine_mode,
-                                                   const_rtx, enum machine_mode,
+static unsigned HOST_WIDE_INT cached_nonzero_bits (const_rtx, machine_mode,
+                                                   const_rtx, machine_mode,
                                                    unsigned HOST_WIDE_INT);
-static unsigned HOST_WIDE_INT nonzero_bits1 (const_rtx, enum machine_mode,
-                                            const_rtx, enum machine_mode,
+static unsigned HOST_WIDE_INT nonzero_bits1 (const_rtx, machine_mode,
+                                            const_rtx, machine_mode,
                                              unsigned HOST_WIDE_INT);
-static unsigned int cached_num_sign_bit_copies (const_rtx, enum machine_mode, const_rtx,
-                                                enum machine_mode,
+static unsigned int cached_num_sign_bit_copies (const_rtx, machine_mode, const_rtx,
+                                                machine_mode,
                                                 unsigned int);
-static unsigned int num_sign_bit_copies1 (const_rtx, enum machine_mode, const_rtx,
-                                          enum machine_mode, unsigned int);
-
-/* Offset of the first 'e', 'E' or 'V' operand for each rtx code, or
-   -1 if a code has no such operand.  */
-static int non_rtx_starting_operands[NUM_RTX_CODE];
+static unsigned int num_sign_bit_copies1 (const_rtx, machine_mode, const_rtx,
+                                          machine_mode, unsigned int);
 
 rtx_subrtx_bound_info rtx_all_subrtx_bounds[NUM_RTX_CODE];
 rtx_subrtx_bound_info rtx_nonconst_subrtx_bounds[NUM_RTX_CODE];
@@ -98,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;
@@ -128,29 +130,58 @@ generic_subrtx_iterator <T>::add_subrtxes_to_queue (array_type &array,
                                                    value_type *base,
                                                    size_t end, rtx_type x)
 {
-  const char *format = GET_RTX_FORMAT (GET_CODE (x));
+  enum rtx_code code = GET_CODE (x);
+  const char *format = GET_RTX_FORMAT (code);
   size_t orig_end = end;
-  for (int i = 0; format[i]; ++i)
-    if (format[i] == 'e')
-      {
-       value_type subx = T::get_value (x->u.fld[i].rt_rtx);
-       if (__builtin_expect (end < LOCAL_ELEMS, true))
-         base[end++] = subx;
-       else
-         base = add_single_to_queue (array, base, end++, subx);
-      }
-    else if (format[i] == 'E')
-      {
-       int length = GET_NUM_ELEM (x->u.fld[i].rt_rtvec);
-       rtx *vec = x->u.fld[i].rt_rtvec->elem;
-       if (__builtin_expect (end + length <= LOCAL_ELEMS, true))
-         for (int j = 0; j < length; j++)
-           base[end++] = T::get_value (vec[j]);
-       else
-         for (int j = 0; j < length; j++)
-           base = add_single_to_queue (array, base, end++,
-                                       T::get_value (vec[j]));
-      }
+  if (__builtin_expect (INSN_P (x), false))
+    {
+      /* Put the pattern at the top of the queue, since that's what
+        we're likely to want most.  It also allows for the SEQUENCE
+        code below.  */
+      for (int i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; --i)
+       if (format[i] == 'e')
+         {
+           value_type subx = T::get_value (x->u.fld[i].rt_rtx);
+           if (__builtin_expect (end < LOCAL_ELEMS, true))
+             base[end++] = subx;
+           else
+             base = add_single_to_queue (array, base, end++, subx);
+         }
+    }
+  else
+    for (int i = 0; format[i]; ++i)
+      if (format[i] == 'e')
+       {
+         value_type subx = T::get_value (x->u.fld[i].rt_rtx);
+         if (__builtin_expect (end < LOCAL_ELEMS, true))
+           base[end++] = subx;
+         else
+           base = add_single_to_queue (array, base, end++, subx);
+       }
+      else if (format[i] == 'E')
+       {
+         unsigned int length = GET_NUM_ELEM (x->u.fld[i].rt_rtvec);
+         rtx *vec = x->u.fld[i].rt_rtvec->elem;
+         if (__builtin_expect (end + length <= LOCAL_ELEMS, true))
+           for (unsigned int j = 0; j < length; j++)
+             base[end++] = T::get_value (vec[j]);
+         else
+           for (unsigned int j = 0; j < length; j++)
+             base = add_single_to_queue (array, base, end++,
+                                         T::get_value (vec[j]));
+         if (code == SEQUENCE && end == length)
+           /* If the subrtxes of the sequence fill the entire array then
+              we know that no other parts of a containing insn are queued.
+              The caller is therefore iterating over the sequence as a
+              PATTERN (...), so we also want the patterns of the
+              subinstructions.  */
+           for (unsigned int j = 0; j < length; j++)
+             {
+               typename T::rtx_type x = T::get_rtx (base[j]);
+               if (INSN_P (x))
+                 base[j] = T::get_value (PATTERN (x));
+             }
+       }
   return end - orig_end;
 }
 
@@ -321,7 +352,7 @@ rtx_varies_p (const_rtx x, bool for_alias)
 
 static int
 rtx_addr_can_trap_p_1 (const_rtx x, HOST_WIDE_INT offset, HOST_WIDE_INT size,
-                      enum machine_mode mode, bool unaligned_mems)
+                      machine_mode mode, bool unaligned_mems)
 {
   enum rtx_code code = GET_CODE (x);
 
@@ -785,7 +816,7 @@ reg_mentioned_p (const_rtx reg, const_rtx in)
     return 1;
 
   if (GET_CODE (in) == LABEL_REF)
-    return reg == XEXP (in, 0);
+    return reg == LABEL_REF_LABEL (in);
 
   code = GET_CODE (in);
 
@@ -835,9 +866,9 @@ reg_mentioned_p (const_rtx reg, const_rtx in)
    no CODE_LABEL insn.  */
 
 int
-no_labels_between_p (const_rtx beg, const_rtx end)
+no_labels_between_p (const rtx_insn *beg, const rtx_insn *end)
 {
-  rtx p;
+  rtx_insn *p;
   if (beg == end)
     return 0;
   for (p = NEXT_INSN (beg); p != end; p = NEXT_INSN (p))
@@ -850,7 +881,8 @@ no_labels_between_p (const_rtx beg, const_rtx end)
    FROM_INSN and TO_INSN (exclusive of those two).  */
 
 int
-reg_used_between_p (const_rtx reg, const_rtx from_insn, const_rtx to_insn)
+reg_used_between_p (const_rtx reg, const rtx_insn *from_insn,
+                   const rtx_insn *to_insn)
 {
   rtx_insn *insn;
 
@@ -946,7 +978,8 @@ reg_referenced_p (const_rtx x, const_rtx body)
    FROM_INSN and TO_INSN (exclusive of those two).  */
 
 int
-reg_set_between_p (const_rtx reg, const_rtx from_insn, const_rtx to_insn)
+reg_set_between_p (const_rtx reg, const rtx_insn *from_insn,
+                  const rtx_insn *to_insn)
 {
   const rtx_insn *insn;
 
@@ -963,6 +996,17 @@ reg_set_between_p (const_rtx reg, const_rtx from_insn, const_rtx to_insn)
 int
 reg_set_p (const_rtx reg, const_rtx insn)
 {
+  /* After delay slot handling, call and branch insns might be in a
+     sequence.  Check all the elements there.  */
+  if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
+    {
+      for (int i = 0; i < XVECLEN (PATTERN (insn), 0); ++i)
+       if (reg_set_p (reg, XVECEXP (PATTERN (insn), 0, i)))
+         return true;
+
+      return false;
+    }
+
   /* We can be passed an insn or part of one.  If we are passed an insn,
      check if a side-effect of the insn clobbers REG.  */
   if (INSN_P (insn)
@@ -974,7 +1018,7 @@ reg_set_p (const_rtx reg, const_rtx insn)
                                               GET_MODE (reg), REGNO (reg)))
                  || MEM_P (reg)
                  || find_reg_fusage (insn, CLOBBER, reg)))))
-    return 1;
+    return true;
 
   return set_of (reg, insn) != NULL_RTX;
 }
@@ -984,7 +1028,7 @@ reg_set_p (const_rtx reg, const_rtx insn)
    X contains a MEM; this routine does use memory aliasing.  */
 
 int
-modified_between_p (const_rtx x, const_rtx start, const_rtx end)
+modified_between_p (const_rtx x, const rtx_insn *start, const rtx_insn *end)
 {
   const enum rtx_code code = GET_CODE (x);
   const char *fmt;
@@ -1149,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;
 
@@ -1180,7 +1224,7 @@ record_hard_reg_uses (rtx *px, void *data)
    will not be used, which we ignore.  */
 
 rtx
-single_set_2 (const_rtx insn, const_rtx pat)
+single_set_2 (const rtx_insn *insn, const_rtx pat)
 {
   rtx set = NULL;
   int set_verified = 1;
@@ -1320,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);
 
@@ -1368,7 +1412,7 @@ noop_move_p (const_rtx insn)
    References contained within the substructure at LOC do not count.
    LOC may be zero, meaning don't ignore anything.  */
 
-int
+bool
 refers_to_regno_p (unsigned int regno, unsigned int endregno, const_rtx x,
                   rtx *loc)
 {
@@ -1381,7 +1425,7 @@ refers_to_regno_p (unsigned int regno, unsigned int endregno, const_rtx x,
   /* The contents of a REG_NONNEG note is always zero, so we must come here
      upon repeat in case the last REG_NOTE is a REG_NONNEG note.  */
   if (x == 0)
-    return 0;
+    return false;
 
   code = GET_CODE (x);
 
@@ -1394,12 +1438,11 @@ 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 1;
+       return true;
 
       return endregno > x_regno && regno < END_REGNO (x);
 
@@ -1432,10 +1475,10 @@ refers_to_regno_p (unsigned int regno, unsigned int endregno, const_rtx x,
                                     SUBREG_REG (SET_DEST (x)), loc))
              || (!REG_P (SET_DEST (x))
                  && refers_to_regno_p (regno, endregno, SET_DEST (x), loc))))
-       return 1;
+       return true;
 
       if (code == CLOBBER || loc == &SET_SRC (x))
-       return 0;
+       return false;
       x = SET_SRC (x);
       goto repeat;
 
@@ -1457,7 +1500,7 @@ refers_to_regno_p (unsigned int regno, unsigned int endregno, const_rtx x,
            }
          else
            if (refers_to_regno_p (regno, endregno, XEXP (x, i), loc))
-             return 1;
+             return true;
        }
       else if (fmt[i] == 'E')
        {
@@ -1465,10 +1508,10 @@ refers_to_regno_p (unsigned int regno, unsigned int endregno, const_rtx x,
          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
            if (loc != &XVECEXP (x, i, j)
                && refers_to_regno_p (regno, endregno, XVECEXP (x, i, j), loc))
-             return 1;
+             return true;
        }
     }
-  return 0;
+  return false;
 }
 
 /* Nonzero if modifying X will affect IN.  If X is a register or a SUBREG,
@@ -1915,7 +1958,7 @@ find_reg_equal_equiv_note (const_rtx insn)
    return null.  */
 
 rtx
-find_constant_src (const_rtx insn)
+find_constant_src (const rtx_insn *insn)
 {
   rtx note, set, x;
 
@@ -1967,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++)
@@ -2001,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;
     }
 
@@ -2062,14 +2105,14 @@ void
 add_int_reg_note (rtx insn, enum reg_note kind, int datum)
 {
   gcc_checking_assert (int_reg_note_p (kind));
-  REG_NOTES (insn) = gen_rtx_INT_LIST ((enum machine_mode) kind,
+  REG_NOTES (insn) = gen_rtx_INT_LIST ((machine_mode) kind,
                                       datum, REG_NOTES (insn));
 }
 
 /* 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));
@@ -2111,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;
 
@@ -2157,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
@@ -2178,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)
     {
@@ -2207,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)
     {
@@ -2492,7 +2535,7 @@ may_trap_p_1 (const_rtx x, unsigned flags)
     case MOD:
     case UDIV:
     case UMOD:
-      if (HONOR_SNANS (GET_MODE (x)))
+      if (HONOR_SNANS (x))
        return 1;
       if (SCALAR_FLOAT_MODE_P (GET_MODE (x)))
        return flag_trapping_math;
@@ -2518,28 +2561,28 @@ may_trap_p_1 (const_rtx x, unsigned flags)
         when COMPARE is used, though many targets do make this distinction.
         For instance, sparc uses CCFPE for compares which generate exceptions
         and CCFP for compares which do not generate exceptions.  */
-      if (HONOR_NANS (GET_MODE (x)))
+      if (HONOR_NANS (x))
        return 1;
       /* But often the compare has some CC mode, so check operand
         modes as well.  */
-      if (HONOR_NANS (GET_MODE (XEXP (x, 0)))
-         || HONOR_NANS (GET_MODE (XEXP (x, 1))))
+      if (HONOR_NANS (XEXP (x, 0))
+         || HONOR_NANS (XEXP (x, 1)))
        return 1;
       break;
 
     case EQ:
     case NE:
-      if (HONOR_SNANS (GET_MODE (x)))
+      if (HONOR_SNANS (x))
        return 1;
       /* Often comparison is CC mode, so check operand modes.  */
-      if (HONOR_SNANS (GET_MODE (XEXP (x, 0)))
-         || HONOR_SNANS (GET_MODE (XEXP (x, 1))))
+      if (HONOR_SNANS (XEXP (x, 0))
+         || HONOR_SNANS (XEXP (x, 1)))
        return 1;
       break;
 
     case FIX:
       /* Conversion of floating point might trap.  */
-      if (flag_trapping_math && HONOR_NANS (GET_MODE (XEXP (x, 0))))
+      if (flag_trapping_math && HONOR_NANS (XEXP (x, 0)))
        return 1;
       break;
 
@@ -2844,7 +2887,9 @@ rtx_referenced_p (const_rtx x, const_rtx body)
     if (const_rtx y = *iter)
       {
        /* Check if a label_ref Y refers to label X.  */
-       if (GET_CODE (y) == LABEL_REF && LABEL_P (y) && XEXP (y, 0) == x)
+       if (GET_CODE (y) == LABEL_REF
+           && LABEL_P (x)
+           && LABEL_REF_LABEL (y) == x)
          return true;
 
        if (rtx_equal_p (x, y))
@@ -2862,16 +2907,17 @@ rtx_referenced_p (const_rtx x, const_rtx body)
    *LABELP and the jump table to *TABLEP.  LABELP and TABLEP may be NULL.  */
 
 bool
-tablejump_p (const_rtx insn, rtx *labelp, rtx_jump_table_data **tablep)
+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;
 
   label = JUMP_LABEL (insn);
   if (label != NULL_RTX && !ANY_RETURN_P (label)
-      && (table = NEXT_INSN (label)) != NULL_RTX
+      && (table = NEXT_INSN (as_a <rtx_insn *> (label))) != NULL_RTX
       && JUMP_TABLE_DATA_P (table))
     {
       if (labelp)
@@ -2940,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))
@@ -2980,137 +3026,6 @@ computed_jump_p (const_rtx insn)
   return 0;
 }
 
-/* Optimized loop of for_each_rtx, trying to avoid useless recursive
-   calls.  Processes the subexpressions of EXP and passes them to F.  */
-static int
-for_each_rtx_1 (rtx exp, int n, rtx_function f, void *data)
-{
-  int result, i, j;
-  const char *format = GET_RTX_FORMAT (GET_CODE (exp));
-  rtx *x;
-
-  for (; format[n] != '\0'; n++)
-    {
-      switch (format[n])
-       {
-       case 'e':
-         /* Call F on X.  */
-         x = &XEXP (exp, n);
-         result = (*f) (x, data);
-         if (result == -1)
-           /* Do not traverse sub-expressions.  */
-           continue;
-         else if (result != 0)
-           /* Stop the traversal.  */
-           return result;
-
-         if (*x == NULL_RTX)
-           /* There are no sub-expressions.  */
-           continue;
-
-         i = non_rtx_starting_operands[GET_CODE (*x)];
-         if (i >= 0)
-           {
-             result = for_each_rtx_1 (*x, i, f, data);
-             if (result != 0)
-               return result;
-           }
-         break;
-
-       case 'V':
-       case 'E':
-         if (XVEC (exp, n) == 0)
-           continue;
-         for (j = 0; j < XVECLEN (exp, n); ++j)
-           {
-             /* Call F on X.  */
-             x = &XVECEXP (exp, n, j);
-             result = (*f) (x, data);
-             if (result == -1)
-               /* Do not traverse sub-expressions.  */
-               continue;
-             else if (result != 0)
-               /* Stop the traversal.  */
-               return result;
-
-             if (*x == NULL_RTX)
-               /* There are no sub-expressions.  */
-               continue;
-
-             i = non_rtx_starting_operands[GET_CODE (*x)];
-             if (i >= 0)
-               {
-                 result = for_each_rtx_1 (*x, i, f, data);
-                 if (result != 0)
-                   return result;
-               }
-           }
-         break;
-
-       default:
-         /* Nothing to do.  */
-         break;
-       }
-    }
-
-  return 0;
-}
-
-/* Traverse X via depth-first search, calling F for each
-   sub-expression (including X itself).  F is also passed the DATA.
-   If F returns -1, do not traverse sub-expressions, but continue
-   traversing the rest of the tree.  If F ever returns any other
-   nonzero value, stop the traversal, and return the value returned
-   by F.  Otherwise, return 0.  This function does not traverse inside
-   tree structure that contains RTX_EXPRs, or into sub-expressions
-   whose format code is `0' since it is not known whether or not those
-   codes are actually RTL.
-
-   This routine is very general, and could (should?) be used to
-   implement many of the other routines in this file.  */
-
-int
-for_each_rtx (rtx *x, rtx_function f, void *data)
-{
-  int result;
-  int i;
-
-  /* Call F on X.  */
-  result = (*f) (x, data);
-  if (result == -1)
-    /* Do not traverse sub-expressions.  */
-    return 0;
-  else if (result != 0)
-    /* Stop the traversal.  */
-    return result;
-
-  if (*x == NULL_RTX)
-    /* There are no sub-expressions.  */
-    return 0;
-
-  i = non_rtx_starting_operands[GET_CODE (*x)];
-  if (i < 0)
-    return 0;
-
-  return for_each_rtx_1 (*x, i, f, data);
-}
-
-/* Like "for_each_rtx", but for calling on an rtx_insn **.  */
-
-int
-for_each_rtx_in_insn (rtx_insn **insn, rtx_function f, void *data)
-{
-  rtx insn_as_rtx = *insn;
-  int result;
-
-  result = for_each_rtx (&insn_as_rtx, f, data);
-
-  if (insn_as_rtx != *insn)
-    *insn = safe_as_a <rtx_insn *> (insn_as_rtx);
-
-  return result;
-}
-
 \f
 
 /* MEM has a PRE/POST-INC/DEC/MODIFY address X.  Extract the operands of
@@ -3217,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)
@@ -3354,8 +3268,8 @@ loc_mentioned_in_p (rtx *loc, const_rtx in)
    (counting from the least significant bit of the operand).  */
 
 unsigned int
-subreg_lsb_1 (enum machine_mode outer_mode,
-             enum machine_mode inner_mode,
+subreg_lsb_1 (machine_mode outer_mode,
+             machine_mode inner_mode,
              unsigned int subreg_byte)
 {
   unsigned int bitpos;
@@ -3406,10 +3320,23 @@ subreg_lsb (const_rtx x)
    xmode  - The mode of xregno.
    offset - The byte offset.
    ymode  - The mode of a top level SUBREG (or what may become one).
-   info   - Pointer to structure to fill in.  */
+   info   - Pointer to structure to fill in.
+
+   Rather than considering one particular inner register (and thus one
+   particular "outer" register) in isolation, this function really uses
+   XREGNO as a model for a sequence of isomorphic hard registers.  Thus the
+   function does not check whether adding INFO->offset to XREGNO gives
+   a valid hard register; even if INFO->offset + XREGNO is out of range,
+   there might be another register of the same type that is in range.
+   Likewise it doesn't check whether HARD_REGNO_MODE_OK accepts the new
+   register, since that can depend on things like whether the final
+   register number is even or odd.  Callers that want to check whether
+   this particular subreg can be replaced by a simple (reg ...) should
+   use simplify_subreg_regno.  */
+
 void
-subreg_get_info (unsigned int xregno, enum machine_mode xmode,
-                unsigned int offset, enum machine_mode ymode,
+subreg_get_info (unsigned int xregno, machine_mode xmode,
+                unsigned int offset, machine_mode ymode,
                 struct subreg_info *info)
 {
   int nregs_xmode, nregs_ymode;
@@ -3426,7 +3353,7 @@ subreg_get_info (unsigned int xregno, enum machine_mode xmode,
      that it is made up of its units concatenated together.  */
   if (HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode))
     {
-      enum machine_mode xmode_unit;
+      machine_mode xmode_unit;
 
       nregs_xmode = HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode);
       if (GET_MODE_INNER (xmode) == VOIDmode)
@@ -3508,6 +3435,22 @@ subreg_get_info (unsigned int xregno, enum 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.  */
@@ -3575,8 +3518,8 @@ subreg_get_info (unsigned int xregno, enum machine_mode xmode,
    ymode  - The mode of a top level SUBREG (or what may become one).
    RETURN - The regno offset which would be used.  */
 unsigned int
-subreg_regno_offset (unsigned int xregno, enum machine_mode xmode,
-                    unsigned int offset, enum machine_mode ymode)
+subreg_regno_offset (unsigned int xregno, machine_mode xmode,
+                    unsigned int offset, machine_mode ymode)
 {
   struct subreg_info info;
   subreg_get_info (xregno, xmode, offset, ymode, &info);
@@ -3591,8 +3534,8 @@ subreg_regno_offset (unsigned int xregno, enum machine_mode xmode,
    ymode  - The mode of a top level SUBREG (or what may become one).
    RETURN - Whether the offset is representable.  */
 bool
-subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode,
-                              unsigned int offset, enum machine_mode ymode)
+subreg_offset_representable_p (unsigned int xregno, machine_mode xmode,
+                              unsigned int offset, machine_mode ymode)
 {
   struct subreg_info info;
   subreg_get_info (xregno, xmode, offset, ymode, &info);
@@ -3608,8 +3551,8 @@ subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode,
    XREGNO is a hard register number.  */
 
 int
-simplify_subreg_regno (unsigned int xregno, enum machine_mode xmode,
-                      unsigned int offset, enum machine_mode ymode)
+simplify_subreg_regno (unsigned int xregno, machine_mode xmode,
+                      unsigned int offset, machine_mode ymode)
 {
   struct subreg_info info;
   unsigned int yregno;
@@ -3726,10 +3669,11 @@ parms_set (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
    to the outer function is passed down as a parameter).
    Do not skip BOUNDARY.  */
 rtx_insn *
-find_first_parameter_load (rtx call_insn, rtx boundary)
+find_first_parameter_load (rtx_insn *call_insn, rtx_insn *boundary)
 {
   struct parms_set_data parm;
-  rtx p, before, first_set;
+  rtx p;
+  rtx_insn *before, *first_set;
 
   /* Since different machines initialize their parameter registers
      in different orders, assume nothing.  Collect the set of all
@@ -3787,14 +3731,14 @@ find_first_parameter_load (rtx call_insn, rtx boundary)
            break;
        }
     }
-  return safe_as_a <rtx_insn *> (first_set);
+  return first_set;
 }
 
 /* Return true if we should avoid inserting code between INSN and preceding
    call instruction.  */
 
 bool
-keep_with_call_p (const_rtx insn)
+keep_with_call_p (const rtx_insn *insn)
 {
   rtx set;
 
@@ -3818,7 +3762,8 @@ keep_with_call_p (const_rtx insn)
          /* This CONST_CAST is okay because next_nonnote_insn just
             returns its argument and we assign it to a const_rtx
             variable.  */
-         const rtx_insn *i2 = next_nonnote_insn (CONST_CAST_RTX (insn));
+         const rtx_insn *i2
+           = next_nonnote_insn (const_cast<rtx_insn *> (insn));
          if (i2 && keep_with_call_p (i2))
            return true;
        }
@@ -3832,7 +3777,7 @@ keep_with_call_p (const_rtx insn)
    not apply to the fallthru case of a conditional jump.  */
 
 bool
-label_is_jump_target_p (const_rtx label, const_rtx jump_insn)
+label_is_jump_target_p (const_rtx label, const rtx_insn *jump_insn)
 {
   rtx tmp = JUMP_LABEL (jump_insn);
   rtx_jump_table_data *table;
@@ -3970,7 +3915,7 @@ get_full_rtx_cost (rtx x, enum rtx_code outer, int opno,
    be returned.  */
 
 int
-address_cost (rtx x, enum machine_mode mode, addr_space_t as, bool speed)
+address_cost (rtx x, machine_mode mode, addr_space_t as, bool speed)
 {
   /* We may be asked for cost of various unusual addresses, such as operands
      of push instruction.  It is not worthwhile to complicate writing
@@ -3985,20 +3930,20 @@ address_cost (rtx x, enum machine_mode mode, addr_space_t as, bool speed)
 /* If the target doesn't override, compute the cost as with arithmetic.  */
 
 int
-default_address_cost (rtx x, enum machine_mode, addr_space_t, bool speed)
+default_address_cost (rtx x, machine_mode, addr_space_t, bool speed)
 {
   return rtx_cost (x, MEM, 0, speed);
 }
 \f
 
 unsigned HOST_WIDE_INT
-nonzero_bits (const_rtx x, enum machine_mode mode)
+nonzero_bits (const_rtx x, machine_mode mode)
 {
   return cached_nonzero_bits (x, mode, NULL_RTX, VOIDmode, 0);
 }
 
 unsigned int
-num_sign_bit_copies (const_rtx x, enum machine_mode mode)
+num_sign_bit_copies (const_rtx x, machine_mode mode)
 {
   return cached_num_sign_bit_copies (x, mode, NULL_RTX, VOIDmode, 0);
 }
@@ -4008,8 +3953,8 @@ num_sign_bit_copies (const_rtx x, enum machine_mode mode)
    identical subexpressions on the first or the second level.  */
 
 static unsigned HOST_WIDE_INT
-cached_nonzero_bits (const_rtx x, enum machine_mode mode, const_rtx known_x,
-                    enum machine_mode known_mode,
+cached_nonzero_bits (const_rtx x, machine_mode mode, const_rtx known_x,
+                    machine_mode known_mode,
                     unsigned HOST_WIDE_INT known_ret)
 {
   if (x == known_x && mode == known_mode)
@@ -4061,14 +4006,14 @@ cached_nonzero_bits (const_rtx x, enum machine_mode mode, const_rtx known_x,
    an arithmetic operation, we can do better.  */
 
 static unsigned HOST_WIDE_INT
-nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x,
-              enum machine_mode known_mode,
+nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
+              machine_mode known_mode,
               unsigned HOST_WIDE_INT known_ret)
 {
   unsigned HOST_WIDE_INT nonzero = GET_MODE_MASK (mode);
   unsigned HOST_WIDE_INT inner_nz;
   enum rtx_code code;
-  enum machine_mode inner_mode;
+  machine_mode inner_mode;
   unsigned int mode_width = GET_MODE_PRECISION (mode);
 
   /* For floating-point and vector values, assume all bits are needed.  */
@@ -4416,7 +4361,7 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x,
          && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT
          && INTVAL (XEXP (x, 1)) < GET_MODE_PRECISION (GET_MODE (x)))
        {
-         enum machine_mode inner_mode = GET_MODE (x);
+         machine_mode inner_mode = GET_MODE (x);
          unsigned int width = GET_MODE_PRECISION (inner_mode);
          int count = INTVAL (XEXP (x, 1));
          unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (inner_mode);
@@ -4519,8 +4464,8 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x,
    first or the second level.  */
 
 static unsigned int
-cached_num_sign_bit_copies (const_rtx x, enum machine_mode mode, const_rtx known_x,
-                           enum machine_mode known_mode,
+cached_num_sign_bit_copies (const_rtx x, machine_mode mode, const_rtx known_x,
+                           machine_mode known_mode,
                            unsigned int known_ret)
 {
   if (x == known_x && mode == known_mode)
@@ -4570,8 +4515,8 @@ cached_num_sign_bit_copies (const_rtx x, enum machine_mode mode, const_rtx known
    be between 1 and the number of bits in MODE.  */
 
 static unsigned int
-num_sign_bit_copies1 (const_rtx x, enum machine_mode mode, const_rtx known_x,
-                     enum machine_mode known_mode,
+num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
+                     machine_mode known_mode,
                      unsigned int known_ret)
 {
   enum rtx_code code = GET_CODE (x);
@@ -4998,6 +4943,26 @@ insn_rtx_cost (rtx pat, bool speed)
   return cost > 0 ? cost : COSTS_N_INSNS (1);
 }
 
+/* Returns estimate on cost of computing SEQ.  */
+
+unsigned
+seq_cost (const rtx_insn *seq, bool speed)
+{
+  unsigned cost = 0;
+  rtx set;
+
+  for (; seq; seq = NEXT_INSN (seq))
+    {
+      set = single_set (seq);
+      if (set)
+        cost += set_rtx_cost (set, speed);
+      else
+        cost++;
+    }
+
+  return cost;
+}
+
 /* Given an insn INSN and condition COND, return the condition in a
    canonical form to simplify testing by callers.  Specifically:
 
@@ -5036,7 +5001,7 @@ canonicalize_condition (rtx_insn *insn, rtx cond, int reverse,
   rtx tem;
   rtx op0, op1;
   int reverse_code = 0;
-  enum machine_mode mode;
+  machine_mode mode;
   basic_block bb = BLOCK_FOR_INSN (insn);
 
   code = GET_CODE (cond);
@@ -5065,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)
@@ -5081,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)
@@ -5119,7 +5082,7 @@ canonicalize_condition (rtx_insn *insn, rtx cond, int reverse,
         relevant.  */
       if (set)
        {
-         enum machine_mode inner_mode = GET_MODE (SET_DEST (set));
+         machine_mode inner_mode = GET_MODE (SET_DEST (set));
 #ifdef FLOAT_STORE_FLAG_VALUE
          REAL_VALUE_TYPE fsfv;
 #endif
@@ -5315,7 +5278,7 @@ get_condition (rtx_insn *jump, rtx_insn **earliest, int allow_cc_mode,
      the condition.  */
   reverse
     = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
-      && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump);
+      && LABEL_REF_LABEL (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (jump);
 
   return canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX,
                                 allow_cc_mode, valid_at_insn_p);
@@ -5333,14 +5296,14 @@ get_condition (rtx_insn *jump, rtx_insn **earliest, int allow_cc_mode,
 static void
 init_num_sign_bit_copies_in_rep (void)
 {
-  enum machine_mode mode, in_mode;
+  machine_mode mode, in_mode;
 
   for (in_mode = GET_CLASS_NARROWEST_MODE (MODE_INT); in_mode != VOIDmode;
        in_mode = GET_MODE_WIDER_MODE (mode))
     for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != in_mode;
         mode = GET_MODE_WIDER_MODE (mode))
       {
-       enum machine_mode i;
+       machine_mode i;
 
        /* Currently, it is assumed that TARGET_MODE_REP_EXTENDED
           extends to the next widest mode.  */
@@ -5351,7 +5314,7 @@ init_num_sign_bit_copies_in_rep (void)
           have to be copies of the sign-bit.  */
        for (i = mode; i != in_mode; i = GET_MODE_WIDER_MODE (i))
          {
-           enum machine_mode wider = GET_MODE_WIDER_MODE (i);
+           machine_mode wider = GET_MODE_WIDER_MODE (i);
 
            if (targetm.mode_rep_extended (i, wider) == SIGN_EXTEND
                /* We can only check sign-bit copies starting from the
@@ -5370,7 +5333,7 @@ init_num_sign_bit_copies_in_rep (void)
    assume it already contains a truncated value of MODE.  */
 
 bool
-truncated_to_mode (enum machine_mode mode, const_rtx x)
+truncated_to_mode (machine_mode mode, const_rtx x)
 {
   /* This register has already been used in MODE without explicit
      truncation.  */
@@ -5421,17 +5384,13 @@ setup_reg_subrtx_bounds (unsigned int code)
   return true;
 }
 
-/* Initialize non_rtx_starting_operands, which is used to speed up
-   for_each_rtx, and rtx_all_subrtx_bounds.  */
+/* Initialize rtx_all_subrtx_bounds.  */
 void
 init_rtlanal (void)
 {
   int i;
   for (i = 0; i < NUM_RTX_CODE; i++)
     {
-      const char *format = GET_RTX_FORMAT (i);
-      const char *first = strpbrk (format, "eEV");
-      non_rtx_starting_operands[i] = first ? first - format : -1;
       if (!setup_reg_subrtx_bounds (i))
        rtx_all_subrtx_bounds[i].count = UCHAR_MAX;
       if (GET_RTX_CLASS (i) != RTX_CONST_OBJ)
@@ -5454,7 +5413,7 @@ constant_pool_constant_p (rtx x)
    M is used in machine mode MODE.  */
 
 int
-low_bitmask_len (enum machine_mode mode, unsigned HOST_WIDE_INT m)
+low_bitmask_len (machine_mode mode, unsigned HOST_WIDE_INT m)
 {
   if (mode != VOIDmode)
     {
@@ -5468,10 +5427,10 @@ low_bitmask_len (enum machine_mode mode, unsigned HOST_WIDE_INT m)
 
 /* Return the mode of MEM's address.  */
 
-enum machine_mode
+machine_mode
 get_address_mode (rtx mem)
 {
-  enum machine_mode mode;
+  machine_mode mode;
 
   gcc_assert (MEM_P (mem));
   mode = GET_MODE (XEXP (mem, 0));
@@ -5650,7 +5609,7 @@ lsb_bitfield_op_p (rtx x)
 {
   if (GET_RTX_CLASS (GET_CODE (x)) == RTX_BITFIELD_OPS)
     {
-      enum machine_mode mode = GET_MODE (XEXP (x, 0));
+      machine_mode mode = GET_MODE (XEXP (x, 0));
       HOST_WIDE_INT len = INTVAL (XEXP (x, 1));
       HOST_WIDE_INT pos = INTVAL (XEXP (x, 2));
 
@@ -5721,7 +5680,8 @@ get_base_term (rtx *inner)
     inner = strip_address_mutations (&XEXP (*inner, 0));
   if (REG_P (*inner)
       || MEM_P (*inner)
-      || GET_CODE (*inner) == SUBREG)
+      || GET_CODE (*inner) == SUBREG
+      || GET_CODE (*inner) == SCRATCH)
     return inner;
   return 0;
 }
@@ -5737,7 +5697,8 @@ get_index_term (rtx *inner)
     inner = strip_address_mutations (&XEXP (*inner, 0));
   if (REG_P (*inner)
       || MEM_P (*inner)
-      || GET_CODE (*inner) == SUBREG)
+      || GET_CODE (*inner) == SUBREG
+      || GET_CODE (*inner) == SCRATCH)
     return inner;
   return 0;
 }
@@ -5857,7 +5818,7 @@ extract_plus_operands (rtx *loc, rtx **ptr, rtx **end)
    MODE, AS, OUTER_CODE and INDEX_CODE are as for ok_for_base_p_1.  */
 
 static int
-baseness (rtx x, enum machine_mode mode, addr_space_t as,
+baseness (rtx x, machine_mode mode, addr_space_t as,
          enum rtx_code outer_code, enum rtx_code index_code)
 {
   /* Believe *_POINTER unless the address shape requires otherwise.  */
@@ -5963,7 +5924,7 @@ decompose_normal_address (struct address_info *info)
    OUTER_CODE is MEM if *LOC is a MEM address and ADDRESS otherwise.  */
 
 void
-decompose_address (struct address_info *info, rtx *loc, enum machine_mode mode,
+decompose_address (struct address_info *info, rtx *loc, machine_mode mode,
                   addr_space_t as, enum rtx_code outer_code)
 {
   memset (info, 0, sizeof (*info));
@@ -6067,7 +6028,7 @@ tls_referenced_p (const_rtx x)
     return false;
 
   subrtx_iterator::array_type array;
-  FOR_EACH_SUBRTX (iter, array, x, NONCONST)
+  FOR_EACH_SUBRTX (iter, array, x, ALL)
     if (GET_CODE (*iter) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (*iter) != 0)
       return true;
   return false;