OSDN Git Service

* lib/target-supports.exp (check_effective_target_vect_condition):
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index 5a0da1d..8420c80 100644 (file)
@@ -1,6 +1,6 @@
 /* Search an insn for pseudo regs that must be in hard regs and are not.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -94,36 +94,42 @@ a register with any other reload.  */
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "rtl.h"
+#include "rtl-error.h"
 #include "tm_p.h"
 #include "insn-config.h"
 #include "expr.h"
 #include "optabs.h"
 #include "recog.h"
+#include "df.h"
 #include "reload.h"
 #include "regs.h"
 #include "addresses.h"
 #include "hard-reg-set.h"
 #include "flags.h"
-#include "real.h"
 #include "output.h"
 #include "function.h"
-#include "toplev.h"
 #include "params.h"
 #include "target.h"
-#include "df.h"
+#include "ira.h"
 
-/* True if X is a constant that can be forced into the constant pool.  */
-#define CONST_POOL_OK_P(X)                     \
-  (CONSTANT_P (X)                              \
+/* True if X is a constant that can be forced into the constant pool.
+   MODE is the mode of the operand, or VOIDmode if not known.  */
+#define CONST_POOL_OK_P(MODE, X)               \
+  ((MODE) != VOIDmode                          \
+   && CONSTANT_P (X)                           \
    && GET_CODE (X) != HIGH                     \
-   && !targetm.cannot_force_const_mem (X))
+   && !targetm.cannot_force_const_mem (MODE, X))
 
 /* True if C is a non-empty register class that has too few registers
    to be safely used as a reload target class.  */
-#define SMALL_REGISTER_CLASS_P(C) \
-  (reg_class_size [(C)] == 1 \
-   || (reg_class_size [(C)] >= 1 && CLASS_LIKELY_SPILLED_P (C)))
+
+static inline bool
+small_register_class_p (reg_class_t rclass)
+{
+  return (reg_class_size [(int) rclass] == 1
+         || (reg_class_size [(int) rclass] >= 1 
+             && targetm.class_likely_spilled_p (rclass)));
+}
 
 \f
 /* All reloads of the current insn are recorded here.  See reload.h for
@@ -152,8 +158,6 @@ static int replace_reloads;
 struct replacement
 {
   rtx *where;                  /* Location to store in */
-  rtx *subreg_loc;             /* Location of SUBREG if WHERE is inside
-                                  a SUBREG; 0 otherwise.  */
   int what;                    /* which reload this is for */
   enum machine_mode mode;      /* mode it must have */
 };
@@ -252,35 +256,35 @@ static int push_secondary_reload (int, rtx, int, int, enum reg_class,
                                  enum insn_code *, secondary_reload_info *);
 static enum reg_class find_valid_class (enum machine_mode, enum machine_mode,
                                        int, unsigned int);
-static int reload_inner_reg_of_subreg (rtx, enum machine_mode, int);
 static void push_replacement (rtx *, int, enum 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, enum reg_class, int, int);
+                             enum 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 int alternative_allows_memconst (const char *, int);
+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 make_memloc (rtx, int);
-static int maybe_memory_address_p (enum machine_mode, rtx, rtx *);
+static int maybe_memory_address_addr_space_p (enum 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 rtx subst_indexed_address (rtx);
 static void update_auto_inc_notes (rtx, int, int);
-static int find_reloads_address_1 (enum machine_mode, rtx, int,
+static int find_reloads_address_1 (enum machine_mode, addr_space_t, rtx, int,
                                   enum rtx_code, enum rtx_code, rtx *,
                                   int, enum reload_type,int, rtx);
 static void find_reloads_address_part (rtx, rtx *, enum reg_class,
                                       enum machine_mode, int,
                                       enum reload_type, int);
 static rtx find_reloads_subreg_address (rtx, int, int, enum reload_type,
-                                       int, rtx);
+                                       int, rtx, 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);
@@ -295,13 +299,13 @@ push_reg_equiv_alt_mem (int regno, rtx mem)
 {
   rtx it;
 
-  for (it = reg_equiv_alt_mem_list [regno]; it; it = XEXP (it, 1))
+  for (it = reg_equiv_alt_mem_list (regno); it; it = XEXP (it, 1))
     if (rtx_equal_p (XEXP (it, 0), mem))
       return;
 
-  reg_equiv_alt_mem_list [regno]
+  reg_equiv_alt_mem_list (regno)
     = alloc_EXPR_LIST (REG_EQUIV, mem,
-                      reg_equiv_alt_mem_list [regno]);
+                      reg_equiv_alt_mem_list (regno));
 }
 \f
 /* Determine if any secondary reloads are needed for loading (if IN_P is
@@ -319,7 +323,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
                       enum machine_mode reload_mode, enum reload_type type,
                       enum insn_code *picode, secondary_reload_info *prev_sri)
 {
-  enum reg_class class = NO_REGS;
+  enum reg_class rclass = NO_REGS;
   enum reg_class scratch_class;
   enum machine_mode mode = reload_mode;
   enum insn_code icode = CODE_FOR_nothing;
@@ -342,9 +346,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
 
   /* If X is a paradoxical SUBREG, use the inner value to determine both the
      mode and object being reloaded.  */
-  if (GET_CODE (x) == SUBREG
-      && (GET_MODE_SIZE (GET_MODE (x))
-         > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
+  if (paradoxical_subreg_p (x))
     {
       x = SUBREG_REG (x);
       reload_mode = GET_MODE (x);
@@ -357,20 +359,21 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
      might be sensitive to the form of the MEM.  */
 
   if (REG_P (x) && REGNO (x) >= FIRST_PSEUDO_REGISTER
-      && reg_equiv_mem[REGNO (x)] != 0)
-    x = reg_equiv_mem[REGNO (x)];
+      && reg_equiv_mem (REGNO (x)))
+    x = reg_equiv_mem (REGNO (x));
 
   sri.icode = CODE_FOR_nothing;
   sri.prev_sri = prev_sri;
-  class = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
-  icode = sri.icode;
+  rclass = (enum reg_class) targetm.secondary_reload (in_p, x, reload_class,
+                                                     reload_mode, &sri);
+  icode = (enum insn_code) sri.icode;
 
   /* If we don't need any secondary registers, done.  */
-  if (class == NO_REGS && icode == CODE_FOR_nothing)
+  if (rclass == NO_REGS && icode == CODE_FOR_nothing)
     return -1;
 
-  if (class != NO_REGS)
-    t_reload = push_secondary_reload (in_p, x, opnum, optional, class,
+  if (rclass != NO_REGS)
+    t_reload = push_secondary_reload (in_p, x, opnum, optional, rclass,
                                      reload_mode, type, &t_icode, &sri);
 
   /* If we will be using an insn, the secondary reload is for a
@@ -392,7 +395,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
         an icode to reload from an intermediate tertiary reload register.
         We should probably have a new field in struct reload to tag a
         chain of scratch operand reloads onto.   */
-      gcc_assert (class == NO_REGS);
+      gcc_assert (rclass == NO_REGS);
 
       scratch_constraint = insn_data[(int) icode].operand[2].constraint;
       gcc_assert (*scratch_constraint == '=');
@@ -404,7 +407,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
                       : REG_CLASS_FROM_CONSTRAINT ((unsigned char) letter,
                                                   scratch_constraint));
 
-      class = scratch_class;
+      rclass = scratch_class;
       mode = insn_data[(int) icode].operand[2].mode;
     }
 
@@ -422,21 +425,22 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
      Allow this when a reload_in/out pattern is being used.  I.e. assume
      that the generated code handles this case.  */
 
-  gcc_assert (!in_p || class != reload_class || icode != CODE_FOR_nothing
+  gcc_assert (!in_p || rclass != reload_class || icode != CODE_FOR_nothing
              || t_icode != CODE_FOR_nothing);
 
   /* See if we can reuse an existing secondary reload.  */
   for (s_reload = 0; s_reload < n_reloads; s_reload++)
     if (rld[s_reload].secondary_p
-       && (reg_class_subset_p (class, rld[s_reload].class)
-           || reg_class_subset_p (rld[s_reload].class, class))
+       && (reg_class_subset_p (rclass, rld[s_reload].rclass)
+           || reg_class_subset_p (rld[s_reload].rclass, rclass))
        && ((in_p && rld[s_reload].inmode == mode)
            || (! in_p && rld[s_reload].outmode == mode))
        && ((in_p && rld[s_reload].secondary_in_reload == t_reload)
            || (! in_p && rld[s_reload].secondary_out_reload == t_reload))
        && ((in_p && rld[s_reload].secondary_in_icode == t_icode)
            || (! in_p && rld[s_reload].secondary_out_icode == t_icode))
-       && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
+       && (small_register_class_p (rclass)
+           || targetm.small_register_classes_for_mode_p (VOIDmode))
        && MERGABLE_RELOADS (secondary_type, rld[s_reload].when_needed,
                             opnum, rld[s_reload].opnum))
       {
@@ -445,8 +449,8 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
        if (! in_p)
          rld[s_reload].outmode = mode;
 
-       if (reg_class_subset_p (class, rld[s_reload].class))
-         rld[s_reload].class = class;
+       if (reg_class_subset_p (rclass, rld[s_reload].rclass))
+         rld[s_reload].rclass = rclass;
 
        rld[s_reload].opnum = MIN (rld[s_reload].opnum, opnum);
        rld[s_reload].optional &= optional;
@@ -454,6 +458,8 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
        if (MERGE_TO_OTHER (secondary_type, rld[s_reload].when_needed,
                            opnum, rld[s_reload].opnum))
          rld[s_reload].when_needed = RELOAD_OTHER;
+
+       break;
       }
 
   if (s_reload == n_reloads)
@@ -465,7 +471,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
         way reloads are output.  */
 
       if (in_p && icode == CODE_FOR_nothing
-         && SECONDARY_MEMORY_NEEDED (class, reload_class, mode))
+         && SECONDARY_MEMORY_NEEDED (rclass, reload_class, mode))
        {
          get_secondary_mem (x, reload_mode, opnum, type);
 
@@ -477,7 +483,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
 
       /* We need to make a new secondary reload for this register class.  */
       rld[s_reload].in = rld[s_reload].out = 0;
-      rld[s_reload].class = class;
+      rld[s_reload].rclass = rclass;
 
       rld[s_reload].inmode = in_p ? mode : VOIDmode;
       rld[s_reload].outmode = ! in_p ? mode : VOIDmode;
@@ -501,7 +507,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
 
 #ifdef SECONDARY_MEMORY_NEEDED
       if (! in_p && icode == CODE_FOR_nothing
-         && SECONDARY_MEMORY_NEEDED (reload_class, class, mode))
+         && SECONDARY_MEMORY_NEEDED (reload_class, rclass, mode))
        get_secondary_mem (x, mode, opnum, type);
 #endif
     }
@@ -513,22 +519,23 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
 /* If a secondary reload is needed, return its class.  If both an intermediate
    register and a scratch register is needed, we return the class of the
    intermediate register.  */
-enum reg_class
-secondary_reload_class (bool in_p, enum reg_class class,
-                       enum machine_mode mode, rtx x)
+reg_class_t
+secondary_reload_class (bool in_p, reg_class_t rclass, enum machine_mode mode,
+                       rtx x)
 {
   enum insn_code icode;
   secondary_reload_info sri;
 
   sri.icode = CODE_FOR_nothing;
   sri.prev_sri = NULL;
-  class = targetm.secondary_reload (in_p, x, class, mode, &sri);
-  icode = sri.icode;
+  rclass
+    = (enum reg_class) targetm.secondary_reload (in_p, x, rclass, mode, &sri);
+  icode = (enum insn_code) sri.icode;
 
   /* If there are no secondary reloads at all, we return NO_REGS.
      If an intermediate register is needed, we return its class.  */
-  if (icode == CODE_FOR_nothing || class != NO_REGS)
-    return class;
+  if (icode == CODE_FOR_nothing || rclass != NO_REGS)
+    return rclass;
 
   /* No intermediate register is needed, but we have a special reload
      pattern, which we assume for now needs a scratch register.  */
@@ -545,7 +552,7 @@ scratch_reload_class (enum insn_code icode)
 {
   const char *scratch_constraint;
   char scratch_letter;
-  enum reg_class class;
+  enum reg_class rclass;
 
   gcc_assert (insn_data[(int) icode].n_operands == 3);
   scratch_constraint = insn_data[(int) icode].operand[2].constraint;
@@ -556,10 +563,10 @@ scratch_reload_class (enum insn_code icode)
   scratch_letter = *scratch_constraint;
   if (scratch_letter == 'r')
     return GENERAL_REGS;
-  class = REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
+  rclass = REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
                                     scratch_constraint);
-  gcc_assert (class != NO_REGS);
-  return class;
+  gcc_assert (rclass != NO_REGS);
+  return rclass;
 }
 \f
 #ifdef SECONDARY_MEMORY_NEEDED
@@ -609,7 +616,8 @@ get_secondary_mem (rtx x ATTRIBUTE_UNUSED, enum machine_mode mode,
      didn't give us a new MEM, make a new one if it isn't valid.  */
 
   loc = eliminate_regs (secondary_memlocs[(int) mode], VOIDmode, NULL_RTX);
-  mem_valid = strict_memory_address_p (mode, XEXP (loc, 0));
+  mem_valid = strict_memory_address_addr_space_p (mode, XEXP (loc, 0),
+                                                 MEM_ADDR_SPACE (loc));
 
   if (! mem_valid && loc == secondary_memlocs[(int) mode])
     loc = copy_rtx (loc);
@@ -658,24 +666,24 @@ find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
                  unsigned int dest_regno ATTRIBUTE_UNUSED)
 {
   int best_cost = -1;
-  int class;
+  int rclass;
   int regno;
   enum reg_class best_class = NO_REGS;
   enum reg_class dest_class ATTRIBUTE_UNUSED = REGNO_REG_CLASS (dest_regno);
   unsigned int best_size = 0;
   int cost;
 
-  for (class = 1; class < N_REG_CLASSES; class++)
+  for (rclass = 1; rclass < N_REG_CLASSES; rclass++)
     {
       int bad = 0;
       int good = 0;
       for (regno = 0; regno < FIRST_PSEUDO_REGISTER - n && ! bad; regno++)
-       if (TEST_HARD_REG_BIT (reg_class_contents[class], regno))
+       if (TEST_HARD_REG_BIT (reg_class_contents[rclass], regno))
          {
            if (HARD_REGNO_MODE_OK (regno, inner))
              {
                good = 1;
-               if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno + n)
+               if (! TEST_HARD_REG_BIT (reg_class_contents[rclass], regno + n)
                    || ! HARD_REGNO_MODE_OK (regno + n, outer))
                  bad = 1;
              }
@@ -683,15 +691,16 @@ find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
 
       if (bad || !good)
        continue;
-      cost = REGISTER_MOVE_COST (outer, class, dest_class);
+      cost = register_move_cost (outer, (enum reg_class) rclass, dest_class);
 
-      if ((reg_class_size[class] > best_size
+      if ((reg_class_size[rclass] > best_size
           && (best_cost < 0 || best_cost >= cost))
          || best_cost > cost)
        {
-         best_class = class;
-         best_size = reg_class_size[class];
-         best_cost = REGISTER_MOVE_COST (outer, class, dest_class);
+         best_class = (enum reg_class) rclass;
+         best_size = reg_class_size[rclass];
+         best_cost = register_move_cost (outer, (enum reg_class) rclass,
+                                         dest_class);
        }
     }
 
@@ -702,14 +711,14 @@ find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
 \f
 /* Return the number of a previously made reload that can be combined with
    a new one, or n_reloads if none of the existing reloads can be used.
-   OUT, CLASS, TYPE and OPNUM are the same arguments as passed to
+   OUT, RCLASS, TYPE and OPNUM are the same arguments as passed to
    push_reload, they determine the kind of the new reload that we try to
    combine.  P_IN points to the corresponding value of IN, which can be
    modified by this function.
    DONT_SHARE is nonzero if we can't share any input-only reload for IN.  */
 
 static int
-find_reusable_reload (rtx *p_in, rtx out, enum reg_class class,
+find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
                      enum reload_type type, int opnum, int dont_share)
 {
   rtx in = *p_in;
@@ -725,23 +734,24 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class class,
      and the other is at worst neutral.
      (A zero compared against anything is neutral.)
 
-     If SMALL_REGISTER_CLASSES, don't use existing reloads unless they are
-     for the same thing since that can cause us to need more reload registers
-     than we otherwise would.  */
+     For targets with small register classes, don't use existing reloads
+     unless they are for the same thing since that can cause us to need
+     more reload registers than we otherwise would.  */
 
   for (i = 0; i < n_reloads; i++)
-    if ((reg_class_subset_p (class, rld[i].class)
-        || reg_class_subset_p (rld[i].class, class))
+    if ((reg_class_subset_p (rclass, rld[i].rclass)
+        || reg_class_subset_p (rld[i].rclass, rclass))
        /* If the existing reload has a register, it must fit our class.  */
        && (rld[i].reg_rtx == 0
-           || TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+           || TEST_HARD_REG_BIT (reg_class_contents[(int) rclass],
                                  true_regnum (rld[i].reg_rtx)))
        && ((in != 0 && MATCHES (rld[i].in, in) && ! dont_share
             && (out == 0 || rld[i].out == 0 || MATCHES (rld[i].out, out)))
            || (out != 0 && MATCHES (rld[i].out, out)
                && (in == 0 || rld[i].in == 0 || MATCHES (rld[i].in, in))))
        && (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
-       && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
+       && (small_register_class_p (rclass)
+           || targetm.small_register_classes_for_mode_p (VOIDmode))
        && MERGABLE_RELOADS (type, rld[i].when_needed, opnum, rld[i].opnum))
       return i;
 
@@ -751,12 +761,12 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class class,
      the preincrementation as happening before any ref in this insn
      to that register.  */
   for (i = 0; i < n_reloads; i++)
-    if ((reg_class_subset_p (class, rld[i].class)
-        || reg_class_subset_p (rld[i].class, class))
+    if ((reg_class_subset_p (rclass, rld[i].rclass)
+        || reg_class_subset_p (rld[i].rclass, rclass))
        /* If the existing reload has a register, it must fit our
           class.  */
        && (rld[i].reg_rtx == 0
-           || TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+           || TEST_HARD_REG_BIT (reg_class_contents[(int) rclass],
                                  true_regnum (rld[i].reg_rtx)))
        && out == 0 && rld[i].out == 0 && rld[i].in != 0
        && ((REG_P (in)
@@ -766,7 +776,8 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class class,
                && GET_RTX_CLASS (GET_CODE (in)) == RTX_AUTOINC
                && MATCHES (XEXP (in, 0), rld[i].in)))
        && (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
-       && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
+       && (small_register_class_p (rclass)
+           || targetm.small_register_classes_for_mode_p (VOIDmode))
        && MERGABLE_RELOADS (type, rld[i].when_needed,
                             opnum, rld[i].opnum))
       {
@@ -779,39 +790,39 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class class,
   return n_reloads;
 }
 
-/* Return nonzero if X is a SUBREG which will require reloading of its
-   SUBREG_REG expression.  */
+/* Return true if X is a SUBREG that will need reloading of its SUBREG_REG
+   expression.  MODE is the mode that X will be used in.  OUTPUT is true if
+   the function is invoked for the output part of an enclosing reload.  */
 
-static int
-reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, int output)
+static bool
+reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, bool output)
 {
   rtx inner;
 
   /* Only SUBREGs are problematical.  */
   if (GET_CODE (x) != SUBREG)
-    return 0;
+    return false;
 
   inner = SUBREG_REG (x);
 
-  /* If INNER is a constant or PLUS, then INNER must be reloaded.  */
+  /* If INNER is a constant or PLUS, then INNER will need reloading.  */
   if (CONSTANT_P (inner) || GET_CODE (inner) == PLUS)
-    return 1;
+    return true;
 
-  /* If INNER is not a hard register, then INNER will not need to
-     be reloaded.  */
-  if (!REG_P (inner)
-      || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
-    return 0;
+  /* If INNER is not a hard register, then INNER will not need reloading.  */
+  if (!(REG_P (inner) && HARD_REGISTER_P (inner)))
+    return false;
 
   /* If INNER is not ok for MODE, then INNER will need reloading.  */
-  if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
-    return 1;
-
-  /* If the outer part is a word or smaller, INNER larger than a
-     word and the number of regs for INNER is not the same as the
-     number of words in INNER, then INNER will need reloading.  */
-  return (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
-         && output
+  if (!HARD_REGNO_MODE_OK (subreg_regno (x), mode))
+    return true;
+
+  /* If this is for an output, and the outer part is a word or smaller,
+     INNER is larger than a word and the number of registers in INNER is
+     not the same as the number of words in INNER, then INNER will need
+     reloading (with an in-out reload).  */
+  return (output
+         && GET_MODE_SIZE (mode) <= UNITS_PER_WORD
          && GET_MODE_SIZE (GET_MODE (inner)) > UNITS_PER_WORD
          && ((GET_MODE_SIZE (GET_MODE (inner)) / UNITS_PER_WORD)
              != (int) hard_regno_nregs[REGNO (inner)][GET_MODE (inner)]));
@@ -876,7 +887,7 @@ can_reload_into (rtx in, int regno, enum machine_mode mode)
    If IN and OUT are both nonzero, it means the same register must be used
    to reload both IN and OUT.
 
-   CLASS is a register class required for the reloaded data.
+   RCLASS is a register class required for the reloaded data.
    INMODE is the machine mode that the instruction requires
    for the reg that replaces IN and OUTMODE is likewise for OUT.
 
@@ -902,14 +913,16 @@ 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 class, enum machine_mode inmode,
+            enum reg_class rclass, enum machine_mode inmode,
             enum machine_mode outmode, int strict_low, int optional,
             int opnum, enum reload_type type)
 {
   int i;
   int dont_share = 0;
   int dont_remove_subreg = 0;
+#ifdef LIMIT_RELOAD_CLASS
   rtx *in_subreg_loc = 0, *out_subreg_loc = 0;
+#endif
   int secondary_in_reload = -1, secondary_out_reload = -1;
   enum insn_code secondary_in_icode = CODE_FOR_nothing;
   enum insn_code secondary_out_icode = CODE_FOR_nothing;
@@ -935,7 +948,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 
       gcc_assert (regno < FIRST_PSEUDO_REGISTER
                  || reg_renumber[regno] >= 0
-                 || reg_equiv_constant[regno] == NULL_RTX);
+                 || reg_equiv_constant (regno) == NULL_RTX);
     }
 
   /* reg_equiv_constant only contains constants which are obviously
@@ -948,7 +961,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 
       gcc_assert (regno < FIRST_PSEUDO_REGISTER
                  || reg_renumber[regno] >= 0
-                 || reg_equiv_constant[regno] == NULL_RTX);
+                 || reg_equiv_constant (regno) == NULL_RTX);
     }
 
   /* If we have a read-write operand with an address side-effect,
@@ -976,9 +989,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
      For machines that extend byte loads, do this for any SUBREG of a pseudo
      where both M1 and M2 are a word or smaller, M1 is wider than M2, and
      M2 is an integral mode that gets extended when loaded.
-     Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
-     either M1 is not valid for R or M2 is wider than a word but we only
-     need one word to store an M2-sized quantity in R.
+     Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R
+     where either M1 is not valid for R or M2 is wider than a word but we
+     only need one register to store an M2-sized quantity in R.
      (However, if OUT is nonzero, we need to reload the reg *and*
      the subreg, so do nothing here, and let following statement handle it.)
 
@@ -986,7 +999,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
      we can't handle it here because CONST_INT does not indicate a mode.
 
      Similarly, we must reload the inside expression if we have a
-     STRICT_LOW_PART (presumably, in == out in the cas).
+     STRICT_LOW_PART (presumably, in == out in this case).
 
      Also reload the inner expression if it does not require a secondary
      reload but the SUBREG does.
@@ -1001,28 +1014,29 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
   if (in != 0 && GET_CODE (in) == SUBREG
       && (subreg_lowpart_p (in) || strict_low)
 #ifdef CANNOT_CHANGE_MODE_CLASS
-      && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, class)
+      && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, rclass)
 #endif
+      && contains_reg_of_mode[(int) rclass][(int) GET_MODE (SUBREG_REG (in))]
       && (CONSTANT_P (SUBREG_REG (in))
          || GET_CODE (SUBREG_REG (in)) == PLUS
          || strict_low
          || (((REG_P (SUBREG_REG (in))
                && REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER)
               || MEM_P (SUBREG_REG (in)))
-             && ((GET_MODE_SIZE (inmode)
-                  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
+             && ((GET_MODE_PRECISION (inmode)
+                  > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
 #ifdef LOAD_EXTEND_OP
                  || (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
                      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
                          <= UNITS_PER_WORD)
-                     && (GET_MODE_SIZE (inmode)
-                         > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
+                     && (GET_MODE_PRECISION (inmode)
+                         > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
                      && INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))
                      && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != UNKNOWN)
 #endif
 #ifdef WORD_REGISTER_OPERATIONS
-                 || ((GET_MODE_SIZE (inmode)
-                      < GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
+                 || ((GET_MODE_PRECISION (inmode)
+                      < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
                      && ((GET_MODE_SIZE (inmode) - 1) / UNITS_PER_WORD ==
                          ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) - 1)
                           / UNITS_PER_WORD)))
@@ -1041,8 +1055,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
                       != (int) hard_regno_nregs[REGNO (SUBREG_REG (in))]
                                                [GET_MODE (SUBREG_REG (in))]))
                  || ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode)))
-         || (secondary_reload_class (1, class, inmode, in) != NO_REGS
-             && (secondary_reload_class (1, class, GET_MODE (SUBREG_REG (in)),
+         || (secondary_reload_class (1, rclass, inmode, in) != NO_REGS
+             && (secondary_reload_class (1, rclass, GET_MODE (SUBREG_REG (in)),
                                          SUBREG_REG (in))
                  == NO_REGS))
 #ifdef CANNOT_CHANGE_MODE_CLASS
@@ -1053,7 +1067,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 #endif
          ))
     {
+#ifdef LIMIT_RELOAD_CLASS
       in_subreg_loc = inloc;
+#endif
       inloc = &SUBREG_REG (in);
       in = *inloc;
 #if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
@@ -1065,19 +1081,18 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
       inmode = GET_MODE (in);
     }
 
-  /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
-     either M1 is not valid for R or M2 is wider than a word but we only
-     need one word to store an M2-sized quantity in R.
+  /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R
+     where M1 is not valid for R if it was not handled by the code above.
+
+     Similar issue for (SUBREG constant ...) if it was not handled by the
+     code above.  This can happen if SUBREG_BYTE != 0.
 
      However, we must reload the inner reg *as well as* the subreg in
      that case.  */
 
-  /* Similar issue for (SUBREG constant ...) if it was not handled by the
-     code above.  This can happen if SUBREG_BYTE != 0.  */
-
-  if (in != 0 && reload_inner_reg_of_subreg (in, inmode, 0))
+  if (in != 0 && reload_inner_reg_of_subreg (in, inmode, false))
     {
-      enum reg_class in_class = class;
+      enum reg_class in_class = rclass;
 
       if (REG_P (SUBREG_REG (in)))
        in_class
@@ -1100,25 +1115,26 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 
   /* Similarly for paradoxical and problematical SUBREGs on the output.
      Note that there is no reason we need worry about the previous value
-     of SUBREG_REG (out); even if wider than out,
-     storing in a subreg is entitled to clobber it all
-     (except in the case of STRICT_LOW_PART,
-     and in that case the constraint should label it input-output.)  */
+     of SUBREG_REG (out); even if wider than out, storing in a subreg is
+     entitled to clobber it all (except in the case of a word mode subreg
+     or of a STRICT_LOW_PART, in that latter case the constraint should
+     label it input-output.)  */
   if (out != 0 && GET_CODE (out) == SUBREG
       && (subreg_lowpart_p (out) || strict_low)
 #ifdef CANNOT_CHANGE_MODE_CLASS
-      && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, class)
+      && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, rclass)
 #endif
+      && contains_reg_of_mode[(int) rclass][(int) GET_MODE (SUBREG_REG (out))]
       && (CONSTANT_P (SUBREG_REG (out))
          || strict_low
          || (((REG_P (SUBREG_REG (out))
                && REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER)
               || MEM_P (SUBREG_REG (out)))
-             && ((GET_MODE_SIZE (outmode)
-                  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
+             && ((GET_MODE_PRECISION (outmode)
+                  > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
 #ifdef WORD_REGISTER_OPERATIONS
-                 || ((GET_MODE_SIZE (outmode)
-                      < GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
+                 || ((GET_MODE_PRECISION (outmode)
+                      < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
                      && ((GET_MODE_SIZE (outmode) - 1) / UNITS_PER_WORD ==
                          ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - 1)
                           / UNITS_PER_WORD)))
@@ -1126,16 +1142,14 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
                  ))
          || (REG_P (SUBREG_REG (out))
              && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
-             && ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
-                  && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
-                      > UNITS_PER_WORD)
-                  && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
-                       / UNITS_PER_WORD)
-                      != (int) hard_regno_nregs[REGNO (SUBREG_REG (out))]
-                                               [GET_MODE (SUBREG_REG (out))]))
-                 || ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
-         || (secondary_reload_class (0, class, outmode, out) != NO_REGS
-             && (secondary_reload_class (0, class, GET_MODE (SUBREG_REG (out)),
+             /* The case of a word mode subreg
+                is handled differently in the following statement.  */
+             && ! (GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
+                   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
+                       > UNITS_PER_WORD))
+             && ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode))
+         || (secondary_reload_class (0, rclass, outmode, out) != NO_REGS
+             && (secondary_reload_class (0, rclass, GET_MODE (SUBREG_REG (out)),
                                          SUBREG_REG (out))
                  == NO_REGS))
 #ifdef CANNOT_CHANGE_MODE_CLASS
@@ -1147,7 +1161,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 #endif
          ))
     {
+#ifdef LIMIT_RELOAD_CLASS
       out_subreg_loc = outloc;
+#endif
       outloc = &SUBREG_REG (out);
       out = *outloc;
 #if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
@@ -1158,31 +1174,32 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
       outmode = GET_MODE (out);
     }
 
-  /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
-     either M1 is not valid for R or M2 is wider than a word but we only
-     need one word to store an M2-sized quantity in R.
+  /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R
+     where either M1 is not valid for R or M2 is wider than a word but we
+     only need one register to store an M2-sized quantity in R.
 
      However, we must reload the inner reg *as well as* the subreg in
-     that case.  In this case, the inner reg is an in-out reload.  */
+     that case and the inner reg is an in-out reload.  */
 
-  if (out != 0 && reload_inner_reg_of_subreg (out, outmode, 1))
+  if (out != 0 && reload_inner_reg_of_subreg (out, outmode, true))
     {
+      enum reg_class in_out_class
+       = find_valid_class (outmode, GET_MODE (SUBREG_REG (out)),
+                           subreg_regno_offset (REGNO (SUBREG_REG (out)),
+                                                GET_MODE (SUBREG_REG (out)),
+                                                SUBREG_BYTE (out),
+                                                GET_MODE (out)),
+                           REGNO (SUBREG_REG (out)));
+
       /* This relies on the fact that emit_reload_insns outputs the
         instructions for output reloads of type RELOAD_OTHER in reverse
         order of the reloads.  Thus if the outer reload is also of type
         RELOAD_OTHER, we are guaranteed that this inner reload will be
         output after the outer reload.  */
-      dont_remove_subreg = 1;
       push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
-                  &SUBREG_REG (out),
-                  find_valid_class (outmode, GET_MODE (SUBREG_REG (out)),
-                                    subreg_regno_offset (REGNO (SUBREG_REG (out)),
-                                                         GET_MODE (SUBREG_REG (out)),
-                                                         SUBREG_BYTE (out),
-                                                         GET_MODE (out)),
-                                    REGNO (SUBREG_REG (out))),
-                  VOIDmode, VOIDmode, 0, 0,
-                  opnum, RELOAD_OTHER);
+                  &SUBREG_REG (out), in_out_class, VOIDmode, VOIDmode,
+                  0, 0, opnum, RELOAD_OTHER);
+      dont_remove_subreg = 1;
     }
 
   /* If IN appears in OUT, we can't share any input-only reload for IN.  */
@@ -1209,21 +1226,20 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
   /* Narrow down the class of register wanted if that is
      desirable on this machine for efficiency.  */
   {
-    enum reg_class preferred_class = class;
+    reg_class_t preferred_class = rclass;
 
     if (in != 0)
-      preferred_class = PREFERRED_RELOAD_CLASS (in, class);
+      preferred_class = targetm.preferred_reload_class (in, rclass);
 
-  /* Output reloads may need analogous treatment, different in detail.  */
-#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
+    /* Output reloads may need analogous treatment, different in detail.  */
     if (out != 0)
-      preferred_class = PREFERRED_OUTPUT_RELOAD_CLASS (out, preferred_class);
-#endif
+      preferred_class
+       = targetm.preferred_output_reload_class (out, preferred_class);
 
     /* Discard what the target said if we cannot do it.  */
     if (preferred_class != NO_REGS
        || (optional && type == RELOAD_FOR_OUTPUT))
-      class = preferred_class;
+      rclass = (enum reg_class) preferred_class;
   }
 
   /* Make sure we use a class that can handle the actual pseudo
@@ -1232,14 +1248,14 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
      can handle SImode, QImode needs a smaller class.  */
 #ifdef LIMIT_RELOAD_CLASS
   if (in_subreg_loc)
-    class = LIMIT_RELOAD_CLASS (inmode, class);
+    rclass = LIMIT_RELOAD_CLASS (inmode, rclass);
   else if (in != 0 && GET_CODE (in) == SUBREG)
-    class = LIMIT_RELOAD_CLASS (GET_MODE (SUBREG_REG (in)), class);
+    rclass = LIMIT_RELOAD_CLASS (GET_MODE (SUBREG_REG (in)), rclass);
 
   if (out_subreg_loc)
-    class = LIMIT_RELOAD_CLASS (outmode, class);
+    rclass = LIMIT_RELOAD_CLASS (outmode, rclass);
   if (out != 0 && GET_CODE (out) == SUBREG)
-    class = LIMIT_RELOAD_CLASS (GET_MODE (SUBREG_REG (out)), class);
+    rclass = LIMIT_RELOAD_CLASS (GET_MODE (SUBREG_REG (out)), rclass);
 #endif
 
   /* Verify that this class is at least possible for the mode that
@@ -1263,7 +1279,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
        }
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        if (HARD_REGNO_MODE_OK (i, mode)
-           && in_hard_reg_set_p (reg_class_contents[(int) class], mode, i))
+           && in_hard_reg_set_p (reg_class_contents[(int) rclass], mode, i))
          break;
       if (i == FIRST_PSEUDO_REGISTER)
        {
@@ -1280,7 +1296,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
             Returning zero here ought to be safe as we take care in
             find_reloads to not process the reloads when instruction was
             replaced by USE.  */
-           
+
          return 0;
        }
     }
@@ -1288,10 +1304,10 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
   /* Optional output reloads are always OK even if we have no register class,
      since the function of these reloads is only to have spill_reg_store etc.
      set, so that the storing insn can be deleted later.  */
-  gcc_assert (class != NO_REGS
+  gcc_assert (rclass != NO_REGS
              || (optional != 0 && type == RELOAD_FOR_OUTPUT));
 
-  i = find_reusable_reload (&in, out, class, type, opnum, dont_share);
+  i = find_reusable_reload (&in, out, rclass, type, opnum, dont_share);
 
   if (i == n_reloads)
     {
@@ -1301,11 +1317,11 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 
       if (in != 0)
        secondary_in_reload
-         = push_secondary_reload (1, in, opnum, optional, class, inmode, type,
+         = push_secondary_reload (1, in, opnum, optional, rclass, inmode, type,
                                   &secondary_in_icode, NULL);
       if (out != 0 && GET_CODE (out) != SCRATCH)
        secondary_out_reload
-         = push_secondary_reload (0, out, opnum, optional, class, outmode,
+         = push_secondary_reload (0, out, opnum, optional, rclass, outmode,
                                   type, &secondary_out_icode, NULL);
 
       /* We found no existing reload suitable for re-use.
@@ -1318,14 +1334,14 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
              || (GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))))
          && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
          && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
-                                     class, inmode))
+                                     rclass, inmode))
        get_secondary_mem (in, inmode, opnum, type);
 #endif
 
       i = n_reloads;
       rld[i].in = in;
       rld[i].out = out;
-      rld[i].class = class;
+      rld[i].rclass = rclass;
       rld[i].inmode = inmode;
       rld[i].outmode = outmode;
       rld[i].reg_rtx = 0;
@@ -1349,7 +1365,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
           && (REG_P (out)
              || (GET_CODE (out) == SUBREG && REG_P (SUBREG_REG (out))))
          && reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
-         && SECONDARY_MEMORY_NEEDED (class,
+         && SECONDARY_MEMORY_NEEDED (rclass,
                                      REGNO_REG_CLASS (reg_or_subregno (out)),
                                      outmode))
        get_secondary_mem (out, outmode, opnum, type);
@@ -1401,16 +1417,39 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
              else
                remove_address_replacements (rld[i].in);
            }
-         rld[i].in = in;
-         rld[i].in_reg = in_reg;
+         /* When emitting reloads we don't necessarily look at the in-
+            and outmode, but also directly at the operands (in and out).
+            So we can't simply overwrite them with whatever we have found
+            for this (to-be-merged) reload, we have to "merge" that too.
+            Reusing another reload already verified that we deal with the
+            same operands, just possibly in different modes.  So we
+            overwrite the operands only when the new mode is larger.
+            See also PR33613.  */
+         if (!rld[i].in
+             || GET_MODE_SIZE (GET_MODE (in))
+                  > GET_MODE_SIZE (GET_MODE (rld[i].in)))
+           rld[i].in = in;
+         if (!rld[i].in_reg
+             || (in_reg
+                 && GET_MODE_SIZE (GET_MODE (in_reg))
+                    > GET_MODE_SIZE (GET_MODE (rld[i].in_reg))))
+           rld[i].in_reg = in_reg;
        }
       if (out != 0)
        {
-         rld[i].out = out;
-         rld[i].out_reg = outloc ? *outloc : 0;
+         if (!rld[i].out
+             || (out
+                 && GET_MODE_SIZE (GET_MODE (out))
+                    > GET_MODE_SIZE (GET_MODE (rld[i].out))))
+           rld[i].out = out;
+         if (outloc
+             && (!rld[i].out_reg
+                 || GET_MODE_SIZE (GET_MODE (*outloc))
+                    > GET_MODE_SIZE (GET_MODE (rld[i].out_reg))))
+           rld[i].out_reg = *outloc;
        }
-      if (reg_class_subset_p (class, rld[i].class))
-       rld[i].class = class;
+      if (reg_class_subset_p (rclass, rld[i].rclass))
+       rld[i].rclass = rclass;
       rld[i].optional &= optional;
       if (MERGE_TO_OTHER (type, rld[i].when_needed,
                          opnum, rld[i].opnum))
@@ -1456,7 +1495,6 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
        {
          struct replacement *r = &replacements[n_replacements++];
          r->what = i;
-         r->subreg_loc = in_subreg_loc;
          r->where = inloc;
          r->mode = inmode;
        }
@@ -1465,7 +1503,6 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
          struct replacement *r = &replacements[n_replacements++];
          r->what = i;
          r->where = outloc;
-         r->subreg_loc = out_subreg_loc;
          r->mode = outmode;
        }
     }
@@ -1482,7 +1519,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
     {
       rld[i].reg_rtx = find_dummy_reload (in, out, inloc, outloc,
                                          inmode, outmode,
-                                         rld[i].class, i,
+                                         rld[i].rclass, i,
                                          earlyclobber_operand_p (out));
 
       /* If the outgoing register already contains the same value
@@ -1491,7 +1528,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
         value for the incoming operand (same as outgoing one).  */
       if (rld[i].reg_rtx == out
          && (REG_P (in) || CONSTANT_P (in))
-         && 0 != find_equiv_reg (in, this_insn, 0, REGNO (out),
+         && 0 != find_equiv_reg (in, this_insn, NO_REGS, REGNO (out),
                                  static_reload_reg_p, i, inmode))
        rld[i].in = out;
     }
@@ -1524,8 +1561,8 @@ 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_LIVE_OUT (ENTRY_BLOCK_PTR),
-                                  ORIGINAL_REGNO (XEXP (note, 0)))
+               || (! bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
+                                   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,
@@ -1559,7 +1596,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 
            for (offs = 0; offs < nregs; offs++)
              if (fixed_regs[regno + offs]
-                 || ! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+                 || ! TEST_HARD_REG_BIT (reg_class_contents[(int) rclass],
                                          regno + offs))
                break;
 
@@ -1594,7 +1631,6 @@ push_replacement (rtx *loc, int reloadnum, enum machine_mode mode)
       struct replacement *r = &replacements[n_replacements++];
       r->what = reloadnum;
       r->where = loc;
-      r->subreg_loc = 0;
       r->mode = mode;
     }
 }
@@ -1728,9 +1764,9 @@ combine_reloads (void)
        && rld[i].when_needed != RELOAD_FOR_OUTPUT_ADDRESS
        && rld[i].when_needed != RELOAD_FOR_OUTADDR_ADDRESS
        && rld[i].when_needed != RELOAD_OTHER
-       && (CLASS_MAX_NREGS (rld[i].class, rld[i].inmode)
-           == CLASS_MAX_NREGS (rld[output_reload].class,
-                               rld[output_reload].outmode))
+       && (ira_reg_class_max_nregs [(int)rld[i].rclass][(int) rld[i].inmode]
+           == ira_reg_class_max_nregs [(int) rld[output_reload].rclass]
+                                      [(int) rld[output_reload].outmode])
        && rld[i].inc == 0
        && rld[i].reg_rtx == 0
 #ifdef SECONDARY_MEMORY_NEEDED
@@ -1741,12 +1777,12 @@ combine_reloads (void)
            || rtx_equal_p (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum],
                            secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum]))
 #endif
-       && (SMALL_REGISTER_CLASSES
-           ? (rld[i].class == rld[output_reload].class)
-           : (reg_class_subset_p (rld[i].class,
-                                  rld[output_reload].class)
-              || reg_class_subset_p (rld[output_reload].class,
-                                     rld[i].class)))
+       && (targetm.small_register_classes_for_mode_p (VOIDmode)
+           ? (rld[i].rclass == rld[output_reload].rclass)
+           : (reg_class_subset_p (rld[i].rclass,
+                                  rld[output_reload].rclass)
+              || reg_class_subset_p (rld[output_reload].rclass,
+                                     rld[i].rclass)))
        && (MATCHES (rld[i].in, rld[output_reload].out)
            /* Args reversed because the first arg seems to be
               the one that we imagine being modified
@@ -1764,8 +1800,8 @@ combine_reloads (void)
                                                             rld[output_reload].out))))
        && ! reload_inner_reg_of_subreg (rld[i].in, rld[i].inmode,
                                         rld[i].when_needed != RELOAD_FOR_INPUT)
-       && (reg_class_size[(int) rld[i].class]
-           || SMALL_REGISTER_CLASSES)
+       && (reg_class_size[(int) rld[i].rclass]
+           || targetm.small_register_classes_for_mode_p (VOIDmode))
        /* We will allow making things slightly worse by combining an
           input and an output, but no worse than that.  */
        && (rld[i].when_needed == RELOAD_FOR_INPUT
@@ -1797,9 +1833,9 @@ combine_reloads (void)
            = secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum];
 #endif
        /* If required, minimize the register class.  */
-       if (reg_class_subset_p (rld[output_reload].class,
-                               rld[i].class))
-         rld[i].class = rld[output_reload].class;
+       if (reg_class_subset_p (rld[output_reload].rclass,
+                               rld[i].rclass))
+         rld[i].rclass = rld[output_reload].rclass;
 
        /* Transfer all replacements from the old reload to the combined.  */
        for (j = 0; j < n_replacements; j++)
@@ -1833,7 +1869,7 @@ combine_reloads (void)
                                                rld[output_reload].out)
        && (regno = REGNO (XEXP (note, 0))) < FIRST_PSEUDO_REGISTER
        && HARD_REGNO_MODE_OK (regno, rld[output_reload].outmode)
-       && TEST_HARD_REG_BIT (reg_class_contents[(int) rld[output_reload].class],
+       && TEST_HARD_REG_BIT (reg_class_contents[(int) rld[output_reload].rclass],
                              regno)
        && (hard_regno_nregs[regno][rld[output_reload].outmode]
            <= hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))])
@@ -1841,10 +1877,10 @@ combine_reloads (void)
           won't want this register.  */
        && ((secondary_out = rld[output_reload].secondary_out_reload) == -1
            || (!(TEST_HARD_REG_BIT
-                 (reg_class_contents[(int) rld[secondary_out].class], regno))
+                 (reg_class_contents[(int) rld[secondary_out].rclass], regno))
                && ((secondary_out = rld[secondary_out].secondary_out_reload) == -1
                    || !(TEST_HARD_REG_BIT
-                        (reg_class_contents[(int) rld[secondary_out].class],
+                        (reg_class_contents[(int) rld[secondary_out].rclass],
                          regno)))))
        && !fixed_regs[regno]
        /* Check that a former pseudo is valid; see find_dummy_reload.  */
@@ -1865,7 +1901,7 @@ combine_reloads (void)
    If so, return the register rtx that proves acceptable.
 
    INLOC and OUTLOC are locations where IN and OUT appear in the insn.
-   CLASS is the register class required for the reload.
+   RCLASS is the register class required for the reload.
 
    If FOR_REAL is >= 0, it is the number of the reload,
    and in some cases when it can be discovered that OUT doesn't need
@@ -1882,7 +1918,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,
-                  enum reg_class class, int for_real, int earlyclobber)
+                  reg_class_t rclass, int for_real, int earlyclobber)
 {
   rtx in = real_in;
   rtx out = real_out;
@@ -1925,9 +1961,9 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
   /* Narrow down the reg class, the same way push_reload will;
      otherwise we might find a dummy now, but push_reload won't.  */
   {
-    enum reg_class preferred_class = PREFERRED_RELOAD_CLASS (in, class);
+    reg_class_t preferred_class = targetm.preferred_reload_class (in, rclass);
     if (preferred_class != NO_REGS)
-      class = preferred_class;
+      rclass = (enum reg_class) preferred_class;
   }
 
   /* See if OUT will do.  */
@@ -1958,7 +1994,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
          unsigned int i;
 
          for (i = 0; i < nwords; i++)
-           if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+           if (! TEST_HARD_REG_BIT (reg_class_contents[(int) rclass],
                                     regno + i))
              break;
 
@@ -2002,7 +2038,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_LIVE_OUT (ENTRY_BLOCK_PTR),
+          || (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
                             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
@@ -2026,7 +2062,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
          unsigned int i;
 
          for (i = 0; i < nwords; i++)
-           if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+           if (! TEST_HARD_REG_BIT (reg_class_contents[(int) rclass],
                                     regno + i))
              break;
 
@@ -2102,18 +2138,24 @@ hard_reg_set_here_p (unsigned int beg_regno, unsigned int end_regno, rtx x)
   return 0;
 }
 
-/* Return 1 if ADDR is a valid memory address for mode MODE,
-   and check that each pseudo reg has the proper kind of
-   hard reg.  */
+/* Return 1 if ADDR is a valid memory address for mode MODE
+   in address space AS, and check that each pseudo reg has the
+   proper kind of hard reg.  */
 
 int
-strict_memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
+strict_memory_address_addr_space_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+                                   rtx addr, addr_space_t as)
 {
+#ifdef GO_IF_LEGITIMATE_ADDRESS
+  gcc_assert (ADDR_SPACE_GENERIC_P (as));
   GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
   return 0;
 
  win:
   return 1;
+#else
+  return targetm.addr_space.legitimate_address_p (mode, addr, 1, as);
+#endif
 }
 \f
 /* Like rtx_equal_p except that it allows a REG and a SUBREG to match
@@ -2173,15 +2215,15 @@ operands_match_p (rtx x, rtx y)
       else
        j = REGNO (y);
 
-      /* On a WORDS_BIG_ENDIAN machine, point to the last register of a
+      /* On a REG_WORDS_BIG_ENDIAN machine, point to the last register of a
         multiple hard register group of scalar integer registers, so that
         for example (reg:DI 0) and (reg:SI 1) will be considered the same
         register.  */
-      if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
+      if (REG_WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
          && SCALAR_INT_MODE_P (GET_MODE (x))
          && i < FIRST_PSEUDO_REGISTER)
        i += hard_regno_nregs[i][GET_MODE (x)] - 1;
-      if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (y)) > UNITS_PER_WORD
+      if (REG_WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (y)) > UNITS_PER_WORD
          && SCALAR_INT_MODE_P (GET_MODE (y))
          && j < FIRST_PSEUDO_REGISTER)
        j += hard_regno_nregs[j][GET_MODE (y)] - 1;
@@ -2216,6 +2258,10 @@ operands_match_p (rtx x, rtx y)
   if (GET_MODE (x) != GET_MODE (y))
     return 0;
 
+  /* MEMs refering to different address space are not equivalent.  */
+  if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
+    return 0;
+
   switch (code)
     {
     case CONST_INT:
@@ -2310,7 +2356,7 @@ decompose (rtx x)
       {
        rtx base = NULL_RTX, offset = 0;
        rtx addr = XEXP (x, 0);
-       
+
        if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC
            || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
          {
@@ -2320,7 +2366,7 @@ decompose (rtx x)
            val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
            return val;
          }
-       
+
        if (GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
          {
            if (GET_CODE (XEXP (addr, 1)) == PLUS
@@ -2334,7 +2380,7 @@ decompose (rtx x)
                return val;
              }
          }
-       
+
        if (GET_CODE (addr) == CONST)
          {
            addr = XEXP (addr, 0);
@@ -2353,7 +2399,7 @@ decompose (rtx x)
                offset = XEXP (addr, 1);
              }
          }
-       
+
        if (offset == 0)
          {
            base = addr;
@@ -2363,12 +2409,12 @@ decompose (rtx x)
          offset = XEXP (offset, 0);
        if (GET_CODE (offset) == PLUS)
          {
-           if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
+           if (CONST_INT_P (XEXP (offset, 0)))
              {
                base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
                offset = XEXP (offset, 0);
              }
-           else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
+           else if (CONST_INT_P (XEXP (offset, 1)))
              {
                base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
                offset = XEXP (offset, 1);
@@ -2379,23 +2425,23 @@ decompose (rtx x)
                offset = const0_rtx;
              }
          }
-       else if (GET_CODE (offset) != CONST_INT)
+       else if (!CONST_INT_P (offset))
          {
            base = gen_rtx_PLUS (GET_MODE (base), base, offset);
            offset = const0_rtx;
          }
-       
+
        if (all_const && GET_CODE (base) == PLUS)
          base = gen_rtx_CONST (GET_MODE (base), base);
-       
-       gcc_assert (GET_CODE (offset) == CONST_INT);
-       
+
+       gcc_assert (CONST_INT_P (offset));
+
        val.start = INTVAL (offset);
        val.end = val.start + GET_MODE_SIZE (GET_MODE (x));
        val.base = base;
       }
       break;
-      
+
     case REG:
       val.reg_flag = 1;
       val.start = true_regnum (x);
@@ -2521,12 +2567,12 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   int noperands;
   /* These start out as the constraints for the insn
      and they are chewed up as we consider alternatives.  */
-  char *constraints[MAX_RECOG_OPERANDS];
+  const char *constraints[MAX_RECOG_OPERANDS];
   /* These are the preferred classes for an operand, or NO_REGS if it isn't
      a register.  */
   enum reg_class preferred_class[MAX_RECOG_OPERANDS];
   char pref_or_nothing[MAX_RECOG_OPERANDS];
-  /* Nonzero for a MEM operand whose entire address needs a reload. 
+  /* Nonzero for a MEM operand whose entire address needs a reload.
      May be -1 to indicate the entire address may or may not need a reload.  */
   int address_reloaded[MAX_RECOG_OPERANDS];
   /* Nonzero for an address operand that needs to be completely reloaded.
@@ -2540,14 +2586,14 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   enum reload_usage { RELOAD_READ, RELOAD_READ_WRITE, RELOAD_WRITE } modified[MAX_RECOG_OPERANDS];
   int no_input_reloads = 0, no_output_reloads = 0;
   int n_alternatives;
-  int this_alternative[MAX_RECOG_OPERANDS];
+  reg_class_t this_alternative[MAX_RECOG_OPERANDS];
   char this_alternative_match_win[MAX_RECOG_OPERANDS];
   char this_alternative_win[MAX_RECOG_OPERANDS];
   char this_alternative_offmemok[MAX_RECOG_OPERANDS];
   char this_alternative_earlyclobber[MAX_RECOG_OPERANDS];
   int this_alternative_matches[MAX_RECOG_OPERANDS];
   int swapped;
-  int goal_alternative[MAX_RECOG_OPERANDS];
+  reg_class_t goal_alternative[MAX_RECOG_OPERANDS];
   int this_alternative_number;
   int goal_alternative_number = 0;
   int operand_reloadnum[MAX_RECOG_OPERANDS];
@@ -2609,7 +2655,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
       && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER
       && REG_P (SET_SRC (body))
       && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
-      && REGISTER_MOVE_COST (GET_MODE (SET_SRC (body)),
+      && register_move_cost (GET_MODE (SET_SRC (body)),
                             REGNO_REG_CLASS (REGNO (SET_SRC (body))),
                             REGNO_REG_CLASS (REGNO (SET_DEST (body)))) == 2)
     return 0;
@@ -2628,7 +2674,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
   memcpy (operand_mode, recog_data.operand_mode,
          noperands * sizeof (enum machine_mode));
-  memcpy (constraints, recog_data.constraints, noperands * sizeof (char *));
+  memcpy (constraints, recog_data.constraints,
+         noperands * sizeof (const char *));
 
   commutative = -1;
 
@@ -2639,8 +2686,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
   for (i = 0; i < noperands; i++)
     {
-      char *p;
+      const char *p;
       int c;
+      char *end;
 
       substed_operand[i] = recog_data.operand[i];
       p = constraints[i];
@@ -2684,7 +2732,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
            case '0': case '1': case '2': case '3': case '4':
            case '5': case '6': case '7': case '8': case '9':
              {
-               c = strtoul (p - 1, &p, 10);
+               c = strtoul (p - 1, &end, 10);
+               p = end;
 
                operands_match[c][i]
                  = operands_match_p (recog_data.operand[c],
@@ -2773,6 +2822,13 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
          /* Address operands are reloaded in their existing mode,
             no matter what is specified in the machine description.  */
          operand_mode[i] = GET_MODE (recog_data.operand[i]);
+
+         /* If the address is a single CONST_INT pick address mode
+            instead otherwise we will later not know in which mode
+            the reload should be performed.  */
+         if (operand_mode[i] == VOIDmode)
+           operand_mode[i] = Pmode;
+
        }
       else if (code == MEM)
        {
@@ -2806,10 +2862,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              && REG_P (reg)
              && (GET_MODE_SIZE (GET_MODE (reg))
                  >= GET_MODE_SIZE (GET_MODE (op)))
-             && reg_equiv_constant[REGNO (reg)] == 0)
+             && reg_equiv_constant (REGNO (reg)) == 0)
            set_unique_reg_note (emit_insn_before (gen_rtx_USE (VOIDmode, reg),
                                                   insn),
-                                REG_EQUAL, reg_equiv_memory_loc[REGNO (reg)]);
+                                REG_EQUAL, reg_equiv_memory_loc (REGNO (reg)));
 
          substed_operand[i] = recog_data.operand[i] = op;
        }
@@ -2830,7 +2886,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
             that we don't try to replace it in the insn in which it
             is being set.  */
          int regno = REGNO (recog_data.operand[i]);
-         if (reg_equiv_constant[regno] != 0
+         if (reg_equiv_constant (regno) != 0
              && (set == 0 || &SET_DEST (set) != recog_data.operand_loc[i]))
            {
              /* Record the existing mode so that the check if constants are
@@ -2840,10 +2896,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                operand_mode[i] = GET_MODE (recog_data.operand[i]);
 
              substed_operand[i] = recog_data.operand[i]
-               = reg_equiv_constant[regno];
+               = reg_equiv_constant (regno);
            }
-         if (reg_equiv_memory_loc[regno] != 0
-             && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
+         if (reg_equiv_memory_loc (regno) != 0
+             && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset))
            /* We need not give a valid is_set_dest argument since the case
               of a constant equivalence was checked above.  */
            substed_operand[i] = recog_data.operand[i]
@@ -2912,11 +2968,21 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
         a bad register class to only count 1/3 as much.  */
       int reject = 0;
 
+      if (!recog_data.alternative_enabled_p[this_alternative_number])
+       {
+         int i;
+
+         for (i = 0; i < recog_data.n_operands; i++)
+           constraints[i] = skip_alternative (constraints[i]);
+
+         continue;
+       }
+
       this_earlyclobber = 0;
 
       for (i = 0; i < noperands; i++)
        {
-         char *p = constraints[i];
+         const char *p = constraints[i];
          char *end;
          int len;
          int win = 0;
@@ -2957,12 +3023,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              if (REG_P (SUBREG_REG (operand))
                  && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
                {
-                 if (!subreg_offset_representable_p
-                       (REGNO (SUBREG_REG (operand)),
-                        GET_MODE (SUBREG_REG (operand)),
-                        SUBREG_BYTE (operand),
-                        GET_MODE (operand)))
-                    force_reload = 1;
+                 if (simplify_subreg_regno (REGNO (SUBREG_REG (operand)),
+                                            GET_MODE (SUBREG_REG (operand)),
+                                            SUBREG_BYTE (operand),
+                                            GET_MODE (operand)) < 0)
+                   force_reload = 1;
                  offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
                                                 GET_MODE (SUBREG_REG (operand)),
                                                 SUBREG_BYTE (operand),
@@ -3022,7 +3087,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                force_reload = 1;
            }
 
-         this_alternative[i] = (int) NO_REGS;
+         this_alternative[i] = NO_REGS;
          this_alternative_win[i] = 0;
          this_alternative_match_win[i] = 0;
          this_alternative_offmemok[i] = 0;
@@ -3109,7 +3174,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                       this combination, because we can't reload it.  */
                    if (this_alternative_offmemok[m]
                        && MEM_P (recog_data.operand[m])
-                       && this_alternative[m] == (int) NO_REGS
+                       && this_alternative[m] == NO_REGS
                        && ! this_alternative_win[m])
                      bad = 1;
 
@@ -3125,7 +3190,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                    if (this_alternative_win[m])
                      losers++;
                    this_alternative_win[m] = 0;
-                   if (this_alternative[m] == (int) NO_REGS)
+                   if (this_alternative[m] == NO_REGS)
                      bad = 1;
                    /* But count the pair only once in the total badness of
                       this alternative, if the pair can be a dummy reload.
@@ -3175,12 +3240,13 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                /* All necessary reloads for an address_operand
                   were handled in find_reloads_address.  */
                this_alternative[i]
-                 = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
+                 = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+                                   ADDRESS, SCRATCH);
                win = 1;
                badop = 0;
                break;
 
-             case 'm':
+             case TARGET_MEM_CONSTRAINT:
                if (force_reload)
                  break;
                if (MEM_P (operand)
@@ -3188,7 +3254,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                        && REGNO (operand) >= FIRST_PSEUDO_REGISTER
                        && reg_renumber[REGNO (operand)] < 0))
                  win = 1;
-               if (CONST_POOL_OK_P (operand))
+               if (CONST_POOL_OK_P (operand_mode[i], operand))
                  badop = 0;
                constmemok = 1;
                break;
@@ -3222,7 +3288,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                       to override the handling of reg_equiv_address.  */
                    && !(REG_P (XEXP (operand, 0))
                         && (ind_levels == 0
-                            || reg_equiv_address[REGNO (XEXP (operand, 0))] != 0)))
+                            || reg_equiv_address (REGNO (XEXP (operand, 0))) != 0)))
                  win = 1;
                break;
 
@@ -3246,11 +3312,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                           loading it into a register; hence it will be
                           offsettable, but we cannot say that reg_equiv_mem
                           is offsettable without checking.  */
-                       && ((reg_equiv_mem[REGNO (operand)] != 0
-                            && offsettable_memref_p (reg_equiv_mem[REGNO (operand)]))
-                           || (reg_equiv_address[REGNO (operand)] != 0))))
+                       && ((reg_equiv_mem (REGNO (operand)) != 0
+                            && offsettable_memref_p (reg_equiv_mem (REGNO (operand))))
+                           || (reg_equiv_address (REGNO (operand)) != 0))))
                  win = 1;
-               if (CONST_POOL_OK_P (operand)
+               if (CONST_POOL_OK_P (operand_mode[i], operand)
                    || MEM_P (operand))
                  badop = 0;
                constmemok = 1;
@@ -3280,7 +3346,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                break;
 
              case 's':
-               if (GET_CODE (operand) == CONST_INT
+               if (CONST_INT_P (operand)
                    || (GET_CODE (operand) == CONST_DOUBLE
                        && GET_MODE (operand) == VOIDmode))
                  break;
@@ -3291,7 +3357,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                break;
 
              case 'n':
-               if (GET_CODE (operand) == CONST_INT
+               if (CONST_INT_P (operand)
                    || (GET_CODE (operand) == CONST_DOUBLE
                        && GET_MODE (operand) == VOIDmode))
                  win = 1;
@@ -3305,7 +3371,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              case 'N':
              case 'O':
              case 'P':
-               if (GET_CODE (operand) == CONST_INT
+               if (CONST_INT_P (operand)
                    && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p))
                  win = 1;
                break;
@@ -3334,7 +3400,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
              case 'r':
                this_alternative[i]
-                 = (int) reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
+                 = reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
                goto reg;
 
              default:
@@ -3358,15 +3424,15 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                        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)))
+                                && ((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)
+                       if (CONST_POOL_OK_P (operand_mode[i], operand)
                            || MEM_P (operand))
                          badop = 0;
                        constmemok = 1;
@@ -3381,7 +3447,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                        /* If we didn't already win, we can reload
                           the address into a base register.  */
                        this_alternative[i]
-                         = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
+                         = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+                                           ADDRESS, SCRATCH);
                        badop = 0;
                        break;
                      }
@@ -3393,9 +3460,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                  }
 
                this_alternative[i]
-                 = (int) (reg_class_subunion
-                          [this_alternative[i]]
-                          [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
+                 = (reg_class_subunion
+                    [this_alternative[i]]
+                    [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
              reg:
                if (GET_MODE (operand) == BLKmode)
                  break;
@@ -3412,7 +3479,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
          /* If this operand could be handled with a reg,
             and some reg is allowed, then this operand can be handled.  */
-         if (winreg && this_alternative[i] != (int) NO_REGS)
+         if (winreg && this_alternative[i] != NO_REGS
+             && (win || !class_only_fixed_regs[this_alternative[i]]))
            badop = 0;
 
          /* Record which operands fit this alternative.  */
@@ -3431,7 +3499,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                bad = 1;
              /* Alternative loses if it has no regs for a reg operand.  */
              if (REG_P (operand)
-                 && this_alternative[i] == (int) NO_REGS
+                 && this_alternative[i] == NO_REGS
                  && this_alternative_matches[i] < 0)
                bad = 1;
 
@@ -3443,15 +3511,14 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                 an early reload pass.  Note that the test here is
                 precisely the same as in the code below that calls
                 force_const_mem.  */
-             if (CONST_POOL_OK_P (operand)
-                 && ((PREFERRED_RELOAD_CLASS (operand,
-                                              (enum reg_class) this_alternative[i])
+             if (CONST_POOL_OK_P (operand_mode[i], operand)
+                 && ((targetm.preferred_reload_class (operand,
+                                                      this_alternative[i])
                       == NO_REGS)
-                     || no_input_reloads)
-                 && operand_mode[i] != VOIDmode)
+                     || no_input_reloads))
                {
                  const_to_mem = 1;
-                 if (this_alternative[i] != (int) NO_REGS)
+                 if (this_alternative[i] != NO_REGS)
                    losers++;
                }
 
@@ -3471,21 +3538,17 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                 LIMIT_RELOAD_CLASS, but we don't check that
                 here.  */
 
-             if (! CONSTANT_P (operand)
-                 && (enum reg_class) this_alternative[i] != NO_REGS)
+             if (! CONSTANT_P (operand) && this_alternative[i] != NO_REGS)
                {
-                 if (PREFERRED_RELOAD_CLASS
-                       (operand, (enum reg_class) this_alternative[i])
+                 if (targetm.preferred_reload_class (operand, this_alternative[i])
                      == NO_REGS)
                    reject = 600;
 
-#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
                  if (operand_type[i] == RELOAD_FOR_OUTPUT
-                     && PREFERRED_OUTPUT_RELOAD_CLASS
-                          (operand, (enum reg_class) this_alternative[i])
-                        == NO_REGS)
+                     && (targetm.preferred_output_reload_class (operand,
+                                                                this_alternative[i])
+                         == NO_REGS))
                    reject = 600;
-#endif
                }
 
              /* We prefer to reload pseudos over reloading other things,
@@ -3531,10 +3594,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
             because we might otherwise exhaust the class.  */
 
          if (! win && ! did_match
-             && this_alternative[i] != (int) NO_REGS
+             && this_alternative[i] != NO_REGS
              && GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
              && reg_class_size [(int) preferred_class[i]] > 0
-             && ! SMALL_REGISTER_CLASS_P (preferred_class[i]))
+             && ! small_register_class_p (preferred_class[i]))
            {
              if (! reg_class_subset_p (this_alternative[i],
                                        preferred_class[i]))
@@ -3545,7 +3608,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                     common case anyway.  */
                  if (reg_class_subset_p (preferred_class[i],
                                          this_alternative[i]))
-                   this_alternative[i] = (int) preferred_class[i];
+                   this_alternative[i] = preferred_class[i];
                  else
                    reject += (2 + 2 * pref_or_nothing[i]);
                }
@@ -3580,7 +3643,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                   || modified[j] != RELOAD_WRITE)
                  && j != i
                  /* Ignore things like match_operator operands.  */
-                 && *recog_data.constraints[j] != 0
+                 && !recog_data.is_operator[j]
                  /* Don't count an input operand that is constrained to match
                     the early clobber operand.  */
                  && ! (this_alternative_matches[j] == i
@@ -3592,7 +3655,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                {
                  /* If the output is in a non-empty few-regs class,
                     it's costly to reload it, so reload the input instead.  */
-                 if (SMALL_REGISTER_CLASS_P (this_alternative[i])
+                 if (small_register_class_p (this_alternative[i])
                      && (REG_P (recog_data.operand[j])
                          || GET_CODE (recog_data.operand[j]) == SUBREG))
                    {
@@ -3657,22 +3720,27 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
       /* If this alternative can be made to work by reloading,
         and it needs less reloading than the others checked so far,
         record it as the chosen goal for reloading.  */
-      if (! bad && best > losers)
+      if (! bad)
        {
-         for (i = 0; i < noperands; i++)
+         if (best > losers)
            {
-             goal_alternative[i] = this_alternative[i];
-             goal_alternative_win[i] = this_alternative_win[i];
-             goal_alternative_match_win[i] = this_alternative_match_win[i];
-             goal_alternative_offmemok[i] = this_alternative_offmemok[i];
-             goal_alternative_matches[i] = this_alternative_matches[i];
-             goal_alternative_earlyclobber[i]
-               = this_alternative_earlyclobber[i];
+             for (i = 0; i < noperands; i++)
+               {
+                 goal_alternative[i] = this_alternative[i];
+                 goal_alternative_win[i] = this_alternative_win[i];
+                 goal_alternative_match_win[i]
+                   = this_alternative_match_win[i];
+                 goal_alternative_offmemok[i]
+                   = this_alternative_offmemok[i];
+                 goal_alternative_matches[i] = this_alternative_matches[i];
+                 goal_alternative_earlyclobber[i]
+                   = this_alternative_earlyclobber[i];
+               }
+             goal_alternative_swapped = swapped;
+             best = losers;
+             goal_alternative_number = this_alternative_number;
+             goal_earlyclobber = this_earlyclobber;
            }
-         goal_alternative_swapped = swapped;
-         best = losers;
-         goal_alternative_number = this_alternative_number;
-         goal_earlyclobber = this_earlyclobber;
        }
     }
 
@@ -3715,7 +3783,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
          address_reloaded[commutative + 1] = t;
 
          memcpy (constraints, recog_data.constraints,
-                 noperands * sizeof (char *));
+                 noperands * sizeof (const char *));
          goto try_swapped;
        }
       else
@@ -3828,43 +3896,59 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   /* Any constants that aren't allowed and can't be reloaded
      into registers are here changed into memory references.  */
   for (i = 0; i < noperands; i++)
-    if (! goal_alternative_win[i]
-       && CONST_POOL_OK_P (recog_data.operand[i])
-       && ((PREFERRED_RELOAD_CLASS (recog_data.operand[i],
-                                    (enum reg_class) goal_alternative[i])
-            == NO_REGS)
-           || no_input_reloads)
-       && operand_mode[i] != VOIDmode)
+    if (! goal_alternative_win[i])
       {
-       substed_operand[i] = recog_data.operand[i]
-         = find_reloads_toplev (force_const_mem (operand_mode[i],
-                                                 recog_data.operand[i]),
-                                i, address_type[i], ind_levels, 0, insn,
-                                NULL);
-       if (alternative_allows_memconst (recog_data.constraints[i],
-                                        goal_alternative_number))
-         goal_alternative_win[i] = 1;
-      }
+       rtx op = recog_data.operand[i];
+       rtx subreg = NULL_RTX;
+       rtx plus = NULL_RTX;
+       enum 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.  */
+       if (GET_CODE (op) == SUBREG)
+         {
+           subreg = op;
+           op = SUBREG_REG (op);
+           mode = GET_MODE (op);
+         }
 
-  /* Likewise any invalid constants appearing as operand of a PLUS
-     that is to be reloaded.  */
-  for (i = 0; i < noperands; i++)
-    if (! goal_alternative_win[i]
-       && GET_CODE (recog_data.operand[i]) == PLUS
-       && CONST_POOL_OK_P (XEXP (recog_data.operand[i], 1))
-       && (PREFERRED_RELOAD_CLASS (XEXP (recog_data.operand[i], 1),
-                                   (enum reg_class) goal_alternative[i])
-            == NO_REGS)
-       && operand_mode[i] != VOIDmode)
-      {
-       rtx tem = force_const_mem (operand_mode[i],
-                                  XEXP (recog_data.operand[i], 1));
-       tem = gen_rtx_PLUS (operand_mode[i],
-                           XEXP (recog_data.operand[i], 0), tem);
+       if (GET_CODE (op) == PLUS)
+         {
+           plus = op;
+           op = XEXP (op, 1);
+         }
 
-       substed_operand[i] = recog_data.operand[i]
-         = find_reloads_toplev (tem, i, address_type[i],
-                                ind_levels, 0, insn, NULL);
+       if (CONST_POOL_OK_P (mode, op)
+           && ((targetm.preferred_reload_class (op, goal_alternative[i])
+                == NO_REGS)
+               || no_input_reloads))
+         {
+           int this_address_reloaded;
+           rtx tem = force_const_mem (mode, op);
+
+           /* If we stripped a SUBREG or a PLUS above add it back.  */
+           if (plus != NULL_RTX)
+             tem = gen_rtx_PLUS (mode, XEXP (plus, 0), tem);
+
+           if (subreg != NULL_RTX)
+             tem = gen_rtx_SUBREG (operand_mode[i], tem, SUBREG_BYTE (subreg));
+
+           this_address_reloaded = 0;
+           substed_operand[i] = recog_data.operand[i]
+             = find_reloads_toplev (tem, i, address_type[i], ind_levels,
+                                    0, insn, &this_address_reloaded);
+
+           /* If the alternative accepts constant pool refs directly
+              there will be no reload needed at all.  */
+           if (plus == NULL_RTX
+               && subreg == NULL_RTX
+               && alternative_allows_const_pool_ref (this_address_reloaded == 0
+                                                     ? substed_operand[i]
+                                                     : NULL,
+                                                     recog_data.constraints[i],
+                                                     goal_alternative_number))
+             goal_alternative_win[i] = 1;
+         }
       }
 
   /* Record the values of the earlyclobber operands for the caller.  */
@@ -3892,17 +3976,18 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                 && MEM_P (recog_data.operand[i]))
          {
            /* If the address to be reloaded is a VOIDmode constant,
-              use Pmode as mode of the reload register, as would have
-              been done by find_reloads_address.  */
+              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;
            address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
            if (address_mode == VOIDmode)
-             address_mode = Pmode;
+             address_mode = targetm.addr_space.address_mode (as);
 
            operand_reloadnum[i]
              = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
                             &XEXP (recog_data.operand[i], 0), (rtx*) 0,
-                            base_reg_class (VOIDmode, MEM, SCRATCH),
+                            base_reg_class (VOIDmode, as, MEM, SCRATCH),
                             address_mode,
                             VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
            rld[operand_reloadnum[i]].inc
@@ -4009,7 +4094,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
            /* If this is only for an output, the optional reload would not
               actually cause us to use a register now, just note that
               something is stored here.  */
-           && ((enum reg_class) goal_alternative[i] != NO_REGS
+           && (goal_alternative[i] != NO_REGS
                || modified[i] == RELOAD_WRITE)
            && ! no_input_reloads
            /* An optional output reload might allow to delete INSN later.
@@ -4062,7 +4147,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                  PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, operand),
                                              insn), QImode);
                if (modified[i] != RELOAD_READ)
-                 emit_insn_after (gen_rtx_CLOBBER (VOIDmode, operand), insn);
+                 emit_insn_after (gen_clobber (operand), insn);
              }
          }
       }
@@ -4083,8 +4168,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
        if ((MEM_P (operand)
             || (REG_P (operand)
                 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
-           && ((enum reg_class) goal_alternative[goal_alternative_matches[i]]
-               != NO_REGS))
+           && (goal_alternative[goal_alternative_matches[i]] != NO_REGS))
          operand_reloadnum[i] = operand_reloadnum[goal_alternative_matches[i]]
            = push_reload (recog_data.operand[goal_alternative_matches[i]],
                           recog_data.operand[i],
@@ -4124,9 +4208,12 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              && (!JUMP_P (insn)
                  || !label_is_jump_target_p (XEXP (substitution, 0),
                                              insn)))
-           REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND,
-                                                 XEXP (substitution, 0),
-                                                 REG_NOTES (insn));
+           {
+             add_reg_note (insn, REG_LABEL_OPERAND, XEXP (substitution, 0));
+             if (LABEL_P (XEXP (substitution, 0)))
+               ++LABEL_NUSES (XEXP (substitution, 0));
+           }
+
        }
       else
        retval |= (substed_operand[i] != *recog_data.operand_loc[i]);
@@ -4165,7 +4252,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
        && rld[i].out == 0)
       {
        rld[i].reg_rtx
-         = find_equiv_reg (rld[i].in, insn, rld[i].class, -1,
+         = find_equiv_reg (rld[i].in, insn, rld[i].rclass, -1,
                            static_reload_reg_p, 0, rld[i].inmode);
        /* Prevent generation of insn to load the value
           because the one we found already has the value.  */
@@ -4177,7 +4264,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   /* If we detected error and replaced asm instruction by USE, forget about the
      reloads.  */
   if (GET_CODE (PATTERN (insn)) == USE
-      && GET_CODE (XEXP (PATTERN (insn), 0)) == CONST_INT)
+      && CONST_INT_P (XEXP (PATTERN (insn), 0)))
     n_reloads = 0;
 
   /* Perhaps an output reload can be combined with another
@@ -4434,7 +4521,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
        if (i != j && rld[j].in != 0 && rld[j].out == 0
            && rld[j].when_needed == rld[i].when_needed
            && MATCHES (rld[i].in, rld[j].in)
-           && rld[i].class == rld[j].class
+           && rld[i].rclass == rld[j].rclass
            && !rld[i].nocombine && !rld[j].nocombine
            && rld[i].reg_rtx == rld[j].reg_rtx)
          {
@@ -4463,7 +4550,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
               > GET_MODE_SIZE (rld[i].inmode)))
          ? rld[i].outmode : rld[i].inmode;
 
-      rld[i].nregs = CLASS_MAX_NREGS (rld[i].class, rld[i].mode);
+      rld[i].nregs = ira_reg_class_max_nregs [rld[i].rclass][rld[i].mode];
     }
 
   /* Special case a simple move with an input reload and a
@@ -4480,14 +4567,14 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
        unsigned int regno = REGNO (dest);
 
        if (regno < FIRST_PSEUDO_REGISTER
-           && TEST_HARD_REG_BIT (reg_class_contents[rld[i].class], regno)
+           && TEST_HARD_REG_BIT (reg_class_contents[rld[i].rclass], regno)
            && HARD_REGNO_MODE_OK (regno, rld[i].mode))
          {
            int nr = hard_regno_nregs[regno][rld[i].mode];
            int ok = 1, nri;
 
            for (nri = 1; nri < nr; nri ++)
-             if (! TEST_HARD_REG_BIT (reg_class_contents[rld[i].class], regno + nri))
+             if (! TEST_HARD_REG_BIT (reg_class_contents[rld[i].rclass], regno + nri))
                ok = 0;
 
            if (ok)
@@ -4498,26 +4585,44 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   return retval;
 }
 
-/* Return 1 if alternative number ALTNUM in constraint-string CONSTRAINT
-   accepts a memory operand with constant address.  */
+/* Return true if alternative number ALTNUM in constraint-string
+   CONSTRAINT is guaranteed to accept a reloaded constant-pool reference.
+   MEM gives the reference if it didn't need any reloads, otherwise it
+   is null.  */
 
-static int
-alternative_allows_memconst (const char *constraint, int altnum)
+static bool
+alternative_allows_const_pool_ref (rtx mem ATTRIBUTE_UNUSED,
+                                  const char *constraint, int altnum)
 {
   int c;
+
   /* Skip alternatives before the one requested.  */
   while (altnum > 0)
     {
-      while (*constraint++ != ',');
+      while (*constraint++ != ',')
+       ;
       altnum--;
     }
-  /* Scan the requested alternative for 'm' or 'o'.
-     If one of them is present, this alternative accepts memory constants.  */
+  /* Scan the requested alternative for TARGET_MEM_CONSTRAINT or 'o'.
+     If one of them is present, this alternative accepts the result of
+     passing a constant-pool reference through find_reloads_toplev.
+
+     The same is true of extra memory constraints if the address
+     was reloaded into a register.  However, the target may elect
+     to disallow the original constant address, forcing it to be
+     reloaded into a register instead.  */
   for (; (c = *constraint) && c != ',' && c != '#';
        constraint += CONSTRAINT_LEN (c, constraint))
-    if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c, constraint))
-      return 1;
-  return 0;
+    {
+      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)))
+       return true;
+#endif
+    }
+  return false;
 }
 \f
 /* Scan X for memory references and scan the addresses for reloading.
@@ -4557,20 +4662,20 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
     {
       /* This code is duplicated for speed in find_reloads.  */
       int regno = REGNO (x);
-      if (reg_equiv_constant[regno] != 0 && !is_set_dest)
-       x = reg_equiv_constant[regno];
+      if (reg_equiv_constant (regno) != 0 && !is_set_dest)
+       x = reg_equiv_constant (regno);
 #if 0
       /*  This creates (subreg (mem...)) which would cause an unnecessary
          reload of the mem.  */
-      else if (reg_equiv_mem[regno] != 0)
-       x = reg_equiv_mem[regno];
+      else if (reg_equiv_mem (regno) != 0)
+       x = reg_equiv_mem (regno);
 #endif
-      else if (reg_equiv_memory_loc[regno]
-              && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
+      else if (reg_equiv_memory_loc (regno)
+              && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset))
        {
          rtx mem = make_memloc (x, regno);
-         if (reg_equiv_address[regno]
-             || ! rtx_equal_p (mem, reg_equiv_mem[regno]))
+         if (reg_equiv_address (regno)
+             || ! rtx_equal_p (mem, reg_equiv_mem (regno)))
            {
              /* If this is not a toplevel operand, find_reloads doesn't see
                 this substitution.  We have to emit a USE of the pseudo so
@@ -4620,13 +4725,14 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
 
       if (regno >= FIRST_PSEUDO_REGISTER
          && reg_renumber[regno] < 0
-         && reg_equiv_constant[regno] != 0)
+         && reg_equiv_constant (regno) != 0)
        {
          tem =
-           simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno],
+           simplify_gen_subreg (GET_MODE (x), reg_equiv_constant (regno),
                                 GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
          gcc_assert (tem);
-         if (CONSTANT_P (tem) && !LEGITIMATE_CONSTANT_P (tem))
+         if (CONSTANT_P (tem)
+             && !targetm.legitimate_constant_p (GET_MODE (x), tem))
            {
              tem = force_const_mem (GET_MODE (x), tem);
              i = find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
@@ -4653,17 +4759,17 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
 
       if (regno >= FIRST_PSEUDO_REGISTER
 #ifdef LOAD_EXTEND_OP
-              && (GET_MODE_SIZE (GET_MODE (x))
-                  <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+         && !paradoxical_subreg_p (x)
 #endif
-              && (reg_equiv_address[regno] != 0
-                  || (reg_equiv_mem[regno] != 0
-                      && (! strict_memory_address_p (GET_MODE (x),
-                                                     XEXP (reg_equiv_mem[regno], 0))
-                          || ! offsettable_memref_p (reg_equiv_mem[regno])
-                          || num_not_at_initial_offset))))
+         && (reg_equiv_address (regno) != 0
+             || (reg_equiv_mem (regno) != 0
+                 && (! strict_memory_address_addr_space_p
+                     (GET_MODE (x), XEXP (reg_equiv_mem (regno), 0),
+                      MEM_ADDR_SPACE (reg_equiv_mem (regno)))
+                     || ! offsettable_memref_p (reg_equiv_mem (regno))
+                     || num_not_at_initial_offset))))
        x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
-                                        insn);
+                                          insn, address_reloaded);
     }
 
   for (copied = 0, i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
@@ -4698,36 +4804,38 @@ make_memloc (rtx ad, int regno)
   /* We must rerun eliminate_regs, in case the elimination
      offsets have changed.  */
   rtx tem
-    = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0, NULL_RTX), 0);
+    = XEXP (eliminate_regs (reg_equiv_memory_loc (regno), VOIDmode, NULL_RTX),
+           0);
 
   /* If TEM might contain a pseudo, we must copy it to avoid
      modifying it when we do the substitution for the reload.  */
   if (rtx_varies_p (tem, 0))
     tem = copy_rtx (tem);
 
-  tem = replace_equiv_address_nv (reg_equiv_memory_loc[regno], tem);
+  tem = replace_equiv_address_nv (reg_equiv_memory_loc (regno), tem);
   tem = adjust_address_nv (tem, GET_MODE (ad), 0);
 
   /* Copy the result if it's still the same as the equivalence, to avoid
      modifying it when we do the substitution for the reload.  */
-  if (tem == reg_equiv_memory_loc[regno])
+  if (tem == reg_equiv_memory_loc (regno))
     tem = copy_rtx (tem);
   return tem;
 }
 
 /* Returns true if AD could be turned into a valid memory reference
-   to mode MODE by reloading the part pointed to by PART into a
-   register.  */
+   to mode MODE in address space AS by reloading the part pointed to
+   by PART into a register.  */
 
 static int
-maybe_memory_address_p (enum machine_mode mode, rtx ad, rtx *part)
+maybe_memory_address_addr_space_p (enum machine_mode mode, rtx ad,
+                                  addr_space_t as, rtx *part)
 {
   int retv;
   rtx tem = *part;
   rtx reg = gen_rtx_REG (GET_MODE (tem), max_reg_num ());
 
   *part = reg;
-  retv = memory_address_p (mode, ad);
+  retv = memory_address_addr_space_p (mode, ad, as);
   *part = tem;
 
   return retv;
@@ -4763,6 +4871,8 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
                      rtx *loc, int opnum, enum reload_type type,
                      int ind_levels, rtx insn)
 {
+  addr_space_t as = memrefloc? MEM_ADDR_SPACE (*memrefloc)
+                            : ADDR_SPACE_GENERIC;
   int regno;
   int removed_and = 0;
   int op_index;
@@ -4776,21 +4886,23 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
     {
       regno = REGNO (ad);
 
-      if (reg_equiv_constant[regno] != 0)
+      if (reg_equiv_constant (regno) != 0)
        {
-         find_reloads_address_part (reg_equiv_constant[regno], loc,
-                                    base_reg_class (mode, MEM, SCRATCH),
+         find_reloads_address_part (reg_equiv_constant (regno), loc,
+                                    base_reg_class (mode, as, MEM, SCRATCH),
                                     GET_MODE (ad), opnum, type, ind_levels);
          return 1;
        }
 
-      tem = reg_equiv_memory_loc[regno];
+      tem = reg_equiv_memory_loc (regno);
       if (tem != 0)
        {
-         if (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)
+         if (reg_equiv_address (regno) != 0 || num_not_at_initial_offset)
            {
              tem = make_memloc (ad, regno);
-             if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
+             if (! strict_memory_address_addr_space_p (GET_MODE (tem),
+                                                       XEXP (tem, 0),
+                                                       MEM_ADDR_SPACE (tem)))
                {
                  rtx orig = tem;
 
@@ -4806,7 +4918,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
                 address: only reg or reg+constant.  */
 
              if (ind_levels > 0
-                 && strict_memory_address_p (mode, tem)
+                 && strict_memory_address_addr_space_p (mode, tem, as)
                  && (REG_P (XEXP (tem, 0))
                      || (GET_CODE (XEXP (tem, 0)) == PLUS
                          && REG_P (XEXP (XEXP (tem, 0), 0))
@@ -4817,7 +4929,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
                     in the final reload pass.  */
                  if (replace_reloads
                      && num_not_at_initial_offset
-                     && ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+                     && ! rtx_equal_p (tem, reg_equiv_mem (regno)))
                    {
                      *loc = tem;
                      /* We mark the USE with QImode so that we
@@ -4840,17 +4952,18 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
         subject of a CLOBBER in this insn.  */
 
       else if (regno < FIRST_PSEUDO_REGISTER
-              && regno_ok_for_base_p (regno, mode, MEM, SCRATCH)
+              && regno_ok_for_base_p (regno, mode, as, MEM, SCRATCH)
               && ! regno_clobbered_p (regno, this_insn, mode, 0))
        return 0;
 
       /* If we do not have one of the cases above, we must do the reload.  */
-      push_reload (ad, NULL_RTX, loc, (rtx*) 0, base_reg_class (mode, MEM, SCRATCH),
+      push_reload (ad, NULL_RTX, loc, (rtx*) 0,
+                  base_reg_class (mode, as, MEM, SCRATCH),
                   GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
       return 1;
     }
 
-  if (strict_memory_address_p (mode, ad))
+  if (strict_memory_address_addr_space_p (mode, ad, as))
     {
       /* The address appears valid, so reloads are not needed.
         But the address may contain an eliminable register.
@@ -4861,9 +4974,9 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 
       /* But first quickly dispose of a common case.  */
       if (GET_CODE (ad) == PLUS
-         && GET_CODE (XEXP (ad, 1)) == CONST_INT
+         && CONST_INT_P (XEXP (ad, 1))
          && REG_P (XEXP (ad, 0))
-         && reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0)
+         && reg_equiv_constant (REGNO (XEXP (ad, 0))) == 0)
        return 0;
 
       subst_reg_equivs_changed = 0;
@@ -4873,14 +4986,14 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
        return 0;
 
       /* Check result for validity after substitution.  */
-      if (strict_memory_address_p (mode, ad))
+      if (strict_memory_address_addr_space_p (mode, ad, as))
        return 0;
     }
 
 #ifdef LEGITIMIZE_RELOAD_ADDRESS
   do
     {
-      if (memrefloc)
+      if (memrefloc && ADDR_SPACE_GENERIC_P (as))
        {
          LEGITIMIZE_RELOAD_ADDRESS (ad, GET_MODE (*memrefloc), opnum, type,
                                     ind_levels, win);
@@ -4941,12 +5054,12 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
          || ! (REG_P (XEXP (tem, 0))
                || (GET_CODE (XEXP (tem, 0)) == PLUS
                    && REG_P (XEXP (XEXP (tem, 0), 0))
-                   && GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT)))
+                   && CONST_INT_P (XEXP (XEXP (tem, 0), 1)))))
        {
          /* Must use TEM here, not AD, since it is the one that will
             have any subexpressions reloaded, if needed.  */
          push_reload (tem, NULL_RTX, loc, (rtx*) 0,
-                      base_reg_class (mode, MEM, SCRATCH), GET_MODE (tem),
+                      base_reg_class (mode, as, MEM, SCRATCH), GET_MODE (tem),
                       VOIDmode, 0,
                       0, opnum, type);
          return ! removed_and;
@@ -4963,9 +5076,14 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
   else if (GET_CODE (ad) == PLUS
           && REG_P (XEXP (ad, 0))
           && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
-          && GET_CODE (XEXP (ad, 1)) == CONST_INT
-          && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
-                                  CONST_INT))
+          && CONST_INT_P (XEXP (ad, 1))
+          && (regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, as, PLUS,
+                                   CONST_INT)
+              /* Similarly, if we were to reload the base register and the
+                 mem+offset address is still invalid, then we want to reload
+                 the whole address, not just the base register.  */
+              || ! maybe_memory_address_addr_space_p
+                    (mode, ad, as, &(XEXP (ad, 0)))))
 
     {
       /* Unshare the MEM rtx so we can safely alter it.  */
@@ -4977,7 +5095,9 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
            loc = &XEXP (*loc, 0);
        }
 
-      if (double_reg_address_ok)
+      if (double_reg_address_ok
+         && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, as,
+                                 PLUS, CONST_INT))
        {
          /* Unshare the sum as well.  */
          *loc = ad = copy_rtx (ad);
@@ -4995,8 +5115,8 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
             reload the sum into a base reg.
             That will at least work.  */
          find_reloads_address_part (ad, loc,
-                                    base_reg_class (mode, MEM, SCRATCH),
-                                    Pmode, opnum, type, ind_levels);
+                                    base_reg_class (mode, as, MEM, SCRATCH),
+                                    GET_MODE (ad), opnum, type, ind_levels);
        }
       return ! removed_and;
     }
@@ -5036,8 +5156,8 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
          continue;
 
       inner_code = GET_CODE (XEXP (ad, 0));
-      if (!(GET_CODE (ad) == PLUS 
-           && GET_CODE (XEXP (ad, 1)) == CONST_INT
+      if (!(GET_CODE (ad) == PLUS
+           && CONST_INT_P (XEXP (ad, 1))
            && (inner_code == PLUS || inner_code == LO_SUM)))
        continue;
 
@@ -5047,18 +5167,18 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 
       addend = XEXP (XEXP (ad, 0), 1 - op_index);
 
-      if ((regno_ok_for_base_p (REGNO (operand), mode, inner_code,
+      if ((regno_ok_for_base_p (REGNO (operand), mode, as, inner_code,
                                GET_CODE (addend))
           || operand == frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+#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
           || operand == stack_pointer_rtx)
-         && ! maybe_memory_address_p (mode, ad, 
-                                      &XEXP (XEXP (ad, 0), 1 - op_index)))
+         && ! maybe_memory_address_addr_space_p
+               (mode, ad, as, &XEXP (XEXP (ad, 0), 1 - op_index)))
        {
          rtx offset_reg;
          enum reg_class cls;
@@ -5067,20 +5187,20 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 
          /* Form the adjusted address.  */
          if (GET_CODE (XEXP (ad, 0)) == PLUS)
-           ad = gen_rtx_PLUS (GET_MODE (ad), 
-                              op_index == 0 ? offset_reg : addend, 
+           ad = gen_rtx_PLUS (GET_MODE (ad),
+                              op_index == 0 ? offset_reg : addend,
                               op_index == 0 ? addend : offset_reg);
          else
-           ad = gen_rtx_LO_SUM (GET_MODE (ad), 
-                                op_index == 0 ? offset_reg : addend, 
+           ad = gen_rtx_LO_SUM (GET_MODE (ad),
+                                op_index == 0 ? offset_reg : addend,
                                 op_index == 0 ? addend : offset_reg);
          *loc = ad;
 
-         cls = base_reg_class (mode, MEM, GET_CODE (addend));
-         find_reloads_address_part (XEXP (ad, op_index), 
+         cls = base_reg_class (mode, as, MEM, GET_CODE (addend));
+         find_reloads_address_part (XEXP (ad, op_index),
                                     &XEXP (ad, op_index), cls,
                                     GET_MODE (ad), opnum, type, ind_levels);
-         find_reloads_address_1 (mode,
+         find_reloads_address_1 (mode, as,
                                  XEXP (ad, 1 - op_index), 1, GET_CODE (ad),
                                  GET_CODE (XEXP (ad, op_index)),
                                  &XEXP (ad, 1 - op_index), opnum,
@@ -5096,7 +5216,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
   tem = ad;
   if (GET_CODE (ad) == PLUS)
     tem = subst_indexed_address (ad);
-  if (tem != ad && strict_memory_address_p (mode, tem))
+  if (tem != ad && strict_memory_address_addr_space_p (mode, tem, as))
     {
       /* Ok, we win that way.  Replace any additional eliminable
         registers.  */
@@ -5106,7 +5226,8 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 
       /* Make sure that didn't make the address invalid again.  */
 
-      if (! subst_reg_equivs_changed || strict_memory_address_p (mode, tem))
+      if (! subst_reg_equivs_changed
+         || strict_memory_address_addr_space_p (mode, tem, as))
        {
          *loc = tem;
          return 0;
@@ -5115,8 +5236,12 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 
   /* If constants aren't valid addresses, reload the constant address
      into a register.  */
-  if (CONSTANT_P (ad) && ! strict_memory_address_p (mode, ad))
+  if (CONSTANT_P (ad) && ! strict_memory_address_addr_space_p (mode, ad, as))
     {
+      enum machine_mode address_mode = GET_MODE (ad);
+      if (address_mode == VOIDmode)
+       address_mode = targetm.addr_space.address_mode (as);
+
       /* If AD is an address in the constant pool, the MEM rtx may be shared.
         Unshare it so we can safely alter it.  */
       if (memrefloc && GET_CODE (ad) == SYMBOL_REF
@@ -5128,13 +5253,14 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
            loc = &XEXP (*loc, 0);
        }
 
-      find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
-                                Pmode, opnum, type, ind_levels);
+      find_reloads_address_part (ad, loc,
+                                base_reg_class (mode, as, MEM, SCRATCH),
+                                address_mode, opnum, type, ind_levels);
       return ! removed_and;
     }
 
-  return find_reloads_address_1 (mode, ad, 0, MEM, SCRATCH, loc, opnum, type,
-                                ind_levels, insn);
+  return find_reloads_address_1 (mode, as, ad, 0, MEM, SCRATCH, loc,
+                                opnum, type, ind_levels, insn);
 }
 \f
 /* Find all pseudo regs appearing in AD
@@ -5168,15 +5294,15 @@ subst_reg_equivs (rtx ad, rtx insn)
       {
        int regno = REGNO (ad);
 
-       if (reg_equiv_constant[regno] != 0)
+       if (reg_equiv_constant (regno) != 0)
          {
            subst_reg_equivs_changed = 1;
-           return reg_equiv_constant[regno];
+           return reg_equiv_constant (regno);
          }
-       if (reg_equiv_memory_loc[regno] && num_not_at_initial_offset)
+       if (reg_equiv_memory_loc (regno) && num_not_at_initial_offset)
          {
            rtx mem = make_memloc (ad, regno);
-           if (! rtx_equal_p (mem, reg_equiv_mem[regno]))
+           if (! rtx_equal_p (mem, reg_equiv_mem (regno)))
              {
                subst_reg_equivs_changed = 1;
                /* We mark the USE with QImode so that we recognize it
@@ -5193,7 +5319,7 @@ subst_reg_equivs (rtx ad, rtx insn)
     case PLUS:
       /* Quickly dispose of a common case.  */
       if (XEXP (ad, 0) == frame_pointer_rtx
-         && GET_CODE (XEXP (ad, 1)) == CONST_INT)
+         && CONST_INT_P (XEXP (ad, 1)))
        return ad;
       break;
 
@@ -5216,31 +5342,27 @@ subst_reg_equivs (rtx ad, rtx insn)
    This routine assumes both inputs are already in canonical form.  */
 
 rtx
-form_sum (rtx x, rtx y)
+form_sum (enum machine_mode mode, rtx x, rtx y)
 {
   rtx tem;
-  enum machine_mode mode = GET_MODE (x);
 
-  if (mode == VOIDmode)
-    mode = GET_MODE (y);
+  gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);
+  gcc_assert (GET_MODE (y) == mode || GET_MODE (y) == VOIDmode);
 
-  if (mode == VOIDmode)
-    mode = Pmode;
-
-  if (GET_CODE (x) == CONST_INT)
+  if (CONST_INT_P (x))
     return plus_constant (y, INTVAL (x));
-  else if (GET_CODE (y) == CONST_INT)
+  else if (CONST_INT_P (y))
     return plus_constant (x, INTVAL (y));
   else if (CONSTANT_P (x))
     tem = x, x = y, y = tem;
 
   if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)))
-    return form_sum (XEXP (x, 0), form_sum (XEXP (x, 1), y));
+    return form_sum (mode, XEXP (x, 0), form_sum (mode, XEXP (x, 1), y));
 
   /* Note that if the operands of Y are specified in the opposite
      order in the recursive calls below, infinite recursion will occur.  */
   if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1)))
-    return form_sum (form_sum (x, XEXP (y, 0)), XEXP (y, 1));
+    return form_sum (mode, form_sum (mode, x, XEXP (y, 0)), XEXP (y, 1));
 
   /* If both constant, encapsulate sum.  Otherwise, just form sum.  A
      constant will have been placed second.  */
@@ -5283,13 +5405,13 @@ subst_indexed_address (rtx addr)
       if (REG_P (op0)
          && (regno = REGNO (op0)) >= FIRST_PSEUDO_REGISTER
          && reg_renumber[regno] < 0
-         && reg_equiv_constant[regno] != 0)
-       op0 = reg_equiv_constant[regno];
+         && reg_equiv_constant (regno) != 0)
+       op0 = reg_equiv_constant (regno);
       else if (REG_P (op1)
               && (regno = REGNO (op1)) >= FIRST_PSEUDO_REGISTER
               && reg_renumber[regno] < 0
-              && reg_equiv_constant[regno] != 0)
-       op1 = reg_equiv_constant[regno];
+              && reg_equiv_constant (regno) != 0)
+       op1 = reg_equiv_constant (regno);
       else if (GET_CODE (op0) == PLUS
               && (tem = subst_indexed_address (op0)) != op0)
        op0 = tem;
@@ -5307,9 +5429,9 @@ subst_indexed_address (rtx addr)
 
       /* Compute the sum.  */
       if (op2 != 0)
-       op1 = form_sum (op1, op2);
+       op1 = form_sum (GET_MODE (addr), op1, op2);
       if (op1 != 0)
-       op0 = form_sum (op0, op1);
+       op0 = form_sum (GET_MODE (addr), op0, op1);
 
       return op0;
     }
@@ -5371,15 +5493,16 @@ 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, rtx x, int context,
+find_reloads_address_1 (enum 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)
 {
-#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, OUTER, INDEX)         \
+#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, AS, OUTER, INDEX)     \
   ((CONTEXT) == 0                                                      \
-   ? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX)                   \
-   : REGNO_OK_FOR_INDEX_P (REGNO))                                     
+   ? regno_ok_for_base_p (REGNO, MODE, AS, OUTER, INDEX)               \
+   : REGNO_OK_FOR_INDEX_P (REGNO))
 
   enum reg_class context_reg_class;
   RTX_CODE code = GET_CODE (x);
@@ -5387,7 +5510,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
   if (context == 1)
     context_reg_class = INDEX_REG_CLASS;
   else
-    context_reg_class = base_reg_class (mode, outer_code, index_code);
+    context_reg_class = base_reg_class (mode, as, outer_code, index_code);
 
   switch (code)
     {
@@ -5444,10 +5567,10 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
        if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
            || code0 == ZERO_EXTEND || code1 == MEM)
          {
-           find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+           find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
                                    &XEXP (x, 0), opnum, type, ind_levels,
                                    insn);
-           find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
+           find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, code0,
                                    &XEXP (x, 1), opnum, type, ind_levels,
                                    insn);
          }
@@ -5455,56 +5578,56 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
        else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
                 || code1 == ZERO_EXTEND || code0 == MEM)
          {
-           find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
+           find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, code1,
                                    &XEXP (x, 0), opnum, type, ind_levels,
                                    insn);
-           find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+           find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
                                    &XEXP (x, 1), opnum, type, ind_levels,
                                    insn);
          }
 
        else if (code0 == CONST_INT || code0 == CONST
                 || code0 == SYMBOL_REF || code0 == LABEL_REF)
-         find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
+         find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, code0,
                                  &XEXP (x, 1), opnum, type, ind_levels,
                                  insn);
 
        else if (code1 == CONST_INT || code1 == CONST
                 || code1 == SYMBOL_REF || code1 == LABEL_REF)
-         find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
+         find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, code1,
                                  &XEXP (x, 0), opnum, type, ind_levels,
                                  insn);
 
        else if (code0 == REG && code1 == REG)
          {
            if (REGNO_OK_FOR_INDEX_P (REGNO (op1))
-               && regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
+               && regno_ok_for_base_p (REGNO (op0), mode, as, PLUS, REG))
              return 0;
            else if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
-                    && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
+                    && regno_ok_for_base_p (REGNO (op1), mode, as, PLUS, REG))
              return 0;
-           else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
-             find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+           else if (regno_ok_for_base_p (REGNO (op0), mode, as, PLUS, REG))
+             find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
                                      &XEXP (x, 1), opnum, type, ind_levels,
                                      insn);
            else if (REGNO_OK_FOR_INDEX_P (REGNO (op1)))
-             find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+             find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
                                      &XEXP (x, 0), opnum, type, ind_levels,
                                      insn);
-           else if (regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
-             find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+           else if (regno_ok_for_base_p (REGNO (op1), mode, as, PLUS, REG))
+             find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
                                      &XEXP (x, 0), opnum, type, ind_levels,
                                      insn);
            else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)))
-             find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
+             find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, REG,
                                      &XEXP (x, 1), opnum, type, ind_levels,
                                      insn);
            else
              {
-               find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+               find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
                                        &XEXP (x, 0), opnum, type, ind_levels,
                                        insn);
-               find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+               find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
                                        &XEXP (x, 1), opnum, type, ind_levels,
                                        insn);
              }
@@ -5512,20 +5635,20 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
 
        else if (code0 == REG)
          {
-           find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+           find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
                                    &XEXP (x, 0), opnum, type, ind_levels,
                                    insn);
-           find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
+           find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, REG,
                                    &XEXP (x, 1), opnum, type, ind_levels,
                                    insn);
          }
 
        else if (code1 == REG)
          {
-           find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+           find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
                                    &XEXP (x, 1), opnum, type, ind_levels,
                                    insn);
-           find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+           find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
                                    &XEXP (x, 0), opnum, type, ind_levels,
                                    insn);
          }
@@ -5567,7 +5690,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
        if ((REG_P (XEXP (op1, 1))
             && !REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
            || GET_CODE (XEXP (op1, 1)) == PLUS)
-         find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH,
+         find_reloads_address_1 (mode, as, XEXP (op1, 1), 1, code, SCRATCH,
                                  &XEXP (op1, 1), opnum, RELOAD_OTHER,
                                  ind_levels, insn);
 
@@ -5578,18 +5701,18 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
 
        /* A register that is incremented cannot be constant!  */
        gcc_assert (regno < FIRST_PSEUDO_REGISTER
-                   || reg_equiv_constant[regno] == 0);
+                   || reg_equiv_constant (regno) == 0);
 
        /* Handle a register that is equivalent to a memory location
            which cannot be addressed directly.  */
-       if (reg_equiv_memory_loc[regno] != 0
-           && (reg_equiv_address[regno] != 0
+       if (reg_equiv_memory_loc (regno) != 0
+           && (reg_equiv_address (regno) != 0
                || num_not_at_initial_offset))
          {
            rtx tem = make_memloc (XEXP (x, 0), regno);
 
-           if (reg_equiv_address[regno]
-               || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+           if (reg_equiv_address (regno)
+               || ! rtx_equal_p (tem, reg_equiv_mem (regno)))
              {
                rtx orig = tem;
 
@@ -5609,8 +5732,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
                   register.  */
                reloadnum = push_reload (tem, tem, &XEXP (x, 0),
                                         &XEXP (op1, 0),
-                                        base_reg_class (mode, code,
-                                                        index_code),
+                                        base_reg_class (mode, as,
+                                                        code, index_code),
                                         GET_MODE (x), GET_MODE (x), 0,
                                         0, opnum, RELOAD_OTHER);
 
@@ -5623,11 +5746,12 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
          regno = reg_renumber[regno];
 
        /* We require a base register here...  */
-       if (!regno_ok_for_base_p (regno, GET_MODE (x), code, index_code))
+       if (!regno_ok_for_base_p (regno, GET_MODE (x), as, code, index_code))
          {
            reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
                                     &XEXP (op1, 0), &XEXP (x, 0),
-                                    base_reg_class (mode, code, index_code),
+                                    base_reg_class (mode, as,
+                                                    code, index_code),
                                     GET_MODE (x), GET_MODE (x), 0, 0,
                                     opnum, RELOAD_OTHER);
 
@@ -5649,16 +5773,16 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
 
          /* A register that is incremented cannot be constant!  */
          gcc_assert (regno < FIRST_PSEUDO_REGISTER
-                     || reg_equiv_constant[regno] == 0);
+                     || reg_equiv_constant (regno) == 0);
 
          /* Handle a register that is equivalent to a memory location
             which cannot be addressed directly.  */
-         if (reg_equiv_memory_loc[regno] != 0
-             && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
+         if (reg_equiv_memory_loc (regno) != 0
+             && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset))
            {
              rtx tem = make_memloc (XEXP (x, 0), regno);
-             if (reg_equiv_address[regno]
-                 || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+             if (reg_equiv_address (regno)
+                 || ! rtx_equal_p (tem, reg_equiv_mem (regno)))
                {
                  rtx orig = tem;
 
@@ -5693,7 +5817,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
          if (reg_renumber[regno] >= 0)
            regno = reg_renumber[regno];
          if (regno >= FIRST_PSEUDO_REGISTER
-             || !REG_OK_FOR_CONTEXT (context, regno, mode, code,
+             || !REG_OK_FOR_CONTEXT (context, regno, mode, as, code,
                                      index_code))
            {
              int reloadnum;
@@ -5708,18 +5832,16 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
                 Also don't do this if we can probably update x directly.  */
              rtx equiv = (MEM_P (XEXP (x, 0))
                           ? XEXP (x, 0)
-                          : reg_equiv_mem[regno]);
-             int icode = (int) optab_handler (add_optab, Pmode)->insn_code;
+                          : reg_equiv_mem (regno));
+             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
                  && ! sets_cc0_p (PATTERN (insn))
 #endif
                  && ! (icode != CODE_FOR_nothing
-                       && ((*insn_data[icode].operand[0].predicate)
-                           (equiv, Pmode))
-                       && ((*insn_data[icode].operand[1].predicate)
-                           (equiv, Pmode))))
+                       && insn_operand_matches (icode, 0, equiv)
+                       && insn_operand_matches (icode, 1, equiv)))
                {
                  /* We use the original pseudo for loc, so that
                     emit_reload_insns() knows which pseudo this
@@ -5764,7 +5886,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
         reloaded.  Targets that are better off reloading just either part
         (or perhaps even a different part of an outer expression), should
         define LEGITIMIZE_RELOAD_ADDRESS.  */
-      find_reloads_address_1 (GET_MODE (XEXP (x, 0)), XEXP (x, 0),
+      find_reloads_address_1 (GET_MODE (XEXP (x, 0)), as, XEXP (x, 0),
                              context, code, SCRATCH, &XEXP (x, 0), opnum,
                              type, ind_levels, insn);
       push_reload (x, NULL_RTX, loc, (rtx*) 0,
@@ -5796,9 +5918,9 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
       {
        int regno = REGNO (x);
 
-       if (reg_equiv_constant[regno] != 0)
+       if (reg_equiv_constant (regno) != 0)
          {
-           find_reloads_address_part (reg_equiv_constant[regno], loc,
+           find_reloads_address_part (reg_equiv_constant (regno), loc,
                                       context_reg_class,
                                       GET_MODE (x), opnum, type, ind_levels);
            return 1;
@@ -5806,21 +5928,21 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
 
 #if 0 /* This might screw code in reload1.c to delete prior output-reload
         that feeds this insn.  */
-       if (reg_equiv_mem[regno] != 0)
+       if (reg_equiv_mem (regno) != 0)
          {
-           push_reload (reg_equiv_mem[regno], NULL_RTX, loc, (rtx*) 0,
+           push_reload (reg_equiv_mem (regno), NULL_RTX, loc, (rtx*) 0,
                         context_reg_class,
                         GET_MODE (x), VOIDmode, 0, 0, opnum, type);
            return 1;
          }
 #endif
 
-       if (reg_equiv_memory_loc[regno]
-           && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
+       if (reg_equiv_memory_loc (regno)
+           && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset))
          {
            rtx tem = make_memloc (x, regno);
-           if (reg_equiv_address[regno] != 0
-               || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+           if (reg_equiv_address (regno) != 0
+               || ! rtx_equal_p (tem, reg_equiv_mem (regno)))
              {
                x = tem;
                find_reloads_address (GET_MODE (x), &x, XEXP (x, 0),
@@ -5835,7 +5957,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
          regno = reg_renumber[regno];
 
        if (regno >= FIRST_PSEUDO_REGISTER
-           || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+           || !REG_OK_FOR_CONTEXT (context, regno, mode, as, outer_code,
                                    index_code))
          {
            push_reload (x, NULL_RTX, loc, (rtx*) 0,
@@ -5868,7 +5990,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
            {
              int regno ATTRIBUTE_UNUSED = subreg_regno (x);
 
-             if (!REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+             if (!REG_OK_FOR_CONTEXT (context, regno, mode, as, outer_code,
                                       index_code))
                {
                  push_reload (x, NULL_RTX, loc, (rtx*) 0,
@@ -5881,14 +6003,14 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
             is larger than the class size, then reload the whole SUBREG.  */
          else
            {
-             enum reg_class class = context_reg_class;
-             if ((unsigned) CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
-                 > reg_class_size[class])
+             enum reg_class rclass = context_reg_class;
+             if (ira_reg_class_max_nregs [rclass][GET_MODE (SUBREG_REG (x))]
+                 > reg_class_size[(int) rclass])
                {
-                 x = find_reloads_subreg_address (x, 0, opnum, 
+                 x = find_reloads_subreg_address (x, 0, opnum,
                                                   ADDR_TYPE (type),
-                                                  ind_levels, insn);
-                 push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
+                                                  ind_levels, insn, NULL);
+                 push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass,
                               GET_MODE (x), VOIDmode, 0, 0, opnum, type);
                  return 1;
                }
@@ -5909,8 +6031,9 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
        if (fmt[i] == 'e')
          /* Pass SCRATCH for INDEX_CODE, since CODE can never be a PLUS once
             we get here.  */
-         find_reloads_address_1 (mode, XEXP (x, i), context, code, SCRATCH,
-                                 &XEXP (x, i), opnum, type, ind_levels, insn);
+         find_reloads_address_1 (mode, as, XEXP (x, i), context,
+                                 code, SCRATCH, &XEXP (x, i),
+                                 opnum, type, ind_levels, insn);
       }
   }
 
@@ -5919,7 +6042,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
 }
 \f
 /* X, which is found at *LOC, is a part of an address that needs to be
-   reloaded into a register of class CLASS.  If X is a constant, or if
+   reloaded into a register of class RCLASS.  If X is a constant, or if
    X is a PLUS that contains a constant, check that the constant is a
    legitimate operand and that we are supposed to be able to load
    it into the register.
@@ -5934,13 +6057,13 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
    supports.  */
 
 static void
-find_reloads_address_part (rtx x, rtx *loc, enum reg_class class,
+find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass,
                           enum machine_mode mode, int opnum,
                           enum reload_type type, int ind_levels)
 {
   if (CONSTANT_P (x)
-      && (! LEGITIMATE_CONSTANT_P (x)
-         || PREFERRED_RELOAD_CLASS (x, class) == NO_REGS))
+      && (!targetm.legitimate_constant_p (mode, x)
+         || targetm.preferred_reload_class (x, rclass) == NO_REGS))
     {
       x = force_const_mem (mode, x);
       find_reloads_address (mode, &x, XEXP (x, 0), &XEXP (x, 0),
@@ -5949,8 +6072,9 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class class,
 
   else if (GET_CODE (x) == PLUS
           && CONSTANT_P (XEXP (x, 1))
-          && (! LEGITIMATE_CONSTANT_P (XEXP (x, 1))
-              || PREFERRED_RELOAD_CLASS (XEXP (x, 1), class) == NO_REGS))
+          && (!targetm.legitimate_constant_p (GET_MODE (x), XEXP (x, 1))
+              || targetm.preferred_reload_class (XEXP (x, 1), rclass)
+                  == NO_REGS))
     {
       rtx tem;
 
@@ -5960,7 +6084,7 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class class,
                            opnum, type, ind_levels, 0);
     }
 
-  push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
+  push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass,
               mode, VOIDmode, 0, 0, opnum, type);
 }
 \f
@@ -5988,17 +6112,19 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class class,
 
 static rtx
 find_reloads_subreg_address (rtx x, int force_replace, int opnum,
-                            enum reload_type type, int ind_levels, rtx insn)
+                            enum reload_type type, int ind_levels, rtx insn,
+                            int *address_reloaded)
 {
   int regno = REGNO (SUBREG_REG (x));
+  int reloaded = 0;
 
-  if (reg_equiv_memory_loc[regno])
+  if (reg_equiv_memory_loc (regno))
     {
       /* If the address is not directly addressable, or if the address is not
         offsettable, then it must be replaced.  */
       if (! force_replace
-         && (reg_equiv_address[regno]
-             || ! offsettable_memref_p (reg_equiv_mem[regno])))
+         && (reg_equiv_address (regno)
+             || ! offsettable_memref_p (reg_equiv_mem (regno))))
        force_replace = 1;
 
       if (force_replace || num_not_at_initial_offset)
@@ -6008,14 +6134,12 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
          /* If the address changes because of register elimination, then
             it must be replaced.  */
          if (force_replace
-             || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+             || ! rtx_equal_p (tem, reg_equiv_mem (regno)))
            {
              unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
              unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
              int offset;
              rtx orig = tem;
-             enum machine_mode orig_mode = GET_MODE (orig);
-             int reloaded;
 
              /* For big-endian paradoxical subregs, SUBREG_BYTE does not
                 hold the correct (negative) byte offset.  */
@@ -6026,8 +6150,11 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
 
              XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
              PUT_MODE (tem, GET_MODE (x));
-             if (MEM_OFFSET (tem))
-               set_mem_offset (tem, plus_constant (MEM_OFFSET (tem), offset));
+             if (MEM_OFFSET_KNOWN_P (tem))
+               set_mem_offset (tem, MEM_OFFSET (tem) + offset);
+             if (MEM_SIZE_KNOWN_P (tem)
+                 && MEM_SIZE (tem) != (HOST_WIDE_INT) outer_size)
+               set_mem_size (tem, outer_size);
 
              /* If this was a paradoxical subreg that we replaced, the
                 resulting memory must be sufficiently aligned to allow
@@ -6039,7 +6166,7 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
                  base = XEXP (tem, 0);
                  if (GET_CODE (base) == PLUS)
                    {
-                     if (GET_CODE (XEXP (base, 1)) == CONST_INT
+                     if (CONST_INT_P (XEXP (base, 1))
                          && INTVAL (XEXP (base, 1)) % outer_size != 0)
                        return x;
                      base = XEXP (base, 0);
@@ -6060,22 +6187,36 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
              /* For some processors an address may be valid in the
                 original mode but not in a smaller mode.  For
                 example, ARM accepts a scaled index register in
-                SImode but not in HImode.  find_reloads_address
-                assumes that we pass it a valid address, and doesn't
-                force a reload.  This will probably be fine if
-                find_reloads_address finds some reloads.  But if it
-                doesn't find any, then we may have just converted a
-                valid address into an invalid one.  Check for that
-                here.  */
-             if (reloaded != 1
-                 && strict_memory_address_p (orig_mode, XEXP (tem, 0))
-                 && !strict_memory_address_p (GET_MODE (tem),
-                                              XEXP (tem, 0)))
-               push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
-                            base_reg_class (GET_MODE (tem), MEM, SCRATCH),
-                            GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
-                            opnum, type);
-
+                SImode but not in HImode.  Note that this is only
+                a problem if the address in reg_equiv_mem is already
+                invalid in the new mode; other cases would be fixed
+                by find_reloads_address as usual.
+
+                ??? We attempt to handle such cases here by doing an
+                additional reload of the full address after the
+                usual processing by find_reloads_address.  Note that
+                this may not work in the general case, but it seems
+                to cover the cases where this situation currently
+                occurs.  A more general fix might be to reload the
+                *value* instead of the address, but this would not
+                be expected by the callers of this routine as-is.
+
+                If find_reloads_address already completed replaced
+                the address, there is nothing further to do.  */
+             if (reloaded == 0
+                 && reg_equiv_mem (regno) != 0
+                 && !strict_memory_address_addr_space_p
+                       (GET_MODE (x), XEXP (reg_equiv_mem (regno), 0),
+                        MEM_ADDR_SPACE (reg_equiv_mem (regno))))
+               {
+                 push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
+                              base_reg_class (GET_MODE (tem),
+                                              MEM_ADDR_SPACE (tem),
+                                              MEM, SCRATCH),
+                              GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
+                              opnum, type);
+                 reloaded = 1;
+               }
              /* If this is not a toplevel operand, find_reloads doesn't see
                 this substitution.  We have to emit a USE of the pseudo so
                 that delete_output_reload can see it.  */
@@ -6090,6 +6231,9 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
            }
        }
     }
+  if (address_reloaded)
+    *address_reloaded = reloaded;
+
   return x;
 }
 \f
@@ -6128,14 +6272,14 @@ subst_reloads (rtx insn)
          for (check_regno = 0; check_regno < max_regno; check_regno++)
            {
 #define CHECK_MODF(ARRAY)                                              \
-             gcc_assert (!ARRAY[check_regno]                           \
+             gcc_assert (!VEC_index (reg_equivs_t, reg_equivs, check_regno).ARRAY              \
                          || !loc_mentioned_in_p (r->where,             \
-                                                 ARRAY[check_regno]))
+                                                 VEC_index (reg_equivs_t, reg_equivs, check_regno).ARRAY))
 
-             CHECK_MODF (reg_equiv_constant);
-             CHECK_MODF (reg_equiv_memory_loc);
-             CHECK_MODF (reg_equiv_address);
-             CHECK_MODF (reg_equiv_mem);
+             CHECK_MODF (equiv_constant);
+             CHECK_MODF (equiv_memory_loc);
+             CHECK_MODF (equiv_address);
+             CHECK_MODF (equiv_mem);
 #undef CHECK_MODF
            }
 #endif /* DEBUG_RELOAD */
@@ -6157,33 +6301,7 @@ subst_reloads (rtx insn)
          if (GET_MODE (reloadreg) != r->mode && r->mode != VOIDmode)
            reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode);
 
-         /* If we are putting this into a SUBREG and RELOADREG is a
-            SUBREG, we would be making nested SUBREGs, so we have to fix
-            this up.  Note that r->where == &SUBREG_REG (*r->subreg_loc).  */
-
-         if (r->subreg_loc != 0 && GET_CODE (reloadreg) == SUBREG)
-           {
-             if (GET_MODE (*r->subreg_loc)
-                 == GET_MODE (SUBREG_REG (reloadreg)))
-               *r->subreg_loc = SUBREG_REG (reloadreg);
-             else
-               {
-                 int final_offset =
-                   SUBREG_BYTE (*r->subreg_loc) + SUBREG_BYTE (reloadreg);
-
-                 /* When working with SUBREGs the rule is that the byte
-                    offset must be a multiple of the SUBREG's mode.  */
-                 final_offset = (final_offset /
-                                 GET_MODE_SIZE (GET_MODE (*r->subreg_loc)));
-                 final_offset = (final_offset *
-                                 GET_MODE_SIZE (GET_MODE (*r->subreg_loc)));
-
-                 *r->where = SUBREG_REG (reloadreg);
-                 SUBREG_BYTE (*r->subreg_loc) = final_offset;
-               }
-           }
-         else
-           *r->where = reloadreg;
+         *r->where = reloadreg;
        }
       /* If reload got no reg and isn't optional, something's wrong.  */
       else
@@ -6197,10 +6315,6 @@ subst_reloads (rtx insn)
 void
 copy_replacements (rtx x, rtx y)
 {
-  /* We can't support X being a SUBREG because we might then need to know its
-     location if something inside it was replaced.  */
-  gcc_assert (GET_CODE (x) != SUBREG);
-
   copy_replacements_1 (&x, &y, n_replacements);
 }
 
@@ -6214,24 +6328,13 @@ copy_replacements_1 (rtx *px, rtx *py, int orig_replacements)
   const char *fmt;
 
   for (j = 0; j < orig_replacements; j++)
-    {
-      if (replacements[j].subreg_loc == px)
-       {
-         r = &replacements[n_replacements++];
-         r->where = replacements[j].where;
-         r->subreg_loc = py;
-         r->what = replacements[j].what;
-         r->mode = replacements[j].mode;
-       }
-      else if (replacements[j].where == px)
-       {
-         r = &replacements[n_replacements++];
-         r->where = py;
-         r->subreg_loc = 0;
-         r->what = replacements[j].what;
-         r->mode = replacements[j].mode;
-       }
-    }
+    if (replacements[j].where == px)
+      {
+       r = &replacements[n_replacements++];
+       r->where = py;
+       r->what = replacements[j].what;
+       r->mode = replacements[j].mode;
+      }
 
   x = *px;
   y = *py;
@@ -6257,13 +6360,8 @@ move_replacements (rtx *x, rtx *y)
   int i;
 
   for (i = 0; i < n_replacements; i++)
-    if (replacements[i].subreg_loc == x)
-      replacements[i].subreg_loc = y;
-    else if (replacements[i].where == x)
-      {
-       replacements[i].where = y;
-       replacements[i].subreg_loc = 0;
-      }
+    if (replacements[i].where == x)
+      replacements[i].where = y;
 }
 \f
 /* If LOC was scheduled to be replaced by something, return the replacement.
@@ -6281,36 +6379,19 @@ find_replacement (rtx *loc)
       if (reloadreg && r->where == loc)
        {
          if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
-           reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg));
+           reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode);
 
          return reloadreg;
        }
-      else if (reloadreg && r->subreg_loc == loc)
+      else if (reloadreg && GET_CODE (*loc) == SUBREG
+              && r->where == &SUBREG_REG (*loc))
        {
-         /* RELOADREG must be either a REG or a SUBREG.
-
-            ??? Is it actually still ever a SUBREG?  If so, why?  */
-
-         if (REG_P (reloadreg))
-           return gen_rtx_REG (GET_MODE (*loc),
-                               (REGNO (reloadreg) +
-                                subreg_regno_offset (REGNO (SUBREG_REG (*loc)),
-                                                     GET_MODE (SUBREG_REG (*loc)),
-                                                     SUBREG_BYTE (*loc),
-                                                     GET_MODE (*loc))));
-         else if (GET_MODE (reloadreg) == GET_MODE (*loc))
-           return reloadreg;
-         else
-           {
-             int final_offset = SUBREG_BYTE (reloadreg) + SUBREG_BYTE (*loc);
-
-             /* When working with SUBREGs the rule is that the byte
-                offset must be a multiple of the SUBREG's mode.  */
-             final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (*loc)));
-             final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (*loc)));
-             return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg),
-                                    final_offset);
-           }
+         if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
+           reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode);
+
+         return simplify_gen_subreg (GET_MODE (*loc), reloadreg,
+                                     GET_MODE (SUBREG_REG (*loc)),
+                                     SUBREG_BYTE (*loc));
        }
     }
 
@@ -6363,12 +6444,12 @@ refers_to_regno_for_reload_p (unsigned int regno, unsigned int endregno,
         X must therefore either be a constant or be in memory.  */
       if (r >= FIRST_PSEUDO_REGISTER)
        {
-         if (reg_equiv_memory_loc[r])
+         if (reg_equiv_memory_loc (r))
            return refers_to_regno_for_reload_p (regno, endregno,
-                                                reg_equiv_memory_loc[r],
+                                                reg_equiv_memory_loc (r),
                                                 (rtx*) 0);
 
-         gcc_assert (reg_equiv_constant[r] || reg_equiv_invariant[r]);
+         gcc_assert (reg_equiv_constant (r) || reg_equiv_invariant (r));
          return 0;
        }
 
@@ -6474,7 +6555,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
   /* If either argument is a constant, then modifying X can not affect IN.  */
   if (CONSTANT_P (x) || CONSTANT_P (in))
     return 0;
-  else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
+  else if (GET_CODE (x) == SUBREG && MEM_P (SUBREG_REG (x)))
     return refers_to_mem_for_reload_p (in);
   else if (GET_CODE (x) == SUBREG)
     {
@@ -6498,9 +6579,9 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
 
       if (regno >= FIRST_PSEUDO_REGISTER)
        {
-         if (reg_equiv_memory_loc[regno])
+         if (reg_equiv_memory_loc (regno))
            return refers_to_mem_for_reload_p (in);
-         gcc_assert (reg_equiv_constant[regno]);
+         gcc_assert (reg_equiv_constant (regno));
          return 0;
        }
 
@@ -6513,7 +6594,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
   else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
           || GET_CODE (x) == CC0)
     return reg_mentioned_p (x, in);
-  else 
+  else
     {
       gcc_assert (GET_CODE (x) == PLUS);
 
@@ -6551,7 +6632,7 @@ refers_to_mem_for_reload_p (rtx x)
 
   if (REG_P (x))
     return (REGNO (x) >= FIRST_PSEUDO_REGISTER
-           && reg_equiv_memory_loc[REGNO (x)]);
+           && reg_equiv_memory_loc (REGNO (x)));
 
   fmt = GET_RTX_FORMAT (GET_CODE (x));
   for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
@@ -6565,7 +6646,7 @@ refers_to_mem_for_reload_p (rtx x)
 \f
 /* Check the insns before INSN to see if there is a suitable register
    containing the same value as GOAL.
-   If OTHER is -1, look for a register in class CLASS.
+   If OTHER is -1, look for a register in class RCLASS.
    Otherwise, just see if register number OTHER shares GOAL's value.
 
    Return an rtx for the register found, or zero if none is found.
@@ -6591,7 +6672,7 @@ 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 class, int other,
+find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other,
                short *reload_reg_p, int goalreg, enum machine_mode mode)
 {
   rtx p = insn;
@@ -6654,11 +6735,22 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
   while (1)
     {
       p = PREV_INSN (p);
+      if (p && DEBUG_INSN_P (p))
+       continue;
       num++;
       if (p == 0 || LABEL_P (p)
          || num > PARAM_VALUE (PARAM_MAX_RELOAD_SEARCH_INSNS))
        return 0;
 
+      /* Don't reuse register contents from before a setjmp-type
+        function call; on the second return (from the longjmp) it
+        might have been clobbered by a later reuse.  It doesn't
+        seem worthwhile to actually go and see if it is actually
+        reused even if that information would be readily available;
+        just don't reuse it across the setjmp call.  */
+      if (CALL_P (p) && find_reg_note (p, REG_SETJMP, NULL_RTX))
+       return 0;
+
       if (NONJUMP_INSN_P (p)
          /* If we don't want spill regs ...  */
          && (! (reload_reg_p != 0
@@ -6708,7 +6800,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                          || (REG_P (SET_DEST (pat))
                              && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
                              && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
-                             && GET_CODE (goal) == CONST_INT
+                             && CONST_INT_P (goal)
                              && 0 != (goaltry
                                       = operand_subword (XEXP (tem, 0), 0, 0,
                                                          VOIDmode))
@@ -6722,7 +6814,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                      && REG_P (SET_DEST (pat))
                      && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
                      && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
-                     && GET_CODE (goal) == CONST_INT
+                     && CONST_INT_P (goal)
                      && 0 != (goaltry = operand_subword (XEXP (tem, 0), 1, 0,
                                                          VOIDmode))
                      && rtx_equal_p (goal, goaltry)
@@ -6737,7 +6829,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                }
              else if ((unsigned) valueno >= FIRST_PSEUDO_REGISTER)
                continue;
-             else if (!in_hard_reg_set_p (reg_class_contents[(int) class],
+             else if (!in_hard_reg_set_p (reg_class_contents[(int) rclass],
                                          mode, valueno))
                continue;
              value = valtry;
@@ -6903,7 +6995,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                       && ! push_operand (dest, GET_MODE (dest)))
                return 0;
              else if (MEM_P (dest) && regno >= FIRST_PSEUDO_REGISTER
-                      && reg_equiv_memory_loc[regno] != 0)
+                      && reg_equiv_memory_loc (regno) != 0)
                return 0;
              else if (need_stable_sp && push_operand (dest, GET_MODE (dest)))
                return 0;
@@ -6948,7 +7040,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                               && ! push_operand (dest, GET_MODE (dest)))
                        return 0;
                      else if (MEM_P (dest) && regno >= FIRST_PSEUDO_REGISTER
-                              && reg_equiv_memory_loc[regno] != 0)
+                              && reg_equiv_memory_loc (regno) != 0)
                        return 0;
                      else if (need_stable_sp
                               && push_operand (dest, GET_MODE (dest)))
@@ -7050,7 +7142,7 @@ find_inc_amount (rtx x, rtx inced)
               && GET_CODE (XEXP (addr, 1)) == PLUS
               && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
               && XEXP (addr, 0) == inced
-              && GET_CODE (XEXP (XEXP (addr, 1), 1)) == CONST_INT)
+              && CONST_INT_P (XEXP (XEXP (addr, 1), 1)))
        {
          i = INTVAL (XEXP (XEXP (addr, 1), 1));
          return i < 0 ? -i : i;
@@ -7085,7 +7177,7 @@ find_inc_amount (rtx x, rtx inced)
    REG_INC note in insn INSN.  REGNO must refer to a hard register.  */
 
 #ifdef AUTO_INC_DEC
-static int 
+static int
 reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno,
                           rtx insn)
 {
@@ -7095,13 +7187,13 @@ reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno,
 
   if (! INSN_P (insn))
     return 0;
-    
+
   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
     if (REG_NOTE_KIND (link) == REG_INC)
       {
        unsigned int test = (int) REGNO (XEXP (link, 0));
        if (test >= regno && test < endregno)
-         return 1; 
+         return 1;
       }
   return 0;
 }
@@ -7109,7 +7201,7 @@ reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno,
 
 #define reg_inc_found_and_valid_p(regno,endregno,insn) 0
 
-#endif 
+#endif
 
 /* Return 1 if register REGNO is the subject of a clobber in insn INSN.
    If SETS is 1, also consider SETs.  If SETS is 2, enable checking
@@ -7137,8 +7229,8 @@ regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
     }
 
   if (sets == 2 && reg_inc_found_and_valid_p (regno, endregno, insn))
-    return 1; 
-  
+    return 1;
+
   if (GET_CODE (PATTERN (insn)) == PARALLEL)
     {
       int i = XVECLEN (PATTERN (insn), 0) - 1;
@@ -7147,7 +7239,7 @@ regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
        {
          rtx elt = XVECEXP (PATTERN (insn), 0, i);
          if ((GET_CODE (elt) == CLOBBER
-              || (sets == 1 && GET_CODE (PATTERN (insn)) == SET))
+              || (sets == 1 && GET_CODE (elt) == SET))
              && REG_P (XEXP (elt, 0)))
            {
              unsigned int test = REGNO (XEXP (elt, 0));
@@ -7157,7 +7249,7 @@ regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
            }
          if (sets == 2
              && reg_inc_found_and_valid_p (regno, endregno, elt))
-           return 1; 
+           return 1;
        }
     }
 
@@ -7175,7 +7267,7 @@ reload_adjust_reg_for_mode (rtx reloadreg, enum machine_mode mode)
 
   regno = REGNO (reloadreg);
 
-  if (WORDS_BIG_ENDIAN)
+  if (REG_WORDS_BIG_ENDIAN)
     regno += (int) hard_regno_nregs[regno][GET_MODE (reloadreg)]
       - (int) hard_regno_nregs[regno][mode];
 
@@ -7199,7 +7291,7 @@ static const char *const reload_when_needed_name[] =
 
 /* These functions are used to print the variables set by 'find_reloads' */
 
-void
+DEBUG_FUNCTION void
 debug_reload_to_stream (FILE *f)
 {
   int r;
@@ -7227,7 +7319,7 @@ debug_reload_to_stream (FILE *f)
          fprintf (f, "\n\t");
        }
 
-      fprintf (f, "%s, ", reg_class_names[(int) rld[r].class]);
+      fprintf (f, "%s, ", reg_class_names[(int) rld[r].rclass]);
 
       fprintf (f, "%s (opnum = %d)",
               reload_when_needed_name[(int) rld[r].when_needed],
@@ -7294,7 +7386,7 @@ debug_reload_to_stream (FILE *f)
     }
 }
 
-void
+DEBUG_FUNCTION void
 debug_reload (void)
 {
   debug_reload_to_stream (stderr);