OSDN Git Service

PR c++/47132
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index 93fff40..045e559 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, 2008
+   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
@@ -259,7 +265,7 @@ 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);
@@ -267,7 +273,8 @@ 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);
@@ -280,7 +287,7 @@ 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 +302,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
@@ -357,13 +364,14 @@ 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;
-  rclass = 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 (rclass == NO_REGS && icode == CODE_FOR_nothing)
@@ -436,7 +444,8 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
            || (! 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 (rclass) || 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))
       {
@@ -515,17 +524,18 @@ 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 rclass,
-                       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;
-  rclass = targetm.secondary_reload (in_p, x, rclass, 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.  */
@@ -611,7 +621,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);
@@ -685,15 +696,16 @@ find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
 
       if (bad || !good)
        continue;
-      cost = REGISTER_MOVE_COST (outer, rclass, dest_class);
+      cost = register_move_cost (outer, (enum reg_class) rclass, dest_class);
 
       if ((reg_class_size[rclass] > best_size
           && (best_cost < 0 || best_cost >= cost))
          || best_cost > cost)
        {
-         best_class = rclass;
+         best_class = (enum reg_class) rclass;
          best_size = reg_class_size[rclass];
-         best_cost = REGISTER_MOVE_COST (outer, rclass, dest_class);
+         best_cost = register_move_cost (outer, (enum reg_class) rclass,
+                                         dest_class);
        }
     }
 
@@ -727,9 +739,9 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
      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 (rclass, rld[i].rclass)
@@ -743,7 +755,8 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
            || (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 (rclass) || 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;
 
@@ -768,7 +781,8 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
                && 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 (rclass) || 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))
       {
@@ -937,7 +951,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
@@ -950,7 +964,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,
@@ -1211,21 +1225,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 = rclass;
+    reg_class_t preferred_class = rclass;
 
     if (in != 0)
-      preferred_class = PREFERRED_RELOAD_CLASS (in, rclass);
+      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))
-      rclass = preferred_class;
+      rclass = (enum reg_class) preferred_class;
   }
 
   /* Make sure we use a class that can handle the actual pseudo
@@ -1282,7 +1295,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;
        }
     }
@@ -1403,13 +1416,36 @@ 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 (rclass, rld[i].rclass))
        rld[i].rclass = rclass;
@@ -1493,7 +1529,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;
     }
@@ -1526,8 +1562,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,
@@ -1743,7 +1779,7 @@ 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
+       && (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)
@@ -1767,7 +1803,7 @@ combine_reloads (void)
        && ! reload_inner_reg_of_subreg (rld[i].in, rld[i].inmode,
                                         rld[i].when_needed != RELOAD_FOR_INPUT)
        && (reg_class_size[(int) rld[i].rclass]
-           || SMALL_REGISTER_CLASSES)
+           || 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
@@ -1884,7 +1920,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 rclass, int for_real, int earlyclobber)
+                  reg_class_t rclass, int for_real, int earlyclobber)
 {
   rtx in = real_in;
   rtx out = real_out;
@@ -1927,9 +1963,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, rclass);
+    reg_class_t preferred_class = targetm.preferred_reload_class (in, rclass);
     if (preferred_class != NO_REGS)
-      rclass = preferred_class;
+      rclass = (enum reg_class) preferred_class;
   }
 
   /* See if OUT will do.  */
@@ -2004,7 +2040,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
@@ -2104,18 +2140,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
@@ -2218,6 +2260,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:
@@ -2312,7 +2358,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)
          {
@@ -2322,7 +2368,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
@@ -2336,7 +2382,7 @@ decompose (rtx x)
                return val;
              }
          }
-       
+
        if (GET_CODE (addr) == CONST)
          {
            addr = XEXP (addr, 0);
@@ -2355,7 +2401,7 @@ decompose (rtx x)
                offset = XEXP (addr, 1);
              }
          }
-       
+
        if (offset == 0)
          {
            base = addr;
@@ -2365,12 +2411,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);
@@ -2381,23 +2427,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);
@@ -2528,7 +2574,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
      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.
@@ -2542,14 +2588,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];
@@ -2611,7 +2657,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;
@@ -2811,10 +2857,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;
        }
@@ -2835,7 +2881,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
@@ -2845,10 +2891,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]
@@ -2972,12 +3018,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),
@@ -3037,7 +3082,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;
@@ -3124,7 +3169,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;
 
@@ -3140,7 +3185,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.
@@ -3189,8 +3234,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              case 'p':
                /* All necessary reloads for an address_operand
                   were handled in find_reloads_address.  */
-               this_alternative[i]
-                 = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
+               this_alternative[i] = base_reg_class (VOIDmode, ADDRESS,
+                                                     SCRATCH);
                win = 1;
                badop = 0;
                break;
@@ -3203,7 +3248,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;
@@ -3237,7 +3282,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;
 
@@ -3261,11 +3306,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;
@@ -3295,7 +3340,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;
@@ -3306,7 +3351,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;
@@ -3320,7 +3365,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;
@@ -3349,7 +3394,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:
@@ -3373,15 +3418,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;
@@ -3395,8 +3440,9 @@ 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);
+                       this_alternative[i] = base_reg_class (VOIDmode,
+                                                             ADDRESS,
+                                                             SCRATCH);
                        badop = 0;
                        break;
                      }
@@ -3408,9 +3454,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;
@@ -3427,7 +3473,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.  */
@@ -3446,7 +3493,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;
 
@@ -3458,15 +3505,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++;
                }
 
@@ -3486,21 +3532,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,
@@ -3546,10 +3588,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]))
@@ -3560,7 +3602,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]);
                }
@@ -3595,7 +3637,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
@@ -3607,7 +3649,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))
                    {
@@ -3672,22 +3714,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;
        }
     }
 
@@ -3865,12 +3912,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
            op = XEXP (op, 1);
          }
 
-       if (CONST_POOL_OK_P (op)
-           && ((PREFERRED_RELOAD_CLASS (op,
-                                        (enum reg_class) goal_alternative[i])
+       if (CONST_POOL_OK_P (mode, op)
+           && ((targetm.preferred_reload_class (op, goal_alternative[i])
                 == NO_REGS)
-               || no_input_reloads)
-           && mode != VOIDmode)
+               || no_input_reloads))
          {
            int this_address_reloaded;
            rtx tem = force_const_mem (mode, op);
@@ -3925,12 +3970,15 @@ 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.  */
            enum machine_mode address_mode;
            address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
            if (address_mode == VOIDmode)
-             address_mode = Pmode;
+             {
+               addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]);
+               address_mode = targetm.addr_space.address_mode (as);
+             }
 
            operand_reloadnum[i]
              = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
@@ -4042,7 +4090,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.
@@ -4116,8 +4164,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],
@@ -4208,7 +4255,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
@@ -4535,7 +4582,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
    is null.  */
 
 static bool
-alternative_allows_const_pool_ref (rtx mem, const char *constraint, int altnum)
+alternative_allows_const_pool_ref (rtx mem ATTRIBUTE_UNUSED,
+                                  const char *constraint, int altnum)
 {
   int c;
 
@@ -4604,20 +4652,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
@@ -4667,13 +4715,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),
@@ -4703,14 +4752,15 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
               && (GET_MODE_SIZE (GET_MODE (x))
                   <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (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])
+              && (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--)
@@ -4745,36 +4795,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;
@@ -4810,6 +4862,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;
@@ -4823,21 +4877,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,
+         find_reloads_address_part (reg_equiv_constant (regno), loc,
                                     base_reg_class (mode, 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;
 
@@ -4853,7 +4909,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))
@@ -4864,7 +4920,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
@@ -4897,7 +4953,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
       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.
@@ -4908,9 +4964,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;
@@ -4920,14 +4976,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);
@@ -4988,7 +5044,7 @@ 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.  */
@@ -5010,9 +5066,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, 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.  */
@@ -5024,7 +5085,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,
+                                 PLUS, CONST_INT))
        {
          /* Unshare the sum as well.  */
          *loc = ad = copy_rtx (ad);
@@ -5043,7 +5106,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
             That will at least work.  */
          find_reloads_address_part (ad, loc,
                                     base_reg_class (mode, MEM, SCRATCH),
-                                    Pmode, opnum, type, ind_levels);
+                                    GET_MODE (ad), opnum, type, ind_levels);
        }
       return ! removed_and;
     }
@@ -5083,8 +5146,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;
 
@@ -5097,15 +5160,15 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
       if ((regno_ok_for_base_p (REGNO (operand), mode, 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;
@@ -5114,17 +5177,17 @@ 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), 
+         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,
@@ -5143,7 +5206,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.  */
@@ -5153,7 +5216,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;
@@ -5162,8 +5226,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
@@ -5176,7 +5244,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
        }
 
       find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
-                                Pmode, opnum, type, ind_levels);
+                                address_mode, opnum, type, ind_levels);
       return ! removed_and;
     }
 
@@ -5215,15 +5283,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
@@ -5240,7 +5308,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;
 
@@ -5263,31 +5331,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.  */
@@ -5330,13 +5394,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;
@@ -5354,9 +5418,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;
     }
@@ -5426,7 +5490,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
 #define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, OUTER, INDEX)         \
   ((CONTEXT) == 0                                                      \
    ? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX)                   \
-   : REGNO_OK_FOR_INDEX_P (REGNO))                                     
+   : REGNO_OK_FOR_INDEX_P (REGNO))
 
   enum reg_class context_reg_class;
   RTX_CODE code = GET_CODE (x);
@@ -5625,18 +5689,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;
 
@@ -5696,16 +5760,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;
 
@@ -5755,18 +5819,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
@@ -5843,9 +5905,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;
@@ -5853,21 +5915,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),
@@ -5932,9 +5994,9 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
              if ((unsigned) CLASS_MAX_NREGS (rclass, GET_MODE (SUBREG_REG (x)))
                  > reg_class_size[rclass])
                {
-                 x = find_reloads_subreg_address (x, 0, opnum, 
+                 x = find_reloads_subreg_address (x, 0, opnum,
                                                   ADDR_TYPE (type),
-                                                  ind_levels, insn);
+                                                  ind_levels, insn, NULL);
                  push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass,
                               GET_MODE (x), VOIDmode, 0, 0, opnum, type);
                  return 1;
@@ -5986,8 +6048,8 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass,
                           enum reload_type type, int ind_levels)
 {
   if (CONSTANT_P (x)
-      && (! LEGITIMATE_CONSTANT_P (x)
-         || PREFERRED_RELOAD_CLASS (x, rclass) == 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),
@@ -5996,8 +6058,9 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass,
 
   else if (GET_CODE (x) == PLUS
           && CONSTANT_P (XEXP (x, 1))
-          && (! LEGITIMATE_CONSTANT_P (XEXP (x, 1))
-              || PREFERRED_RELOAD_CLASS (XEXP (x, 1), rclass) == NO_REGS))
+          && (!targetm.legitimate_constant_p (GET_MODE (x), XEXP (x, 1))
+              || targetm.preferred_reload_class (XEXP (x, 1), rclass)
+                  == NO_REGS))
     {
       rtx tem;
 
@@ -6035,17 +6098,19 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass,
 
 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)
@@ -6055,13 +6120,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;
-             int reloaded;
 
              /* For big-endian paradoxical subregs, SUBREG_BYTE does not
                 hold the correct (negative) byte offset.  */
@@ -6074,6 +6138,9 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
              PUT_MODE (tem, GET_MODE (x));
              if (MEM_OFFSET (tem))
                set_mem_offset (tem, plus_constant (MEM_OFFSET (tem), offset));
+             if (MEM_SIZE (tem)
+                 && INTVAL (MEM_SIZE (tem)) != (HOST_WIDE_INT) outer_size)
+               set_mem_size (tem, GEN_INT (outer_size));
 
              /* If this was a paradoxical subreg that we replaced, the
                 resulting memory must be sufficiently aligned to allow
@@ -6085,7 +6152,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);
@@ -6106,23 +6173,34 @@ 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.  Similarly, the address may
-                have been valid before the subreg offset was added,
-                but not afterwards.  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.  */
+                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
-                 && !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);
-
+                 && 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, 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.  */
@@ -6137,6 +6215,9 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
            }
        }
     }
+  if (reloaded && address_reloaded)
+    *address_reloaded = 1;
+
   return x;
 }
 \f
@@ -6175,14 +6256,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 */
@@ -6410,12 +6491,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;
        }
 
@@ -6521,7 +6602,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)
     {
@@ -6545,9 +6626,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;
        }
 
@@ -6560,7 +6641,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);
 
@@ -6598,7 +6679,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--)
@@ -6701,6 +6782,8 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, 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))
@@ -6755,7 +6838,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, 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))
@@ -6769,7 +6852,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, 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)
@@ -6950,7 +7033,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, 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;
@@ -6995,7 +7078,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, 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)))
@@ -7097,7 +7180,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;
@@ -7132,7 +7215,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)
 {
@@ -7142,13 +7225,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;
 }
@@ -7156,7 +7239,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
@@ -7184,8 +7267,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;
@@ -7204,7 +7287,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;
        }
     }
 
@@ -7246,7 +7329,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;
@@ -7341,7 +7424,7 @@ debug_reload_to_stream (FILE *f)
     }
 }
 
-void
+DEBUG_FUNCTION void
 debug_reload (void)
 {
   debug_reload_to_stream (stderr);