OSDN Git Service

PR middle-end/24750
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index b114dc2..0503f5a 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 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 /* This file contains subroutines used only from the file reload1.c.
    It knows how to scan one insn for operands and values
@@ -108,19 +108,18 @@ a register with any other reload.  */
 #include "params.h"
 #include "target.h"
 
-#ifndef REGNO_MODE_OK_FOR_BASE_P
-#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) REGNO_OK_FOR_BASE_P (REGNO)
-#endif
-
-#ifndef REG_MODE_OK_FOR_BASE_P
-#define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO)
-#endif
-
 /* True if X is a constant that can be forced into the constant pool.  */
 #define CONST_POOL_OK_P(X)                     \
   (CONSTANT_P (X)                              \
    && GET_CODE (X) != HIGH                     \
    && !targetm.cannot_force_const_mem (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)))
+
 \f
 /* All reloads of the current insn are recorded here.  See reload.h for
    comments.  */
@@ -248,7 +247,8 @@ static int push_secondary_reload (int, rtx, int, int, enum reg_class,
                                  enum machine_mode, enum reload_type,
                                  enum insn_code *);
 #endif
-static enum reg_class find_valid_class (enum machine_mode, int, unsigned int);
+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 *);
@@ -279,6 +279,9 @@ static rtx find_reloads_subreg_address (rtx, int, int, enum reload_type,
                                        int, rtx);
 static void copy_replacements_1 (rtx *, rtx *, int);
 static int find_inc_amount (rtx, rtx);
+static int refers_to_mem_for_reload_p (rtx);
+static int refers_to_regno_for_reload_p (unsigned int, unsigned int,
+                                        rtx, rtx *);
 \f
 #ifdef HAVE_SECONDARY_RELOADS
 
@@ -388,17 +391,15 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
               : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
                                            insn_constraint));
 
-          if (insn_class == NO_REGS)
-           abort ();
-         if (in_p
-             && insn_data[(int) icode].operand[!in_p].constraint[0] != '=')
-           abort ();
+          gcc_assert (insn_class != NO_REGS);
+         gcc_assert (!in_p
+                     || insn_data[(int) icode].operand[!in_p].constraint[0]
+                        == '=');
        }
 
       /* The scratch register's constraint must start with "=&".  */
-      if (insn_data[(int) icode].operand[2].constraint[0] != '='
-         || insn_data[(int) icode].operand[2].constraint[1] != '&')
-       abort ();
+      gcc_assert (insn_data[(int) icode].operand[2].constraint[0] == '='
+                 && insn_data[(int) icode].operand[2].constraint[1] == '&');
 
       if (reg_class_subset_p (reload_class, insn_class))
        mode = insn_data[(int) icode].operand[2].mode;
@@ -431,9 +432,8 @@ 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.  */
 
-  if (in_p && class == reload_class && icode == CODE_FOR_nothing
-      && t_icode == CODE_FOR_nothing)
-    abort ();
+  gcc_assert (!in_p || class != reload_class || icode != CODE_FOR_nothing
+             || t_icode != CODE_FOR_nothing);
 
   /* If we need a tertiary reload, see if we have one we can reuse or else
      make a new one.  */
@@ -450,7 +450,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
                          == CODE_FOR_nothing))
                || (! in_p &&(rld[t_reload].secondary_out_icode
                              == CODE_FOR_nothing)))
-           && (reg_class_size[(int) t_class] == 1 || SMALL_REGISTER_CLASSES)
+           && (SMALL_REGISTER_CLASS_P (t_class) || SMALL_REGISTER_CLASSES)
            && MERGABLE_RELOADS (secondary_type,
                                 rld[t_reload].when_needed,
                                 opnum, rld[t_reload].opnum))
@@ -508,7 +508,7 @@ 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))
-       && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
+       && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
        && MERGABLE_RELOADS (secondary_type, rld[s_reload].when_needed,
                             opnum, rld[s_reload].opnum))
       {
@@ -667,12 +667,15 @@ clear_secondary_mem (void)
 }
 #endif /* SECONDARY_MEMORY_NEEDED */
 \f
-/* Find the largest class for which every register number plus N is valid in
-   M1 (if in range) and is cheap to move into REGNO.
-   Abort if no such class exists.  */
+
+/* Find the largest class which has at least one register valid in
+   mode INNER, and which for every such register, that register number
+   plus N is also valid in OUTER (if in range) and is cheap to move
+   into REGNO.  Such a class must exist.  */
 
 static enum reg_class
-find_valid_class (enum machine_mode m1 ATTRIBUTE_UNUSED, int n,
+find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
+                 enum machine_mode inner ATTRIBUTE_UNUSED, int n,
                  unsigned int dest_regno ATTRIBUTE_UNUSED)
 {
   int best_cost = -1;
@@ -686,15 +689,22 @@ find_valid_class (enum machine_mode m1 ATTRIBUTE_UNUSED, int n,
   for (class = 1; class < N_REG_CLASSES; class++)
     {
       int bad = 0;
-      for (regno = 0; regno < FIRST_PSEUDO_REGISTER && ! bad; regno++)
-       if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
-           && TEST_HARD_REG_BIT (reg_class_contents[class], regno + n)
-           && ! HARD_REGNO_MODE_OK (regno + n, m1))
-         bad = 1;
+      int good = 0;
+      for (regno = 0; regno < FIRST_PSEUDO_REGISTER - n && ! bad; regno++)
+       if (TEST_HARD_REG_BIT (reg_class_contents[class], regno))
+         {
+           if (HARD_REGNO_MODE_OK (regno, inner))
+             {
+               good = 1;
+               if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno + n)
+                   || ! HARD_REGNO_MODE_OK (regno + n, outer))
+                 bad = 1;
+             }
+         }
 
-      if (bad)
+      if (bad || !good)
        continue;
-      cost = REGISTER_MOVE_COST (m1, class, dest_class);
+      cost = REGISTER_MOVE_COST (outer, class, dest_class);
 
       if ((reg_class_size[class] > best_size
           && (best_cost < 0 || best_cost >= cost))
@@ -702,12 +712,11 @@ find_valid_class (enum machine_mode m1 ATTRIBUTE_UNUSED, int n,
        {
          best_class = class;
          best_size = reg_class_size[class];
-         best_cost = REGISTER_MOVE_COST (m1, class, dest_class);
+         best_cost = REGISTER_MOVE_COST (outer, class, dest_class);
        }
     }
 
-  if (best_size == 0)
-    abort ();
+  gcc_assert (best_size != 0);
 
   return best_class;
 }
@@ -753,7 +762,7 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class class,
            || (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))
-       && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
+       && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
        && MERGABLE_RELOADS (type, rld[i].when_needed, opnum, rld[i].opnum))
       return i;
 
@@ -778,7 +787,7 @@ 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))
-       && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
+       && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
        && MERGABLE_RELOADS (type, rld[i].when_needed,
                             opnum, rld[i].opnum))
       {
@@ -1071,8 +1080,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
       if (MEM_P (in))
        /* This is supposed to happen only for paradoxical subregs made by
           combine.c.  (SUBREG (MEM)) isn't supposed to occur other ways.  */
-       if (GET_MODE_SIZE (GET_MODE (in)) > GET_MODE_SIZE (inmode))
-         abort ();
+       gcc_assert (GET_MODE_SIZE (GET_MODE (in)) <= GET_MODE_SIZE (inmode));
 #endif
       inmode = GET_MODE (in);
     }
@@ -1093,7 +1101,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 
       if (REG_P (SUBREG_REG (in)))
        in_class
-         = find_valid_class (inmode,
+         = find_valid_class (inmode, GET_MODE (SUBREG_REG (in)),
                              subreg_regno_offset (REGNO (SUBREG_REG (in)),
                                                   GET_MODE (SUBREG_REG (in)),
                                                   SUBREG_BYTE (in),
@@ -1166,9 +1174,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
       outloc = &SUBREG_REG (out);
       out = *outloc;
 #if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
-      if (MEM_P (out)
-         && GET_MODE_SIZE (GET_MODE (out)) > GET_MODE_SIZE (outmode))
-       abort ();
+      gcc_assert (!MEM_P (out)
+                 || GET_MODE_SIZE (GET_MODE (out))
+                    <= GET_MODE_SIZE (outmode));
 #endif
       outmode = GET_MODE (out);
     }
@@ -1190,7 +1198,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
       dont_remove_subreg = 1;
       push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
                   &SUBREG_REG (out),
-                  find_valid_class (outmode,
+                  find_valid_class (outmode, GET_MODE (SUBREG_REG (out)),
                                     subreg_regno_offset (REGNO (SUBREG_REG (out)),
                                                          GET_MODE (SUBREG_REG (out)),
                                                          SUBREG_BYTE (out),
@@ -1259,7 +1267,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
        mode = outmode;
       if (mode == VOIDmode)
        {
-         error_for_asm (this_insn, "cannot reload integer constant operand in `asm'");
+         error_for_asm (this_insn, "cannot reload integer constant "
+                        "operand in %<asm%>");
          mode = word_mode;
          if (in != 0)
            inmode = word_mode;
@@ -1281,7 +1290,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
          }
       if (i == FIRST_PSEUDO_REGISTER)
        {
-         error_for_asm (this_insn, "impossible register constraint in `asm'");
+         error_for_asm (this_insn, "impossible register constraint "
+                        "in %<asm%>");
          class = ALL_REGS;
        }
     }
@@ -1289,9 +1299,8 @@ 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.  */
-  if (class == NO_REGS
-      && (optional == 0 || type != RELOAD_FOR_OUTPUT))
-    abort ();
+  gcc_assert (class != NO_REGS
+             || (optional != 0 && type == RELOAD_FOR_OUTPUT));
 
   i = find_reusable_reload (&in, out, class, type, opnum, dont_share);
 
@@ -1445,8 +1454,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
       /* If we did not find a nonzero amount-to-increment-by,
         that contradicts the belief that IN is being incremented
         in an address in this insn.  */
-      if (rld[i].inc == 0)
-       abort ();
+      gcc_assert (rld[i].inc != 0);
     }
 #endif
 
@@ -1512,7 +1520,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
      But if there is no spilling in this block, that is OK.
      An explicitly used hard reg cannot be a spill reg.  */
 
-  if (rld[i].reg_rtx == 0 && in != 0)
+  if (rld[i].reg_rtx == 0 && in != 0 && hard_regs_live_known)
     {
       rtx note;
       int regno;
@@ -1526,6 +1534,11 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
            && REG_P (XEXP (note, 0))
            && (regno = REGNO (XEXP (note, 0))) < FIRST_PSEUDO_REGISTER
            && reg_mentioned_p (XEXP (note, 0), in)
+           /* Check that we don't use a hardreg for an uninitialized
+              pseudo.  See also find_dummy_reload().  */
+           && (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
+               || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
+                                  ORIGINAL_REGNO (XEXP (note, 0))))
            && ! refers_to_regno_for_reload_p (regno,
                                               (regno
                                                + hard_regno_nregs[regno]
@@ -1989,7 +2002,17 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
                                is a subreg, and in that case, out
                                has a real mode.  */
                             (GET_MODE (out) != VOIDmode
-                             ? GET_MODE (out) : outmode)))
+                             ? GET_MODE (out) : outmode))
+        /* But only do all this if we can be sure, that this input
+           operand doesn't correspond with an uninitialized pseudoreg.
+           global can assign some hardreg to it, which is the same as
+          a different pseudo also currently live (as it can ignore the
+          conflict).  So we never must introduce writes to such hardregs,
+          as they would clobber the other live pseudo using the same.
+          See also PR20973.  */
+      && (ORIGINAL_REGNO (in) < FIRST_PSEUDO_REGISTER
+          || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
+                            ORIGINAL_REGNO (in))))
     {
       unsigned int regno = REGNO (in) + in_offset;
       unsigned int nwords = hard_regno_nregs[regno][inmode];
@@ -2152,12 +2175,15 @@ operands_match_p (rtx x, rtx y)
        j = REGNO (y);
 
       /* On a WORDS_BIG_ENDIAN machine, point to the last register of a
-        multiple hard register group, so that for example (reg:DI 0) and
-        (reg:SI 1) will be considered the same register.  */
+        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
+         && 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
+         && SCALAR_INT_MODE_P (GET_MODE (y))
          && j < FIRST_PSEUDO_REGISTER)
        j += hard_regno_nregs[j][GET_MODE (y)] - 1;
 
@@ -2182,20 +2208,30 @@ operands_match_p (rtx x, rtx y)
 
  slow:
 
-  /* Now we have disposed of all the cases
-     in which different rtx codes can match.  */
+  /* Now we have disposed of all the cases in which different rtx codes
+     can match.  */
   if (code != GET_CODE (y))
     return 0;
-  if (code == LABEL_REF)
-    return XEXP (x, 0) == XEXP (y, 0);
-  if (code == SYMBOL_REF)
-    return XSTR (x, 0) == XSTR (y, 0);
 
   /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.  */
-
   if (GET_MODE (x) != GET_MODE (y))
     return 0;
 
+  switch (code)
+    {
+    case CONST_INT:
+    case CONST_DOUBLE:
+      return 0;
+
+    case LABEL_REF:
+      return XEXP (x, 0) == XEXP (y, 0);
+    case SYMBOL_REF:
+      return XSTR (x, 0) == XSTR (y, 0);
+
+    default:
+      break;
+    }
+
   /* Compare the elements.  If any pair of corresponding elements
      fail to match, return 0 for the whole things.  */
 
@@ -2246,7 +2282,7 @@ operands_match_p (rtx x, rtx y)
             contain anything but integers and other rtx's,
             except for within LABEL_REFs and SYMBOL_REFs.  */
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   return 1 + success_2;
@@ -2268,101 +2304,102 @@ decompose (rtx x)
 
   memset (&val, 0, sizeof (val));
 
-  if (MEM_P (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)
-       {
-         val.base = XEXP (addr, 0);
-         val.start = -GET_MODE_SIZE (GET_MODE (x));
-         val.end = GET_MODE_SIZE (GET_MODE (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
-             && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
-             && CONSTANT_P (XEXP (XEXP (addr, 1), 1)))
-           {
-             val.base  = XEXP (addr, 0);
-             val.start = -INTVAL (XEXP (XEXP (addr, 1), 1));
-             val.end   = INTVAL (XEXP (XEXP (addr, 1), 1));
-             val.safe  = REGNO (val.base) == STACK_POINTER_REGNUM;
-             return val;
-           }
-       }
-
-      if (GET_CODE (addr) == CONST)
-       {
-         addr = XEXP (addr, 0);
-         all_const = 1;
-       }
-      if (GET_CODE (addr) == PLUS)
-       {
-         if (CONSTANT_P (XEXP (addr, 0)))
-           {
-             base = XEXP (addr, 1);
-             offset = XEXP (addr, 0);
-           }
-         else if (CONSTANT_P (XEXP (addr, 1)))
-           {
-             base = XEXP (addr, 0);
-             offset = XEXP (addr, 1);
-           }
-       }
-
-      if (offset == 0)
-       {
-         base = addr;
-         offset = const0_rtx;
-       }
-      if (GET_CODE (offset) == CONST)
-       offset = XEXP (offset, 0);
-      if (GET_CODE (offset) == PLUS)
-       {
-         if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
-           {
-             base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
-             offset = XEXP (offset, 0);
-           }
-         else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
-           {
-             base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
-             offset = XEXP (offset, 1);
-           }
-         else
-           {
-             base = gen_rtx_PLUS (GET_MODE (base), base, offset);
-             offset = const0_rtx;
-           }
-       }
-      else if (GET_CODE (offset) != CONST_INT)
-       {
-         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);
-
-      if (GET_CODE (offset) != CONST_INT)
-       abort ();
-
-      val.start = INTVAL (offset);
-      val.end = val.start + GET_MODE_SIZE (GET_MODE (x));
-      val.base = base;
-      return val;
-    }
-  else if (REG_P (x))
+  switch (GET_CODE (x))
     {
+    case MEM:
+      {
+       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)
+         {
+           val.base = XEXP (addr, 0);
+           val.start = -GET_MODE_SIZE (GET_MODE (x));
+           val.end = GET_MODE_SIZE (GET_MODE (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
+               && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
+               && CONSTANT_P (XEXP (XEXP (addr, 1), 1)))
+             {
+               val.base  = XEXP (addr, 0);
+               val.start = -INTVAL (XEXP (XEXP (addr, 1), 1));
+               val.end   = INTVAL (XEXP (XEXP (addr, 1), 1));
+               val.safe  = REGNO (val.base) == STACK_POINTER_REGNUM;
+               return val;
+             }
+         }
+       
+       if (GET_CODE (addr) == CONST)
+         {
+           addr = XEXP (addr, 0);
+           all_const = 1;
+         }
+       if (GET_CODE (addr) == PLUS)
+         {
+           if (CONSTANT_P (XEXP (addr, 0)))
+             {
+               base = XEXP (addr, 1);
+               offset = XEXP (addr, 0);
+             }
+           else if (CONSTANT_P (XEXP (addr, 1)))
+             {
+               base = XEXP (addr, 0);
+               offset = XEXP (addr, 1);
+             }
+         }
+       
+       if (offset == 0)
+         {
+           base = addr;
+           offset = const0_rtx;
+         }
+       if (GET_CODE (offset) == CONST)
+         offset = XEXP (offset, 0);
+       if (GET_CODE (offset) == PLUS)
+         {
+           if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
+             {
+               base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
+               offset = XEXP (offset, 0);
+             }
+           else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
+             {
+               base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
+               offset = XEXP (offset, 1);
+             }
+           else
+             {
+               base = gen_rtx_PLUS (GET_MODE (base), base, offset);
+               offset = const0_rtx;
+             }
+         }
+       else if (GET_CODE (offset) != CONST_INT)
+         {
+           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);
+       
+       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);
-      if (val.start < 0)
+      if (val.start < 0 || val.start >= FIRST_PSEUDO_REGISTER)
        {
          /* A pseudo with no hard reg.  */
          val.start = REGNO (x);
@@ -2371,26 +2408,31 @@ decompose (rtx x)
       else
        /* A hard reg.  */
        val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
-    }
-  else if (GET_CODE (x) == SUBREG)
-    {
+      break;
+
+    case SUBREG:
       if (!REG_P (SUBREG_REG (x)))
        /* This could be more precise, but it's good enough.  */
        return decompose (SUBREG_REG (x));
       val.reg_flag = 1;
       val.start = true_regnum (x);
-      if (val.start < 0)
+      if (val.start < 0 || val.start >= FIRST_PSEUDO_REGISTER)
        return decompose (SUBREG_REG (x));
       else
        /* A hard reg.  */
        val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
+      break;
+
+    case SCRATCH:
+      /* This hasn't been assigned yet, so it can't conflict yet.  */
+      val.safe = 1;
+      break;
+
+    default:
+      gcc_assert (CONSTANT_P (x));
+      val.safe = 1;
+      break;
     }
-  else if (CONSTANT_P (x)
-          /* This hasn't been assigned yet, so it can't conflict yet.  */
-          || GET_CODE (x) == SCRATCH)
-    val.safe = 1;
-  else
-    abort ();
   return val;
 }
 
@@ -2407,8 +2449,7 @@ immune_p (rtx x, rtx y, struct decomposition ydata)
   if (ydata.safe)
     return 1;
 
-  if (!MEM_P (y))
-    abort ();
+  gcc_assert (MEM_P (y));
   /* If Y is memory and X is not, Y can't affect X.  */
   if (!MEM_P (x))
     return 1;
@@ -2485,9 +2526,11 @@ 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.  */
+  /* Nonzero for an address operand that needs to be completely reloaded.
+     May be -1 to indicate the entire operand may or may not need a reload.  */
   int address_operand_reloaded[MAX_RECOG_OPERANDS];
   /* Value of enum reload_type to use for operand.  */
   enum reload_type operand_type[MAX_RECOG_OPERANDS];
@@ -2621,8 +2664,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
            case '%':
              {
                /* The last operand should not be marked commutative.  */
-               if (i == noperands - 1)
-                 abort ();
+               gcc_assert (i != noperands - 1);
 
                /* We currently only support one commutative pair of
                   operands.  Some existing asm code currently uses more
@@ -2633,8 +2675,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                   future we may handle it correctly.  */
                if (commutative < 0)
                  commutative = i;
-               else if (!this_insn_is_asm)
-                 abort ();
+               else
+                 gcc_assert (this_insn_is_asm);
              }
              break;
            /* Use of ISDIGIT is tempting here, but it may get expensive because
@@ -2649,8 +2691,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                                      recog_data.operand[i]);
 
                /* An operand may not match itself.  */
-               if (c == i)
-                 abort ();
+               gcc_assert (c != i);
 
                /* If C can be commuted with C+1, and C might need to match I,
                   then C+1 might also need to match I.  */
@@ -3077,6 +3118,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                  {
                    /* Operands don't match.  */
                    rtx value;
+                   int loc1, loc2;
                    /* Retroactively mark the operand we had to match
                       as a loser, if it wasn't already.  */
                    if (this_alternative_win[m])
@@ -3085,12 +3127,26 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                    if (this_alternative[m] == (int) 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.  */
+                      this alternative, if the pair can be a dummy reload.
+                      The pointers in operand_loc are not swapped; swap
+                      them by hand if necessary.  */
+                   if (swapped && i == commutative)
+                     loc1 = commutative + 1;
+                   else if (swapped && i == commutative + 1)
+                     loc1 = commutative;
+                   else
+                     loc1 = i;
+                   if (swapped && m == commutative)
+                     loc2 = commutative + 1;
+                   else if (swapped && m == commutative + 1)
+                     loc2 = commutative;
+                   else
+                     loc2 = m;
                    value
                      = find_dummy_reload (recog_data.operand[i],
                                           recog_data.operand[m],
-                                          recog_data.operand_loc[i],
-                                          recog_data.operand_loc[m],
+                                          recog_data.operand_loc[loc1],
+                                          recog_data.operand_loc[loc2],
                                           operand_mode[i], operand_mode[m],
                                           this_alternative[m], -1,
                                           this_alternative_earlyclobber[m]);
@@ -3180,7 +3236,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                          : offsettable_nonstrict_memref_p (operand))
                         /* A reloaded address is offsettable because it is now
                            just a simple register indirect.  */
-                        || address_reloaded[i]))
+                        || address_reloaded[i] == 1))
                    || (REG_P (operand)
                        && REGNO (operand) >= FIRST_PSEUDO_REGISTER
                        && reg_renumber[REGNO (operand)] < 0
@@ -3291,7 +3347,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                        /* If the address was already reloaded,
                           we win as well.  */
                        else if (MEM_P (operand)
-                                && address_reloaded[i])
+                                && address_reloaded[i] == 1)
                          win = 1;
                        /* Likewise if the address will be reloaded because
                           reg_equiv_address is nonzero.  For reg_equiv_mem
@@ -3463,7 +3519,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
          if (! win && ! did_match
              && this_alternative[i] != (int) NO_REGS
              && GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
-             && reg_class_size[(int) preferred_class[i]] > 1)
+             && reg_class_size [(int) preferred_class[i]] > 0
+             && ! SMALL_REGISTER_CLASS_P (preferred_class[i]))
            {
              if (! reg_class_subset_p (this_alternative[i],
                                        preferred_class[i]))
@@ -3493,17 +3550,14 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
            early_data = decompose (recog_data.operand[i]);
 
-           if (modified[i] == RELOAD_READ)
-             abort ();
+           gcc_assert (modified[i] != RELOAD_READ);
 
            if (this_alternative[i] == NO_REGS)
              {
                this_alternative_earlyclobber[i] = 0;
-               if (this_insn_is_asm)
-                 error_for_asm (this_insn,
-                                "`&' constraint used with no register class");
-               else
-                 abort ();
+               gcc_assert (this_insn_is_asm);
+               error_for_asm (this_insn,
+                              "%<&%> constraint used with no register class");
              }
 
            for (j = 0; j < noperands; j++)
@@ -3522,9 +3576,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                  && !immune_p (recog_data.operand[j], recog_data.operand[i],
                                early_data))
                {
-                 /* If the output is in a single-reg class,
+                 /* If the output is in a non-empty few-regs class,
                     it's costly to reload it, so reload the input instead.  */
-                 if (reg_class_size[this_alternative[i]] == 1
+                 if (SMALL_REGISTER_CLASS_P (this_alternative[i])
                      && (REG_P (recog_data.operand[j])
                          || GET_CODE (recog_data.operand[j]) == SUBREG))
                    {
@@ -3642,6 +3696,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
          pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
          pref_or_nothing[commutative + 1] = t;
 
+         t = address_reloaded[commutative];
+         address_reloaded[commutative] = address_reloaded[commutative + 1];
+         address_reloaded[commutative + 1] = t;
+
          memcpy (constraints, recog_data.constraints,
                  noperands * sizeof (char *));
          goto try_swapped;
@@ -3670,7 +3728,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
       /* No alternative works with reloads??  */
       if (insn_code_number >= 0)
        fatal_insn ("unable to generate reloads for:", insn);
-      error_for_asm (insn, "inconsistent operand constraints in an `asm'");
+      error_for_asm (insn, "inconsistent operand constraints in an %<asm%>");
       /* Avoid further trouble with this insn.  */
       PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
       n_reloads = 0;
@@ -3774,6 +3832,27 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
          goal_alternative_win[i] = 1;
       }
 
+  /* 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);
+
+       substed_operand[i] = recog_data.operand[i]
+         = find_reloads_toplev (tem, i, address_type[i],
+                                ind_levels, 0, insn, NULL);
+      }
+
   /* Record the values of the earlyclobber operands for the caller.  */
   if (goal_earlyclobber)
     for (i = 0; i < noperands; i++)
@@ -3878,11 +3957,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                             0, 0, i, RELOAD_OTHER);
            operand_reloadnum[i] = output_reloadnum;
          }
-       else if (insn_code_number >= 0)
-         abort ();
        else
          {
-           error_for_asm (insn, "inconsistent operand constraints in an `asm'");
+           gcc_assert (insn_code_number < 0);
+           error_for_asm (insn, "inconsistent operand constraints "
+                          "in an %<asm%>");
            /* Avoid further trouble with this insn.  */
            PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
            n_reloads = 0;
@@ -3891,7 +3970,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
       }
     else if (goal_alternative_matched[i] < 0
             && goal_alternative_matches[i] < 0
-            && !address_operand_reloaded[i]
+            && address_operand_reloaded[i] != 1
             && optimize)
       {
        /* For each non-matching operand that's a MEM or a pseudo-register
@@ -4337,10 +4416,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
      do after the insn (such as for output addresses) are fine.  */
   if (no_input_reloads)
     for (i = 0; i < n_reloads; i++)
-      if (rld[i].in != 0
-         && rld[i].when_needed != RELOAD_FOR_OUTADDR_ADDRESS
-         && rld[i].when_needed != RELOAD_FOR_OUTPUT_ADDRESS)
-       abort ();
+      gcc_assert (rld[i].in == 0
+                 || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS
+                 || rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS);
 #endif
 
   /* Compute reload_mode and reload_nregs.  */
@@ -4491,14 +4569,14 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
 
   if (code == SUBREG && REG_P (SUBREG_REG (x)))
     {
-      /* Check for SUBREG containing a REG that's equivalent to a constant.
-        If the constant has a known value, truncate it right now.
-        Similarly if we are extracting a single-word of a multi-word
-        constant.  If the constant is symbolic, allow it to be substituted
-        normally.  push_reload will strip the subreg later.  If the
-        constant is VOIDmode, abort because we will lose the mode of
-        the register (this should never happen because one of the cases
-        above should handle it).  */
+      /* Check for SUBREG containing a REG that's equivalent to a
+        constant.  If the constant has a known value, truncate it
+        right now.  Similarly if we are extracting a single-word of a
+        multi-word constant.  If the constant is symbolic, allow it
+        to be substituted normally.  push_reload will strip the
+        subreg later.  The constant must not be VOIDmode, because we
+        will lose the mode of the register (this should never happen
+        because one of the cases above should handle it).  */
 
       int regno = REGNO (SUBREG_REG (x));
       rtx tem;
@@ -4516,8 +4594,7 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
          tem =
            simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno],
                                 GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
-         if (!tem)
-           abort ();
+         gcc_assert (tem);
          return tem;
        }
 
@@ -4631,8 +4708,9 @@ maybe_memory_address_p (enum machine_mode mode, rtx ad, rtx *part)
    to determine if we may generate output reloads, and where to put USEs
    for pseudos that we have to replace with stack slots.
 
-   Value is nonzero if this address is reloaded or replaced as a whole.
-   This is interesting to the caller if the address is an autoincrement.
+   Value is one if this address is reloaded or replaced as a whole; it is
+   zero if the top level of this address was not reloaded or replaced, and
+   it is -1 if it may or may not have been reloaded or replaced.
 
    Note that there is no verification that the address will be valid after
    this routine does its work.  Instead, we rely on the fact that the address
@@ -4647,6 +4725,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 {
   int regno;
   int removed_and = 0;
+  int op_index;
   rtx tem;
 
   /* If the address is a register, see if it is a legitimate address and
@@ -4770,7 +4849,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
       *memrefloc = copy_rtx (*memrefloc);
       XEXP (*memrefloc, 0) = ad;
       move_replacements (&ad, &XEXP (*memrefloc, 0));
-      return 1;
+      return -1;
     }
   while (0);
 #endif
@@ -4892,7 +4971,9 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 
      Handle all base registers here, not just fp/ap/sp, because on some
      targets (namely SPARC) we can also get invalid addresses from preventive
-     subreg big-endian corrections made by find_reloads_toplev.
+     subreg big-endian corrections made by find_reloads_toplev.  We
+     can also get expressions involving LO_SUM (rather than PLUS) from
+     find_reloads_subreg_address.
 
      If we decide to do something, it must be that `double_reg_address_ok'
      is true.  We generate a reload of the base register + constant and
@@ -4900,62 +4981,62 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
      This is safe because we know the address isn't shared.
 
      We check for the base register as both the first and second operand of
-     the innermost PLUS.  */
-
-  else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
-          && GET_CODE (XEXP (ad, 0)) == PLUS
-          && REG_P (XEXP (XEXP (ad, 0), 0))
-          && REGNO (XEXP (XEXP (ad, 0), 0)) < FIRST_PSEUDO_REGISTER
-          && (REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 0), mode)
-              || XEXP (XEXP (ad, 0), 0) == frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
-              || XEXP (XEXP (ad, 0), 0) == hard_frame_pointer_rtx
-#endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-              || XEXP (XEXP (ad, 0), 0) == arg_pointer_rtx
-#endif
-              || XEXP (XEXP (ad, 0), 0) == stack_pointer_rtx)
-          && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 1)))
+     the innermost PLUS and/or LO_SUM.  */
+
+  for (op_index = 0; op_index < 2; ++op_index)
     {
-      *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
-                               plus_constant (XEXP (XEXP (ad, 0), 0),
-                                              INTVAL (XEXP (ad, 1))),
-                               XEXP (XEXP (ad, 0), 1));
-      find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0),
-                                MODE_BASE_REG_CLASS (mode),
-                                GET_MODE (ad), opnum, type, ind_levels);
-      find_reloads_address_1 (mode, XEXP (ad, 1), 1, &XEXP (ad, 1), opnum,
-                             type, 0, insn);
+      rtx operand;
 
-      return 0;
-    }
+      if (!(GET_CODE (ad) == PLUS 
+           && GET_CODE (XEXP (ad, 1)) == CONST_INT
+           && (GET_CODE (XEXP (ad, 0)) == PLUS
+               || GET_CODE (XEXP (ad, 0)) == LO_SUM)))
+       continue;
+
+      operand = XEXP (XEXP (ad, 0), op_index);
+      if (!REG_P (operand) || REGNO (operand) >= FIRST_PSEUDO_REGISTER)
+       continue;
 
-  else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
-          && GET_CODE (XEXP (ad, 0)) == PLUS
-          && REG_P (XEXP (XEXP (ad, 0), 1))
-          && REGNO (XEXP (XEXP (ad, 0), 1)) < FIRST_PSEUDO_REGISTER
-          && (REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 1), mode)
-              || XEXP (XEXP (ad, 0), 1) == frame_pointer_rtx
+      if ((REG_MODE_OK_FOR_BASE_P (operand, mode)
+          || operand == frame_pointer_rtx
 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
-              || XEXP (XEXP (ad, 0), 1) == hard_frame_pointer_rtx
+          || operand == hard_frame_pointer_rtx
 #endif
 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-              || XEXP (XEXP (ad, 0), 1) == arg_pointer_rtx
+          || operand == arg_pointer_rtx
 #endif
-              || XEXP (XEXP (ad, 0), 1) == stack_pointer_rtx)
-          && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 0)))
-    {
-      *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
-                               XEXP (XEXP (ad, 0), 0),
-                               plus_constant (XEXP (XEXP (ad, 0), 1),
-                                              INTVAL (XEXP (ad, 1))));
-      find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
-                                MODE_BASE_REG_CLASS (mode),
-                                GET_MODE (ad), opnum, type, ind_levels);
-      find_reloads_address_1 (mode, XEXP (ad, 0), 1, &XEXP (ad, 0), opnum,
-                             type, 0, insn);
+          || operand == stack_pointer_rtx)
+         && ! maybe_memory_address_p (mode, ad, 
+                                      &XEXP (XEXP (ad, 0), 1 - op_index)))
+       {
+         rtx offset_reg;
+         rtx addend;
+
+         offset_reg = plus_constant (operand, INTVAL (XEXP (ad, 1)));
+         addend = XEXP (XEXP (ad, 0), 1 - op_index);
+         
+         /* Form the adjusted address.  */
+         if (GET_CODE (XEXP (ad, 0)) == PLUS)
+           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, 
+                                op_index == 0 ? addend : offset_reg);
+         *loc = ad;
+
+         find_reloads_address_part (XEXP (ad, op_index), 
+                                    &XEXP (ad, op_index),
+                                    MODE_BASE_REG_CLASS (mode),
+                                    GET_MODE (ad), opnum, type, ind_levels);
+         find_reloads_address_1 (mode, 
+                                 XEXP (ad, 1 - op_index), 1, 
+                                 &XEXP (ad, 1 - op_index), opnum,
+                                 type, 0, insn);
 
-      return 0;
+         return 0;
+       }
     }
 
   /* See if address becomes valid when an eliminable register
@@ -5213,7 +5294,8 @@ update_auto_inc_notes (rtx insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED,
    is strictly valid.)
 
    CONTEXT = 1 means we are considering regs as index regs,
-   = 0 means we are considering them as base regs.
+   = 0 means we are considering them as base regs, = 2 means we
+   are considering them as base regs for REG + REG.
 
    OPNUM and TYPE specify the purpose of any reloads made.
 
@@ -5236,8 +5318,23 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
                        rtx *loc, int opnum, enum reload_type type,
                        int ind_levels, rtx insn)
 {
+#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE)               \
+  ((CONTEXT) == 2                                      \
+   ? REGNO_MODE_OK_FOR_REG_BASE_P (REGNO, MODE)                \
+   : (CONTEXT) == 1                                    \
+   ? REGNO_OK_FOR_INDEX_P (REGNO)                      \
+   : REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE))
+
+  enum reg_class context_reg_class;
   RTX_CODE code = GET_CODE (x);
 
+  if (context == 2)
+    context_reg_class = MODE_BASE_REG_REG_CLASS (mode);
+  else if (context == 1)
+    context_reg_class = INDEX_REG_CLASS;
+  else
+    context_reg_class = MODE_BASE_REG_CLASS (mode);
+
   switch (code)
     {
     case PLUS:
@@ -5280,12 +5377,12 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
           register remateralization for expression like &localvar*4.  Reload it.
           It may be possible to combine the displacement on the outer level,
           but it is probably not worthwhile to do so.  */
-       if (context)
+       if (context == 1)
          {
            find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
                                  opnum, ADDR_TYPE (type), ind_levels, insn);
            push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
-                        (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+                        context_reg_class,
                         GET_MODE (x), VOIDmode, 0, 0, opnum, type);
            return 1;
          }
@@ -5321,22 +5418,22 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
        else if (code0 == REG && code1 == REG)
          {
            if (REG_OK_FOR_INDEX_P (op0)
-               && REG_MODE_OK_FOR_BASE_P (op1, mode))
+               && REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
              return 0;
            else if (REG_OK_FOR_INDEX_P (op1)
-                    && REG_MODE_OK_FOR_BASE_P (op0, mode))
+                    && REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
              return 0;
-           else if (REG_MODE_OK_FOR_BASE_P (op1, mode))
+           else if (REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
              find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
                                      type, ind_levels, insn);
-           else if (REG_MODE_OK_FOR_BASE_P (op0, mode))
+           else if (REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
              find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
                                      type, ind_levels, insn);
            else if (REG_OK_FOR_INDEX_P (op1))
-             find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
+             find_reloads_address_1 (mode, orig_op0, 2, &XEXP (x, 0), opnum,
                                      type, ind_levels, insn);
            else if (REG_OK_FOR_INDEX_P (op0))
-             find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
+             find_reloads_address_1 (mode, orig_op1, 2, &XEXP (x, 1), opnum,
                                      type, ind_levels, insn);
            else
              {
@@ -5371,6 +5468,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
       {
        rtx op0 = XEXP (x, 0);
        rtx op1 = XEXP (x, 1);
+       int regno;
+       int reloadnum;
 
        if (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)
          return 0;
@@ -5379,8 +5478,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
           where a base register is {inc,dec}remented by the contents
           of another register or by a constant value.  Thus, these
           operands must match.  */
-       if (op0 != XEXP (op1, 0))
-         abort ();
+       gcc_assert (op0 == XEXP (op1, 0));
 
        /* Require index register (or constant).  Let's just handle the
           register case in the meantime... If the target allows
@@ -5391,67 +5489,62 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
            find_reloads_address_1 (mode, XEXP (op1, 1), 1, &XEXP (op1, 1),
                                    opnum, type, ind_levels, insn);
 
-       if (REG_P (XEXP (op1, 0)))
-         {
-           int regno = REGNO (XEXP (op1, 0));
-           int reloadnum;
-
-           /* A register that is incremented cannot be constant!  */
-           if (regno >= FIRST_PSEUDO_REGISTER
-               && reg_equiv_constant[regno] != 0)
-             abort ();
-
-           /* 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))
-             {
-               rtx tem = make_memloc (XEXP (x, 0), regno);
+       gcc_assert (REG_P (XEXP (op1, 0)));
 
-               if (reg_equiv_address[regno]
-                   || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
-                 {
-                   /* First reload the memory location's address.
-                      We can't use ADDR_TYPE (type) here, because we need to
-                      write back the value after reading it, hence we actually
-                      need two registers.  */
-                   find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
-                                         &XEXP (tem, 0), opnum,
-                                         RELOAD_OTHER,
-                                         ind_levels, insn);
-
-                   /* Then reload the memory location into a base
-                      register.  */
-                   reloadnum = push_reload (tem, tem, &XEXP (x, 0),
-                                            &XEXP (op1, 0),
-                                            MODE_BASE_REG_CLASS (mode),
-                                            GET_MODE (x), GET_MODE (x), 0,
-                                            0, opnum, RELOAD_OTHER);
-
-                   update_auto_inc_notes (this_insn, regno, reloadnum);
-                   return 0;
-                 }
-             }
+       regno = REGNO (XEXP (op1, 0));
 
-           if (reg_renumber[regno] >= 0)
-             regno = reg_renumber[regno];
+       /* A register that is incremented cannot be constant!  */
+       gcc_assert (regno < FIRST_PSEUDO_REGISTER
+                   || reg_equiv_constant[regno] == 0);
 
-           /* We require a base register here...  */
-           if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
+       /* 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))
+         {
+           rtx tem = make_memloc (XEXP (x, 0), regno);
+
+           if (reg_equiv_address[regno]
+               || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
              {
-               reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
-                                        &XEXP (op1, 0), &XEXP (x, 0),
-                                        MODE_BASE_REG_CLASS (mode),
-                                        GET_MODE (x), GET_MODE (x), 0, 0,
-                                        opnum, RELOAD_OTHER);
+               /* First reload the memory location's address.
+                   We can't use ADDR_TYPE (type) here, because we need to
+                   write back the value after reading it, hence we actually
+                   need two registers.  */
+               find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
+                                     &XEXP (tem, 0), opnum,
+                                     RELOAD_OTHER,
+                                     ind_levels, insn);
+
+               /* Then reload the memory location into a base
+                   register.  */
+               reloadnum = push_reload (tem, tem, &XEXP (x, 0),
+                                         &XEXP (op1, 0),
+                                         MODE_BASE_REG_CLASS (mode),
+                                         GET_MODE (x), GET_MODE (x), 0,
+                                         0, opnum, RELOAD_OTHER);
 
                update_auto_inc_notes (this_insn, regno, reloadnum);
                return 0;
              }
          }
-       else
-         abort ();
+
+       if (reg_renumber[regno] >= 0)
+         regno = reg_renumber[regno];
+
+       /* We require a base register here...  */
+       if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
+         {
+           reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
+                                     &XEXP (op1, 0), &XEXP (x, 0),
+                                     MODE_BASE_REG_CLASS (mode),
+                                     GET_MODE (x), GET_MODE (x), 0, 0,
+                                     opnum, RELOAD_OTHER);
+
+           update_auto_inc_notes (this_insn, regno, reloadnum);
+           return 0;
+         }
       }
       return 0;
 
@@ -5466,9 +5559,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
          rtx x_orig = x;
 
          /* A register that is incremented cannot be constant!  */
-         if (regno >= FIRST_PSEUDO_REGISTER
-             && reg_equiv_constant[regno] != 0)
-           abort ();
+         gcc_assert (regno < FIRST_PSEUDO_REGISTER
+                     || reg_equiv_constant[regno] == 0);
 
          /* Handle a register that is equivalent to a memory location
             which cannot be addressed directly.  */
@@ -5505,9 +5597,8 @@ 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
-              || !(context ? REGNO_OK_FOR_INDEX_P (regno)
-                   : REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
+         if (regno >= FIRST_PSEUDO_REGISTER
+             || !REG_OK_FOR_CONTEXT (context, regno, mode))
            {
              int reloadnum;
 
@@ -5543,8 +5634,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
                  x = XEXP (x, 0);
                  reloadnum
                    = push_reload (x, x, loc, loc,
-                                  (context ? INDEX_REG_CLASS :
-                                   MODE_BASE_REG_CLASS (mode)),
+                                  context_reg_class,
                                   GET_MODE (x), GET_MODE (x), 0, 0,
                                   opnum, RELOAD_OTHER);
                }
@@ -5552,8 +5642,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
                {
                  reloadnum
                    = push_reload (x, NULL_RTX, loc, (rtx*) 0,
-                                  (context ? INDEX_REG_CLASS :
-                                   MODE_BASE_REG_CLASS (mode)),
+                                  context_reg_class,
                                   GET_MODE (x), GET_MODE (x), 0, 0,
                                   opnum, type);
                  rld[reloadnum].inc
@@ -5593,8 +5682,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
                                opnum, type, ind_levels, insn);
 
          reloadnum = push_reload (x, NULL_RTX, loc, (rtx*) 0,
-                                  (context ? INDEX_REG_CLASS :
-                                   MODE_BASE_REG_CLASS (mode)),
+                                  context_reg_class,
                                   GET_MODE (x), VOIDmode, 0, 0, opnum, type);
          rld[reloadnum].inc
            = find_inc_amount (PATTERN (this_insn), XEXP (x, 0));
@@ -5607,6 +5695,24 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
        }
       return 0;
 
+    case TRUNCATE:
+    case SIGN_EXTEND:
+    case ZERO_EXTEND:
+      /* Look for parts to reload in the inner expression and reload them
+        too, in addition to this operation.  Reloading all inner parts in
+        addition to this one shouldn't be necessary, but at this point,
+        we don't know if we can possibly omit any part that *can* be
+        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),
+                             context, &XEXP (x, 0), opnum,
+                             type, ind_levels, insn);
+      push_reload (x, NULL_RTX, loc, (rtx*) 0,
+                  context_reg_class,
+                  GET_MODE (x), VOIDmode, 0, 0, opnum, type);
+      return 1;
+
     case MEM:
       /* This is probably the result of a substitution, by eliminate_regs, of
         an equivalent address for a pseudo that was not allocated to a hard
@@ -5623,7 +5729,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
       find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
                            opnum, ADDR_TYPE (type), ind_levels, insn);
       push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
-                  (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+                  context_reg_class,
                   GET_MODE (x), VOIDmode, 0, 0, opnum, type);
       return 1;
 
@@ -5634,8 +5740,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
        if (reg_equiv_constant[regno] != 0)
          {
            find_reloads_address_part (reg_equiv_constant[regno], loc,
-                                      (context ? INDEX_REG_CLASS :
-                                       MODE_BASE_REG_CLASS (mode)),
+                                      context_reg_class,
                                       GET_MODE (x), opnum, type, ind_levels);
            return 1;
          }
@@ -5645,8 +5750,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
        if (reg_equiv_mem[regno] != 0)
          {
            push_reload (reg_equiv_mem[regno], NULL_RTX, loc, (rtx*) 0,
-                        (context ? INDEX_REG_CLASS :
-                         MODE_BASE_REG_CLASS (mode)),
+                        context_reg_class,
                         GET_MODE (x), VOIDmode, 0, 0, opnum, type);
            return 1;
          }
@@ -5669,12 +5773,11 @@ 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
-            || !(context ? REGNO_OK_FOR_INDEX_P (regno)
-                 : REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
+       if (regno >= FIRST_PSEUDO_REGISTER
+           || !REG_OK_FOR_CONTEXT (context, regno, mode))
          {
            push_reload (x, NULL_RTX, loc, (rtx*) 0,
-                        (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+                        context_reg_class,
                         GET_MODE (x), VOIDmode, 0, 0, opnum, type);
            return 1;
          }
@@ -5686,7 +5789,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
        if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0))
          {
            push_reload (x, NULL_RTX, loc, (rtx*) 0,
-                        (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+                        context_reg_class,
                         GET_MODE (x), VOIDmode, 0, 0, opnum, type);
            return 1;
          }
@@ -5703,12 +5806,10 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
            {
              int regno ATTRIBUTE_UNUSED = subreg_regno (x);
 
-             if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
-                    : REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
+             if (! REG_OK_FOR_CONTEXT (context, regno, mode))
                {
                  push_reload (x, NULL_RTX, loc, (rtx*) 0,
-                              (context ? INDEX_REG_CLASS :
-                               MODE_BASE_REG_CLASS (mode)),
+                              context_reg_class,
                               GET_MODE (x), VOIDmode, 0, 0, opnum, type);
                  return 1;
                }
@@ -5717,12 +5818,12 @@ 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 ? INDEX_REG_CLASS
-                                     : MODE_BASE_REG_CLASS (mode));
+             enum reg_class class = context_reg_class;
              if ((unsigned) CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
                  > reg_class_size[class])
                {
-                 x = find_reloads_subreg_address (x, 0, opnum, type,
+                 x = find_reloads_subreg_address (x, 0, opnum, 
+                                                  ADDR_TYPE (type),
                                                   ind_levels, insn);
                  push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
                               GET_MODE (x), VOIDmode, 0, 0, opnum, type);
@@ -5748,6 +5849,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
       }
   }
 
+#undef REG_OK_FOR_CONTEXT
   return 0;
 }
 \f
@@ -5881,7 +5983,7 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
                }
 
              find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
-                                   &XEXP (tem, 0), opnum, ADDR_TYPE (type),
+                                   &XEXP (tem, 0), opnum, type,
                                    ind_levels, insn);
 
              /* If this is not a toplevel operand, find_reloads doesn't see
@@ -5932,10 +6034,9 @@ subst_reloads (rtx insn)
          for (check_regno = 0; check_regno < max_regno; check_regno++)
            {
 #define CHECK_MODF(ARRAY)                                              \
-             if (ARRAY[check_regno]                                    \
-                 && loc_mentioned_in_p (r->where,                      \
-                                        ARRAY[check_regno]))           \
-               abort ()
+             gcc_assert (!ARRAY[check_regno]                           \
+                         || !loc_mentioned_in_p (r->where,             \
+                                                 ARRAY[check_regno]))
 
              CHECK_MODF (reg_equiv_constant);
              CHECK_MODF (reg_equiv_memory_loc);
@@ -5950,9 +6051,12 @@ subst_reloads (rtx insn)
             register refers to.  */
          if (GET_CODE (*r->where) == LABEL_REF
              && JUMP_P (insn))
-           REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
-                                                 XEXP (*r->where, 0),
-                                                 REG_NOTES (insn));
+           {
+             REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
+                                                   XEXP (*r->where, 0),
+                                                   REG_NOTES (insn));
+             JUMP_LABEL (insn) = XEXP (*r->where, 0);
+          }
 
          /* Encapsulate RELOADREG so its machine mode matches what
             used to be there.  Note that gen_lowpart_common will
@@ -5990,8 +6094,8 @@ subst_reloads (rtx insn)
            *r->where = reloadreg;
        }
       /* If reload got no reg and isn't optional, something's wrong.  */
-      else if (! rld[r->what].optional)
-       abort ();
+      else
+       gcc_assert (rld[r->what].optional);
     }
 }
 \f
@@ -6003,8 +6107,7 @@ 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.  */
-  if (GET_CODE (x) == SUBREG)
-    abort ();
+  gcc_assert (GET_CODE (x) != SUBREG);
 
   copy_replacements_1 (&x, &y, n_replacements);
 }
@@ -6144,7 +6247,7 @@ find_replacement (rtx *loc)
    This is similar to refers_to_regno_p in rtlanal.c except that we
    look at equivalences for pseudos that didn't get hard registers.  */
 
-int
+static int
 refers_to_regno_for_reload_p (unsigned int regno, unsigned int endregno,
                              rtx x, rtx *loc)
 {
@@ -6173,10 +6276,8 @@ refers_to_regno_for_reload_p (unsigned int regno, unsigned int endregno,
                                                 reg_equiv_memory_loc[r],
                                                 (rtx*) 0);
 
-         if (reg_equiv_constant[r])
-           return 0;
-
-         abort ();
+         gcc_assert (reg_equiv_constant[r]);
+         return 0;
        }
 
       return (endregno > r
@@ -6301,9 +6402,8 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
        {
          if (reg_equiv_memory_loc[regno])
            return refers_to_mem_for_reload_p (in);
-         else if (reg_equiv_constant[regno])
-           return 0;
-         abort ();
+         gcc_assert (reg_equiv_constant[regno]);
+         return 0;
        }
     }
   else if (MEM_P (x))
@@ -6311,8 +6411,10 @@ 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 if (GET_CODE (x) == PLUS)
+  else 
     {
+      gcc_assert (GET_CODE (x) == PLUS);
+
       /* We actually want to know if X is mentioned somewhere inside IN.
         We must not say that (plus (sp) (const_int 124)) is in
         (plus (sp) (const_int 64)), since that can lead to incorrect reload
@@ -6328,8 +6430,6 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
       else return (reg_overlap_mentioned_for_reload_p (XEXP (x, 0), in)
                   || reg_overlap_mentioned_for_reload_p (XEXP (x, 1), in));
     }
-  else
-    abort ();
 
   endregno = regno + (regno < FIRST_PSEUDO_REGISTER
                      ? hard_regno_nregs[regno][GET_MODE (x)] : 1);
@@ -6340,7 +6440,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
 /* Return nonzero if anything in X contains a MEM.  Look also for pseudo
    registers.  */
 
-int
+static int
 refers_to_mem_for_reload_p (rtx x)
 {
   const char *fmt;
@@ -6468,7 +6568,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                 different from what they were when calculating the need for
                 spills.  If we notice an input-reload insn here, we will
                 reject it below, but it might hide a usable equivalent.
-                That makes bad code.  It may even abort: perhaps no reg was
+                That makes bad code.  It may even fail: perhaps no reg was
                 spilled for this insn because it was assumed we would find
                 that equivalent.  */
              || INSN_UID (p) < reload_first_uid))
@@ -6659,17 +6759,15 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
 
          if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER)
            for (i = 0; i < nregs; ++i)
-             if (call_used_regs[regno + i])
+             if (call_used_regs[regno + i]
+                 || HARD_REGNO_CALL_PART_CLOBBERED (regno + i, mode))
                return 0;
 
          if (valueno >= 0 && valueno < FIRST_PSEUDO_REGISTER)
            for (i = 0; i < valuenregs; ++i)
-             if (call_used_regs[valueno + i])
+             if (call_used_regs[valueno + i]
+                 || HARD_REGNO_CALL_PART_CLOBBERED (valueno + i, mode))
                return 0;
-#ifdef NON_SAVING_SETJMP
-         if (NON_SAVING_SETJMP && find_reg_note (p, REG_SETJMP, NULL))
-           return 0;
-#endif
        }
 
       if (INSN_P (p))
@@ -6692,7 +6790,6 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
              rtx dest = SET_DEST (pat);
              while (GET_CODE (dest) == SUBREG
                     || GET_CODE (dest) == ZERO_EXTRACT
-                    || GET_CODE (dest) == SIGN_EXTRACT
                     || GET_CODE (dest) == STRICT_LOW_PART)
                dest = XEXP (dest, 0);
              if (REG_P (dest))
@@ -6736,7 +6833,6 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                      rtx dest = SET_DEST (v1);
                      while (GET_CODE (dest) == SUBREG
                             || GET_CODE (dest) == ZERO_EXTRACT
-                            || GET_CODE (dest) == SIGN_EXTRACT
                             || GET_CODE (dest) == STRICT_LOW_PART)
                        dest = XEXP (dest, 0);
                      if (REG_P (dest))
@@ -6898,14 +6994,20 @@ find_inc_amount (rtx x, rtx inced)
 }
 \f
 /* Return 1 if register REGNO is the subject of a clobber in insn INSN.
-   If SETS is nonzero, also consider SETs.  */
+   If SETS is nonzero, also consider SETs.  REGNO must refer to a hard
+   register.  */
 
 int
 regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
                   int sets)
 {
-  unsigned int nregs = hard_regno_nregs[regno][mode];
-  unsigned int endregno = regno + nregs;
+  unsigned int nregs, endregno;
+
+  /* regno must be a hard register.  */
+  gcc_assert (regno < FIRST_PSEUDO_REGISTER);
+
+  nregs = hard_regno_nregs[regno][mode];
+  endregno = regno + nregs;
 
   if ((GET_CODE (PATTERN (insn)) == CLOBBER
        || (sets && GET_CODE (PATTERN (insn)) == SET))
@@ -6971,8 +7073,6 @@ static const char *const reload_when_needed_name[] =
   "RELOAD_FOR_OTHER_ADDRESS"
 };
 
-static const char * const reg_class_names[] = REG_CLASS_NAMES;
-
 /* These functions are used to print the variables set by 'find_reloads' */
 
 void