re PR debug/66691 (ICE on valid code at -O3 with -g enabled in simplify_subreg, at...
[gcc.git] / gcc / reload.c
index 959d143b8766dbdeb29bc2ea5d7df06ade44d2b0..1dc04bf0eb96df901aad7d043f58f4d6066c4cbe 100644 (file)
@@ -1,5 +1,5 @@
 /* Search an insn for pseudo regs that must be in hard regs and are not.
-   Copyright (C) 1987-2013 Free Software Foundation, Inc.
+   Copyright (C) 1987-2015 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -95,16 +95,32 @@ a register with any other reload.  */
 #include "rtl-error.h"
 #include "tm_p.h"
 #include "insn-config.h"
+#include "symtab.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "rtl.h"
+#include "flags.h"
+#include "alias.h"
+#include "tree.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
 #include "expr.h"
+#include "insn-codes.h"
 #include "optabs.h"
 #include "recog.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "predict.h"
+#include "basic-block.h"
 #include "df.h"
 #include "reload.h"
 #include "regs.h"
 #include "addresses.h"
-#include "hard-reg-set.h"
-#include "flags.h"
-#include "function.h"
 #include "params.h"
 #include "target.h"
 #include "ira.h"
@@ -156,7 +172,7 @@ struct replacement
 {
   rtx *where;                  /* Location to store in */
   int what;                    /* which reload this is for */
-  enum machine_mode mode;      /* mode it must have */
+  machine_mode mode;   /* mode it must have */
 };
 
 static struct replacement replacements[MAX_RECOG_OPERANDS * ((MAX_REGS_PER_ADDRESS * 2) + 1)];
@@ -191,7 +207,7 @@ static int secondary_memlocs_elim_used = 0;
 
 /* The instruction we are doing reloads for;
    so we can test whether a register dies in it.  */
-static rtx this_insn;
+static rtx_insn *this_insn;
 
 /* Nonzero if this instruction is a user-specified asm with operands.  */
 static int this_insn_is_asm;
@@ -249,39 +265,39 @@ static int output_reloadnum;
       : (type)))
 
 static int push_secondary_reload (int, rtx, int, int, enum reg_class,
-                                 enum machine_mode, enum reload_type,
+                                 machine_mode, enum reload_type,
                                  enum insn_code *, secondary_reload_info *);
-static enum reg_class find_valid_class (enum machine_mode, enum machine_mode,
+static enum reg_class find_valid_class (machine_mode, machine_mode,
                                        int, unsigned int);
-static void push_replacement (rtx *, int, enum machine_mode);
+static void push_replacement (rtx *, int, machine_mode);
 static void dup_replacements (rtx *, rtx *);
 static void combine_reloads (void);
 static int find_reusable_reload (rtx *, rtx, enum reg_class,
                                 enum reload_type, int, int);
-static rtx find_dummy_reload (rtx, rtx, rtx *, rtx *, enum machine_mode,
-                             enum machine_mode, reg_class_t, int, int);
+static rtx find_dummy_reload (rtx, rtx, rtx *, rtx *, machine_mode,
+                             machine_mode, reg_class_t, int, int);
 static int hard_reg_set_here_p (unsigned int, unsigned int, rtx);
 static struct decomposition decompose (rtx);
 static int immune_p (rtx, rtx, struct decomposition);
 static bool alternative_allows_const_pool_ref (rtx, const char *, int);
-static rtx find_reloads_toplev (rtx, int, enum reload_type, int, int, rtx,
-                               int *);
+static rtx find_reloads_toplev (rtx, int, enum reload_type, int, int,
+                               rtx_insn *, int *);
 static rtx make_memloc (rtx, int);
-static int maybe_memory_address_addr_space_p (enum machine_mode, rtx,
+static int maybe_memory_address_addr_space_p (machine_mode, rtx,
                                              addr_space_t, rtx *);
-static int find_reloads_address (enum machine_mode, rtx *, rtx, rtx *,
-                                int, enum reload_type, int, rtx);
-static rtx subst_reg_equivs (rtx, rtx);
+static int find_reloads_address (machine_mode, rtx *, rtx, rtx *,
+                                int, enum reload_type, int, rtx_insn *);
+static rtx subst_reg_equivs (rtx, rtx_insn *);
 static rtx subst_indexed_address (rtx);
-static void update_auto_inc_notes (rtx, int, int);
-static int find_reloads_address_1 (enum machine_mode, addr_space_t, rtx, int,
+static void update_auto_inc_notes (rtx_insn *, int, int);
+static int find_reloads_address_1 (machine_mode, addr_space_t, rtx, int,
                                   enum rtx_code, enum rtx_code, rtx *,
-                                  int, enum reload_type,int, rtx);
+                                  int, enum reload_type,int, rtx_insn *);
 static void find_reloads_address_part (rtx, rtx *, enum reg_class,
-                                      enum machine_mode, int,
+                                      machine_mode, int,
                                       enum reload_type, int);
 static rtx find_reloads_subreg_address (rtx, int, enum reload_type,
-                                       int, rtx, int *);
+                                       int, rtx_insn *, int *);
 static void copy_replacements_1 (rtx *, rtx *, int);
 static int find_inc_amount (rtx, rtx);
 static int refers_to_mem_for_reload_p (rtx);
@@ -317,18 +333,17 @@ push_reg_equiv_alt_mem (int regno, rtx mem)
 static int
 push_secondary_reload (int in_p, rtx x, int opnum, int optional,
                       enum reg_class reload_class,
-                      enum machine_mode reload_mode, enum reload_type type,
+                      machine_mode reload_mode, enum reload_type type,
                       enum insn_code *picode, secondary_reload_info *prev_sri)
 {
   enum reg_class rclass = NO_REGS;
   enum reg_class scratch_class;
-  enum machine_mode mode = reload_mode;
+  machine_mode mode = reload_mode;
   enum insn_code icode = CODE_FOR_nothing;
   enum insn_code t_icode = CODE_FOR_nothing;
   enum reload_type secondary_type;
   int s_reload, t_reload = -1;
   const char *scratch_constraint;
-  char letter;
   secondary_reload_info sri;
 
   if (type == RELOAD_FOR_INPUT_ADDRESS
@@ -399,10 +414,8 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
       scratch_constraint++;
       if (*scratch_constraint == '&')
        scratch_constraint++;
-      letter = *scratch_constraint;
-      scratch_class = (letter == 'r' ? GENERAL_REGS
-                      : REG_CLASS_FROM_CONSTRAINT ((unsigned char) letter,
-                                                  scratch_constraint));
+      scratch_class = (reg_class_for_constraint
+                      (lookup_constraint (scratch_constraint)));
 
       rclass = scratch_class;
       mode = insn_data[(int) icode].operand[2].mode;
@@ -517,7 +530,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
    register and a scratch register is needed, we return the class of the
    intermediate register.  */
 reg_class_t
-secondary_reload_class (bool in_p, reg_class_t rclass, enum machine_mode mode,
+secondary_reload_class (bool in_p, reg_class_t rclass, machine_mode mode,
                        rtx x)
 {
   enum insn_code icode;
@@ -548,7 +561,6 @@ enum reg_class
 scratch_reload_class (enum insn_code icode)
 {
   const char *scratch_constraint;
-  char scratch_letter;
   enum reg_class rclass;
 
   gcc_assert (insn_data[(int) icode].n_operands == 3);
@@ -557,11 +569,7 @@ scratch_reload_class (enum insn_code icode)
   scratch_constraint++;
   if (*scratch_constraint == '&')
     scratch_constraint++;
-  scratch_letter = *scratch_constraint;
-  if (scratch_letter == 'r')
-    return GENERAL_REGS;
-  rclass = REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
-                                    scratch_constraint);
+  rclass = reg_class_for_constraint (lookup_constraint (scratch_constraint));
   gcc_assert (rclass != NO_REGS);
   return rclass;
 }
@@ -573,7 +581,7 @@ scratch_reload_class (enum insn_code icode)
    call find_reloads_address on the location being returned.  */
 
 rtx
-get_secondary_mem (rtx x ATTRIBUTE_UNUSED, enum machine_mode mode,
+get_secondary_mem (rtx x ATTRIBUTE_UNUSED, machine_mode mode,
                   int opnum, enum reload_type type)
 {
   rtx loc;
@@ -658,8 +666,8 @@ clear_secondary_mem (void)
    into REGNO.  Such a class must exist.  */
 
 static enum reg_class
-find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
-                 enum machine_mode inner ATTRIBUTE_UNUSED, int n,
+find_valid_class (machine_mode outer ATTRIBUTE_UNUSED,
+                 machine_mode inner ATTRIBUTE_UNUSED, int n,
                  unsigned int dest_regno ATTRIBUTE_UNUSED)
 {
   int best_cost = -1;
@@ -680,8 +688,8 @@ find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
            if (HARD_REGNO_MODE_OK (regno, inner))
              {
                good = 1;
-               if (TEST_HARD_REG_BIT (reg_class_contents[rclass], regno + n)
-                   || ! HARD_REGNO_MODE_OK (regno + n, outer))
+               if (TEST_HARD_REG_BIT (reg_class_contents[rclass], regno + n)
+                   && ! HARD_REGNO_MODE_OK (regno + n, outer))
                  bad = 1;
              }
          }
@@ -712,8 +720,8 @@ find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
    which we would eventually like to obtain the object.  */
 
 static enum reg_class
-find_valid_class_1 (enum machine_mode outer ATTRIBUTE_UNUSED,
-                   enum machine_mode mode ATTRIBUTE_UNUSED,
+find_valid_class_1 (machine_mode outer ATTRIBUTE_UNUSED,
+                   machine_mode mode ATTRIBUTE_UNUSED,
                    enum reg_class dest_class ATTRIBUTE_UNUSED)
 {
   int best_cost = -1;
@@ -843,7 +851,7 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
    the function is invoked for the output part of an enclosing reload.  */
 
 static bool
-reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, bool output)
+reload_inner_reg_of_subreg (rtx x, machine_mode mode, bool output)
 {
   rtx inner;
 
@@ -891,11 +899,12 @@ reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, bool output)
    patterns by register elimination and substituting pseudos without a home
    by their function-invariant equivalences.  */
 static int
-can_reload_into (rtx in, int regno, enum machine_mode mode)
+can_reload_into (rtx in, int regno, machine_mode mode)
 {
-  rtx dst, test_insn;
+  rtx dst;
+  rtx_insn *test_insn;
   int r = 0;
-  struct Recog_data save_recog_data;
+  struct recog_data_d save_recog_data;
 
   /* For matching constraints, we often get notional input reloads where
      we want to use the original register as the reload register.  I.e.
@@ -915,12 +924,12 @@ can_reload_into (rtx in, int regno, enum machine_mode mode)
   /* If we can make a simple SET insn that does the job, everything should
      be fine.  */
   dst =  gen_rtx_REG (mode, regno);
-  test_insn = make_insn_raw (gen_rtx_SET (VOIDmode, dst, in));
+  test_insn = make_insn_raw (gen_rtx_SET (dst, in));
   save_recog_data = recog_data;
   if (recog_memoized (test_insn) >= 0)
     {
       extract_insn (test_insn);
-      r = constrain_operands (1);
+      r = constrain_operands (1, get_enabled_alternatives (test_insn));
     }
   recog_data = save_recog_data;
   return r;
@@ -961,8 +970,8 @@ can_reload_into (rtx in, int regno, enum machine_mode mode)
 
 int
 push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
-            enum reg_class rclass, enum machine_mode inmode,
-            enum machine_mode outmode, int strict_low, int optional,
+            enum reg_class rclass, machine_mode inmode,
+            machine_mode outmode, int strict_low, int optional,
             int opnum, enum reload_type type)
 {
   int i;
@@ -1314,7 +1323,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
      is specified.  */
   if (this_insn_is_asm)
     {
-      enum machine_mode mode;
+      machine_mode mode;
       if (GET_MODE_SIZE (inmode) > GET_MODE_SIZE (outmode))
        mode = inmode;
       else
@@ -1603,7 +1612,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
     {
       rtx note;
       int regno;
-      enum machine_mode rel_mode = inmode;
+      machine_mode rel_mode = inmode;
 
       if (out && GET_MODE_SIZE (outmode) > GET_MODE_SIZE (inmode))
        rel_mode = outmode;
@@ -1615,13 +1624,14 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
            && reg_mentioned_p (XEXP (note, 0), in)
            /* Check that a former pseudo is valid; see find_dummy_reload.  */
            && (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
-               || (! bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
+               || (! bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR_FOR_FN (cfun)),
                                    ORIGINAL_REGNO (XEXP (note, 0)))
                    && hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] == 1))
            && ! refers_to_regno_for_reload_p (regno,
                                               end_hard_regno (rel_mode,
                                                               regno),
                                               PATTERN (this_insn), inloc)
+           && ! find_reg_fusage (this_insn, USE, XEXP (note, 0))
            /* If this is also an output reload, IN cannot be used as
               the reload register if it is set in this insn unless IN
               is also OUT.  */
@@ -1678,7 +1688,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
    This is used in insn patterns that use match_dup.  */
 
 static void
-push_replacement (rtx *loc, int reloadnum, enum machine_mode mode)
+push_replacement (rtx *loc, int reloadnum, machine_mode mode)
 {
   if (replace_reloads)
     {
@@ -1939,7 +1949,7 @@ combine_reloads (void)
        && !fixed_regs[regno]
        /* Check that a former pseudo is valid; see find_dummy_reload.  */
        && (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
-           || (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
+           || (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR_FOR_FN (cfun)),
                               ORIGINAL_REGNO (XEXP (note, 0)))
                && hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] == 1)))
       {
@@ -1971,7 +1981,7 @@ combine_reloads (void)
 
 static rtx
 find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
-                  enum machine_mode inmode, enum machine_mode outmode,
+                  machine_mode inmode, machine_mode outmode,
                   reg_class_t rclass, int for_real, int earlyclobber)
 {
   rtx in = real_in;
@@ -2098,7 +2108,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
             can ignore the conflict).  We must never introduce writes
             to such hardregs, as they would clobber the other live
             pseudo.  See PR 20973.  */
-          || (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
+         || (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR_FOR_FN (cfun)),
                             ORIGINAL_REGNO (in))
              /* Similarly, only do this if we can be sure that the death
                 note is still valid.  global can assign some hardreg to
@@ -2203,7 +2213,7 @@ hard_reg_set_here_p (unsigned int beg_regno, unsigned int end_regno, rtx x)
    proper kind of hard reg.  */
 
 int
-strict_memory_address_addr_space_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+strict_memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED,
                                    rtx addr, addr_space_t as)
 {
 #ifdef GO_IF_LEGITIMATE_ADDRESS
@@ -2328,7 +2338,7 @@ operands_match_p (rtx x, rtx y)
       return 0;
 
     case LABEL_REF:
-      return XEXP (x, 0) == XEXP (y, 0);
+      return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
@@ -2617,7 +2627,7 @@ safe_from_earlyclobber (rtx op, rtx clobber)
    commutative operands, reg_equiv_address substitution, or whatever.  */
 
 int
-find_reloads (rtx insn, int replace, int ind_levels, int live_known,
+find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
              short *reload_reg_p)
 {
   int insn_code_number;
@@ -2668,7 +2678,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   rtx body = PATTERN (insn);
   rtx set = single_set (insn);
   int goal_earlyclobber = 0, this_earlyclobber;
-  enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
+  machine_mode operand_mode[MAX_RECOG_OPERANDS];
   int retval = 0;
 
   this_insn = insn;
@@ -2685,12 +2695,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   if (JUMP_P (insn) || CALL_P (insn))
     no_output_reloads = 1;
 
-#ifdef HAVE_cc0
-  if (reg_referenced_p (cc0_rtx, PATTERN (insn)))
+  if (HAVE_cc0 && reg_referenced_p (cc0_rtx, PATTERN (insn)))
     no_input_reloads = 1;
-  if (reg_set_p (cc0_rtx, PATTERN (insn)))
+  if (HAVE_cc0 && reg_set_p (cc0_rtx, PATTERN (insn)))
     no_output_reloads = 1;
-#endif
 
 #ifdef SECONDARY_MEMORY_NEEDED
   /* The eliminated forms of any secondary memory locations are per-insn, so
@@ -2730,7 +2738,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   this_insn_is_asm = insn_code_number < 0;
 
   memcpy (operand_mode, recog_data.operand_mode,
-         noperands * sizeof (enum machine_mode));
+         noperands * sizeof (machine_mode));
   memcpy (constraints, recog_data.constraints,
          noperands * sizeof (const char *));
 
@@ -2851,8 +2859,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
       if (*constraints[i] == 0)
        /* Ignore things like match_operator operands.  */
        ;
-      else if (constraints[i][0] == 'p'
-              || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
+      else if (insn_extra_address_constraint
+              (lookup_constraint (constraints[i])))
        {
          address_operand_reloaded[i]
            = find_reloads_address (recog_data.operand_mode[i], (rtx*) 0,
@@ -3004,13 +3012,14 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
      First loop over alternatives.  */
 
+  alternative_mask enabled = get_enabled_alternatives (insn);
   for (this_alternative_number = 0;
        this_alternative_number < n_alternatives;
        this_alternative_number++)
     {
       int swapped;
 
-      if (!recog_data.alternative_enabled_p[this_alternative_number])
+      if (!TEST_BIT (enabled, this_alternative_number))
        {
          int i;
 
@@ -3044,9 +3053,6 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
          if (swapped)
            {
-             enum reg_class tclass;
-             int t;
-
              recog_data.operand[commutative] = substed_operand[commutative + 1];
              recog_data.operand[commutative + 1] = substed_operand[commutative];
              /* Swap the duplicates too.  */
@@ -3056,17 +3062,12 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                  *recog_data.dup_loc[i]
                    = recog_data.operand[(int) recog_data.dup_num[i]];
 
-             tclass = preferred_class[commutative];
-             preferred_class[commutative] = preferred_class[commutative + 1];
-             preferred_class[commutative + 1] = tclass;
-
-             t = pref_or_nothing[commutative];
-             pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
-             pref_or_nothing[commutative + 1] = t;
-
-             t = address_reloaded[commutative];
-             address_reloaded[commutative] = address_reloaded[commutative + 1];
-             address_reloaded[commutative + 1] = t;
+             std::swap (preferred_class[commutative],
+                        preferred_class[commutative + 1]);
+             std::swap (pref_or_nothing[commutative],
+                        pref_or_nothing[commutative + 1]);
+             std::swap (address_reloaded[commutative],
+                        address_reloaded[commutative + 1]);
            }
 
          this_earlyclobber = 0;
@@ -3094,6 +3095,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                 operand.  */
              int constmemok = 0;
              int earlyclobber = 0;
+             enum constraint_num cn;
+             enum reg_class cl;
 
              /* If the predicate accepts a unary operator, it means that
                 we need to reload the operand, but do not do this for
@@ -3207,14 +3210,6 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                    c = '\0';
                    break;
 
-                 case '=':  case '+':  case '*':
-                   break;
-
-                 case '%':
-                   /* We only support one commutative marker, the first
-                      one.  We already set commutative above.  */
-                   break;
-
                  case '?':
                    reject += 6;
                    break;
@@ -3324,7 +3319,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                      for (j = 0; j < i; j++)
                        if (this_alternative_matches[j]
                            == this_alternative_matches[i])
-                         badop = 1;
+                         {
+                           badop = 1;
+                           break;
+                         }
                    break;
 
                  case 'p':
@@ -3420,49 +3418,6 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                    earlyclobber = 1, this_earlyclobber = 1;
                    break;
 
-                 case 'E':
-                 case 'F':
-                   if (CONST_DOUBLE_AS_FLOAT_P (operand)
-                       || (GET_CODE (operand) == CONST_VECTOR
-                           && (GET_MODE_CLASS (GET_MODE (operand))
-                               == MODE_VECTOR_FLOAT)))
-                     win = 1;
-                   break;
-
-                 case 'G':
-                 case 'H':
-                   if (CONST_DOUBLE_AS_FLOAT_P (operand)
-                       && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (operand, c, p))
-                     win = 1;
-                   break;
-
-                 case 's':
-                   if (CONST_SCALAR_INT_P (operand))
-                     break;
-                 case 'i':
-                   if (CONSTANT_P (operand)
-                       && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (operand)))
-                     win = 1;
-                   break;
-
-                 case 'n':
-                   if (CONST_SCALAR_INT_P (operand))
-                     win = 1;
-                   break;
-
-                 case 'I':
-                 case 'J':
-                 case 'K':
-                 case 'L':
-                 case 'M':
-                 case 'N':
-                 case 'O':
-                 case 'P':
-                   if (CONST_INT_P (operand)
-                       && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p))
-                     win = 1;
-                   break;
-
                  case 'X':
                    force_reload = 0;
                    win = 1;
@@ -3483,74 +3438,81 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                            || (REGNO (operand) >= FIRST_PSEUDO_REGISTER
                                && reg_renumber[REGNO (operand)] < 0)))
                      win = 1;
-                   /* Drop through into 'r' case.  */
-
-                 case 'r':
-                   this_alternative[i]
-                     = reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
+                   cl = GENERAL_REGS;
                    goto reg;
 
                  default:
-                   if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS)
+                   cn = lookup_constraint (p);
+                   switch (get_constraint_type (cn))
                      {
-#ifdef EXTRA_CONSTRAINT_STR
-                       if (EXTRA_MEMORY_CONSTRAINT (c, p))
-                         {
-                           if (force_reload)
-                             break;
-                           if (EXTRA_CONSTRAINT_STR (operand, c, p))
-                             win = 1;
-                           /* If the address was already reloaded,
-                              we win as well.  */
-                           else if (MEM_P (operand)
-                                    && address_reloaded[i] == 1)
-                             win = 1;
-                           /* Likewise if the address will be reloaded because
-                              reg_equiv_address is nonzero.  For reg_equiv_mem
-                              we have to check.  */
-                           else if (REG_P (operand)
-                                    && REGNO (operand) >= FIRST_PSEUDO_REGISTER
-                                    && reg_renumber[REGNO (operand)] < 0
-                                    && ((reg_equiv_mem (REGNO (operand)) != 0
-                                         && EXTRA_CONSTRAINT_STR (reg_equiv_mem (REGNO (operand)), c, p))
-                                        || (reg_equiv_address (REGNO (operand)) != 0)))
-                             win = 1;
-
-                           /* If we didn't already win, we can reload
-                              constants via force_const_mem, and other
-                              MEMs by reloading the address like for 'o'.  */
-                           if (CONST_POOL_OK_P (operand_mode[i], operand)
-                               || MEM_P (operand))
-                             badop = 0;
-                           constmemok = 1;
-                           offmemok = 1;
-                           break;
-                         }
-                       if (EXTRA_ADDRESS_CONSTRAINT (c, p))
-                         {
-                           if (EXTRA_CONSTRAINT_STR (operand, c, p))
-                             win = 1;
-
-                           /* If we didn't already win, we can reload
-                              the address into a base register.  */
-                           this_alternative[i]
-                             = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
-                                               ADDRESS, SCRATCH);
-                           badop = 0;
-                           break;
-                         }
+                     case CT_REGISTER:
+                       cl = reg_class_for_constraint (cn);
+                       if (cl != NO_REGS)
+                         goto reg;
+                       break;
+
+                     case CT_CONST_INT:
+                       if (CONST_INT_P (operand)
+                           && (insn_const_int_ok_for_constraint
+                               (INTVAL (operand), cn)))
+                         win = true;
+                       break;
 
-                       if (EXTRA_CONSTRAINT_STR (operand, c, p))
+                     case CT_MEMORY:
+                       if (force_reload)
+                         break;
+                       if (constraint_satisfied_p (operand, cn))
+                         win = 1;
+                       /* If the address was already reloaded,
+                          we win as well.  */
+                       else if (MEM_P (operand) && address_reloaded[i] == 1)
+                         win = 1;
+                       /* Likewise if the address will be reloaded because
+                          reg_equiv_address is nonzero.  For reg_equiv_mem
+                          we have to check.  */
+                       else if (REG_P (operand)
+                                && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+                                && reg_renumber[REGNO (operand)] < 0
+                                && ((reg_equiv_mem (REGNO (operand)) != 0
+                                     && (constraint_satisfied_p
+                                         (reg_equiv_mem (REGNO (operand)),
+                                          cn)))
+                                    || (reg_equiv_address (REGNO (operand))
+                                        != 0)))
+                         win = 1;
+
+                       /* If we didn't already win, we can reload
+                          constants via force_const_mem, and other
+                          MEMs by reloading the address like for 'o'.  */
+                       if (CONST_POOL_OK_P (operand_mode[i], operand)
+                           || MEM_P (operand))
+                         badop = 0;
+                       constmemok = 1;
+                       offmemok = 1;
+                       break;
+
+                     case CT_ADDRESS:
+                       if (constraint_satisfied_p (operand, cn))
+                         win = 1;
+
+                       /* If we didn't already win, we can reload
+                          the address into a base register.  */
+                       this_alternative[i]
+                         = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+                                           ADDRESS, SCRATCH);
+                       badop = 0;
+                       break;
+
+                     case CT_FIXED_FORM:
+                       if (constraint_satisfied_p (operand, cn))
                          win = 1;
-#endif
                        break;
                      }
+                   break;
 
-                   this_alternative[i]
-                     = (reg_class_subunion
-                        [this_alternative[i]]
-                        [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
                  reg:
+                   this_alternative[i]
+                     = reg_class_subunion[this_alternative[i]][cl];
                    if (GET_MODE (operand) == BLKmode)
                      break;
                    winreg = 1;
@@ -3837,9 +3799,6 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
          if (swapped)
            {
-             enum reg_class tclass;
-             int t;
-
              /* If the commutative operands have been swapped, swap
                 them back in order to check the next alternative.  */
              recog_data.operand[commutative] = substed_operand[commutative];
@@ -3852,17 +3811,12 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                    = recog_data.operand[(int) recog_data.dup_num[i]];
 
              /* Unswap the operand related information as well.  */
-             tclass = preferred_class[commutative];
-             preferred_class[commutative] = preferred_class[commutative + 1];
-             preferred_class[commutative + 1] = tclass;
-
-             t = pref_or_nothing[commutative];
-             pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
-             pref_or_nothing[commutative + 1] = t;
-
-             t = address_reloaded[commutative];
-             address_reloaded[commutative] = address_reloaded[commutative + 1];
-             address_reloaded[commutative + 1] = t;
+             std::swap (preferred_class[commutative],
+                        preferred_class[commutative + 1]);
+             std::swap (pref_or_nothing[commutative],
+                        pref_or_nothing[commutative + 1]);
+             std::swap (address_reloaded[commutative],
+                        address_reloaded[commutative + 1]);
            }
        }
     }
@@ -3911,18 +3865,18 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
   if (goal_alternative_swapped)
     {
-      rtx tem;
-
-      tem = substed_operand[commutative];
-      substed_operand[commutative] = substed_operand[commutative + 1];
-      substed_operand[commutative + 1] = tem;
-      tem = recog_data.operand[commutative];
-      recog_data.operand[commutative] = recog_data.operand[commutative + 1];
-      recog_data.operand[commutative + 1] = tem;
-      tem = *recog_data.operand_loc[commutative];
-      *recog_data.operand_loc[commutative]
-       = *recog_data.operand_loc[commutative + 1];
-      *recog_data.operand_loc[commutative + 1] = tem;
+      std::swap (substed_operand[commutative],
+                substed_operand[commutative + 1]);
+      std::swap (recog_data.operand[commutative],
+                recog_data.operand[commutative + 1]);
+      std::swap (*recog_data.operand_loc[commutative],
+                *recog_data.operand_loc[commutative + 1]);
+
+      for (i = 0; i < recog_data.n_dups; i++)
+       if (recog_data.dup_num[i] == commutative
+           || recog_data.dup_num[i] == commutative + 1)
+         *recog_data.dup_loc[i]
+           = recog_data.operand[(int) recog_data.dup_num[i]];
 
       for (i = 0; i < n_reloads; i++)
        {
@@ -3968,7 +3922,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
        rtx op = recog_data.operand[i];
        rtx subreg = NULL_RTX;
        rtx plus = NULL_RTX;
-       enum machine_mode mode = operand_mode[i];
+       machine_mode mode = operand_mode[i];
 
        /* Reloads of SUBREGs of CONSTANT RTXs are handled later in
           push_reload so we have to let them pass here.  */
@@ -4046,7 +4000,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
               use the default address mode as mode of the reload register,
               as would have been done by find_reloads_address.  */
            addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]);
-           enum machine_mode address_mode;
+           machine_mode address_mode;
 
            address_mode = get_address_mode (recog_data.operand[i]);
            operand_reloadnum[i]
@@ -4267,16 +4221,17 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
             this instruction.  */
          if (GET_CODE (substitution) == LABEL_REF
              && !find_reg_note (insn, REG_LABEL_OPERAND,
-                                XEXP (substitution, 0))
+                                LABEL_REF_LABEL (substitution))
              /* For a JUMP_P, if it was a branch target it must have
                 already been recorded as such.  */
              && (!JUMP_P (insn)
-                 || !label_is_jump_target_p (XEXP (substitution, 0),
+                 || !label_is_jump_target_p (LABEL_REF_LABEL (substitution),
                                              insn)))
            {
-             add_reg_note (insn, REG_LABEL_OPERAND, XEXP (substitution, 0));
-             if (LABEL_P (XEXP (substitution, 0)))
-               ++LABEL_NUSES (XEXP (substitution, 0));
+             add_reg_note (insn, REG_LABEL_OPERAND,
+                           LABEL_REF_LABEL (substitution));
+             if (LABEL_P (LABEL_REF_LABEL (substitution)))
+               ++LABEL_NUSES (LABEL_REF_LABEL (substitution));
            }
 
        }
@@ -4595,16 +4550,14 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
            rld[j].in = 0;
          }
 
-#ifdef HAVE_cc0
   /* If we made any reloads for addresses, see if they violate a
      "no input reloads" requirement for this insn.  But loads that we
      do after the insn (such as for output addresses) are fine.  */
-  if (no_input_reloads)
+  if (HAVE_cc0 && no_input_reloads)
     for (i = 0; i < n_reloads; i++)
       gcc_assert (rld[i].in == 0
                  || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS
                  || rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS);
-#endif
 
   /* Compute reload_mode and reload_nregs.  */
   for (i = 0; i < n_reloads; i++)
@@ -4640,7 +4593,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
            for (nri = 1; nri < nr; nri ++)
              if (! TEST_HARD_REG_BIT (reg_class_contents[rld[i].rclass], regno + nri))
-               ok = 0;
+               {
+                 ok = 0;
+                 break;
+               }
 
            if (ok)
              rld[i].reg_rtx = dest;
@@ -4679,13 +4635,10 @@ alternative_allows_const_pool_ref (rtx mem ATTRIBUTE_UNUSED,
   for (; (c = *constraint) && c != ',' && c != '#';
        constraint += CONSTRAINT_LEN (c, constraint))
     {
-      if (c == TARGET_MEM_CONSTRAINT || c == 'o')
-       return true;
-#ifdef EXTRA_CONSTRAINT_STR
-      if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
-         && (mem == NULL || EXTRA_CONSTRAINT_STR (mem, c, constraint)))
+      enum constraint_num cn = lookup_constraint (constraint);
+      if (insn_extra_memory_constraint (cn)
+         && (mem == NULL || constraint_satisfied_p (mem, cn)))
        return true;
-#endif
     }
   return false;
 }
@@ -4714,7 +4667,7 @@ alternative_allows_const_pool_ref (rtx mem ATTRIBUTE_UNUSED,
 
 static rtx
 find_reloads_toplev (rtx x, int opnum, enum reload_type type,
-                    int ind_levels, int is_set_dest, rtx insn,
+                    int ind_levels, int is_set_dest, rtx_insn *insn,
                     int *address_reloaded)
 {
   RTX_CODE code = GET_CODE (x);
@@ -4880,7 +4833,7 @@ make_memloc (rtx ad, int regno)
    by PART into a register.  */
 
 static int
-maybe_memory_address_addr_space_p (enum machine_mode mode, rtx ad,
+maybe_memory_address_addr_space_p (machine_mode mode, rtx ad,
                                   addr_space_t as, rtx *part)
 {
   int retv;
@@ -4920,9 +4873,9 @@ maybe_memory_address_addr_space_p (enum machine_mode mode, rtx ad,
    to a hard register, and frame pointer elimination.  */
 
 static int
-find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
+find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad,
                      rtx *loc, int opnum, enum reload_type type,
-                     int ind_levels, rtx insn)
+                     int ind_levels, rtx_insn *insn)
 {
   addr_space_t as = memrefloc? MEM_ADDR_SPACE (*memrefloc)
                             : ADDR_SPACE_GENERIC;
@@ -5226,9 +5179,8 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
           || operand == hard_frame_pointer_rtx
 #endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-          || operand == arg_pointer_rtx
-#endif
+          || (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+              && operand == arg_pointer_rtx)
           || operand == stack_pointer_rtx)
          && ! maybe_memory_address_addr_space_p
                (mode, ad, as, &XEXP (XEXP (ad, 0), 1 - op_index)))
@@ -5292,7 +5244,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
      into a register.  */
   if (CONSTANT_P (ad) && ! strict_memory_address_addr_space_p (mode, ad, as))
     {
-      enum machine_mode address_mode = GET_MODE (ad);
+      machine_mode address_mode = GET_MODE (ad);
       if (address_mode == VOIDmode)
        address_mode = targetm.addr_space.address_mode (as);
 
@@ -5324,7 +5276,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
    front of it for pseudos that we have to replace with stack slots.  */
 
 static rtx
-subst_reg_equivs (rtx ad, rtx insn)
+subst_reg_equivs (rtx ad, rtx_insn *insn)
 {
   RTX_CODE code = GET_CODE (ad);
   int i;
@@ -5393,7 +5345,7 @@ subst_reg_equivs (rtx ad, rtx insn)
    This routine assumes both inputs are already in canonical form.  */
 
 rtx
-form_sum (enum machine_mode mode, rtx x, rtx y)
+form_sum (machine_mode mode, rtx x, rtx y)
 {
   rtx tem;
 
@@ -5500,7 +5452,7 @@ subst_indexed_address (rtx addr)
    RELOADNUM is the reload number.  */
 
 static void
-update_auto_inc_notes (rtx insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED,
+update_auto_inc_notes (rtx_insn *insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED,
                       int reloadnum ATTRIBUTE_UNUSED)
 {
 #ifdef AUTO_INC_DEC
@@ -5544,11 +5496,11 @@ update_auto_inc_notes (rtx insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED,
    handles those cases gracefully.  */
 
 static int
-find_reloads_address_1 (enum machine_mode mode, addr_space_t as,
+find_reloads_address_1 (machine_mode mode, addr_space_t as,
                        rtx x, int context,
                        enum rtx_code outer_code, enum rtx_code index_code,
                        rtx *loc, int opnum, enum reload_type type,
-                       int ind_levels, rtx insn)
+                       int ind_levels, rtx_insn *insn)
 {
 #define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, AS, OUTER, INDEX)     \
   ((CONTEXT) == 0                                                      \
@@ -5557,6 +5509,7 @@ find_reloads_address_1 (enum machine_mode mode, addr_space_t as,
 
   enum reg_class context_reg_class;
   RTX_CODE code = GET_CODE (x);
+  bool reloaded_inner_of_autoinc = false;
 
   if (context == 1)
     context_reg_class = INDEX_REG_CLASS;
@@ -5844,6 +5797,7 @@ find_reloads_address_1 (enum machine_mode mode, addr_space_t as,
                  find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
                                        &XEXP (tem, 0), opnum, type,
                                        ind_levels, insn);
+                 reloaded_inner_of_autoinc = true;
                  if (!rtx_equal_p (tem, orig))
                    push_reg_equiv_alt_mem (regno, tem);
                  /* Put this inside a new increment-expression.  */
@@ -5887,12 +5841,15 @@ find_reloads_address_1 (enum machine_mode mode, addr_space_t as,
              enum insn_code icode = optab_handler (add_optab, GET_MODE (x));
              if (insn && NONJUMP_INSN_P (insn) && equiv
                  && memory_operand (equiv, GET_MODE (equiv))
-#ifdef HAVE_cc0
+#if HAVE_cc0
                  && ! sets_cc0_p (PATTERN (insn))
 #endif
                  && ! (icode != CODE_FOR_nothing
                        && insn_operand_matches (icode, 0, equiv)
-                       && insn_operand_matches (icode, 1, equiv)))
+                       && insn_operand_matches (icode, 1, equiv))
+                 /* Using RELOAD_OTHER means we emit this and the reload we
+                    made earlier in the wrong order.  */
+                 && !reloaded_inner_of_autoinc)
                {
                  /* We use the original pseudo for loc, so that
                     emit_reload_insns() knows which pseudo this
@@ -6128,7 +6085,7 @@ find_reloads_address_1 (enum machine_mode mode, addr_space_t as,
 
 static void
 find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass,
-                          enum machine_mode mode, int opnum,
+                          machine_mode mode, int opnum,
                           enum reload_type type, int ind_levels)
 {
   if (CONSTANT_P (x)
@@ -6177,10 +6134,11 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass,
 
 static rtx
 find_reloads_subreg_address (rtx x, int opnum, enum reload_type type,
-                            int ind_levels, rtx insn, int *address_reloaded)
+                            int ind_levels, rtx_insn *insn,
+                            int *address_reloaded)
 {
-  enum machine_mode outer_mode = GET_MODE (x);
-  enum machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
+  machine_mode outer_mode = GET_MODE (x);
+  machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
   int regno = REGNO (SUBREG_REG (x));
   int reloaded = 0;
   rtx tem, orig;
@@ -6286,7 +6244,7 @@ find_reloads_subreg_address (rtx x, int opnum, enum reload_type type,
    Return the rtx that X translates into; usually X, but modified.  */
 
 void
-subst_reloads (rtx insn)
+subst_reloads (rtx_insn *insn)
 {
   int i;
 
@@ -6626,7 +6584,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
          return 0;
        }
 
-      endregno = END_HARD_REGNO (x);
+      endregno = END_REGNO (x);
 
       return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
     }
@@ -6713,11 +6671,12 @@ refers_to_mem_for_reload_p (rtx x)
    as if it were a constant except that sp is required to be unchanging.  */
 
 rtx
-find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other,
-               short *reload_reg_p, int goalreg, enum machine_mode mode)
+find_equiv_reg (rtx goal, rtx_insn *insn, enum reg_class rclass, int other,
+               short *reload_reg_p, int goalreg, machine_mode mode)
 {
-  rtx p = insn;
-  rtx goaltry, valtry, value, where;
+  rtx_insn *p = insn;
+  rtx goaltry, valtry, value;
+  rtx_insn *where;
   rtx pat;
   int regno = -1;
   int valueno;
@@ -7249,7 +7208,7 @@ reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno,
    REG_INC.  REGNO must refer to a hard register.  */
 
 int
-regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
+regno_clobbered_p (unsigned int regno, rtx_insn *insn, machine_mode mode,
                   int sets)
 {
   unsigned int nregs, endregno;
@@ -7299,7 +7258,7 @@ regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
 
 /* Find the low part, with mode MODE, of a hard regno RELOADREG.  */
 rtx
-reload_adjust_reg_for_mode (rtx reloadreg, enum machine_mode mode)
+reload_adjust_reg_for_mode (rtx reloadreg, machine_mode mode)
 {
   int regno;