OSDN Git Service

Prevent out-of-bounds array access in reload.
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index e105ac9..9f10321 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.
 
@@ -27,6 +27,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    ought to be used instead.
 
    Before processing the first insn of the function, call `init_reload'.
+   init_reload actually has to be called earlier anyway.
 
    To scan an insn, call `find_reloads'.  This does two things:
    1. sets up tables describing which values must be reloaded
@@ -105,14 +106,20 @@ a register with any other reload.  */
 #include "function.h"
 #include "toplev.h"
 #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
+/* 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)))
 
-#ifndef REG_MODE_OK_FOR_BASE_P
-#define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO)
-#endif
 \f
 /* All reloads of the current insn are recorded here.  See reload.h for
    comments.  */
@@ -203,8 +210,8 @@ static int output_reloadnum;
 
   /* Compare two RTX's.  */
 #define MATCHES(x, y) \
- (x == y || (x != 0 && (GET_CODE (x) == REG                            \
-                       ? GET_CODE (y) == REG && REGNO (x) == REGNO (y) \
+ (x == y || (x != 0 && (REG_P (x)                              \
+                       ? REG_P (y) && REGNO (x) == REGNO (y)   \
                        : rtx_equal_p (x, y) && ! side_effects_p (x))))
 
   /* Indicates if two reloads purposes are for similar enough things that we
@@ -240,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 *);
@@ -271,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
 
@@ -324,7 +335,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
      a secondary reload is needed since whether or not a reload is needed
      might be sensitive to the form of the MEM.  */
 
-  if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER
+  if (REG_P (x) && REGNO (x) >= FIRST_PSEUDO_REGISTER
       && reg_equiv_mem[REGNO (x)] != 0)
     x = reg_equiv_mem[REGNO (x)];
 
@@ -380,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;
@@ -423,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.  */
@@ -442,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))
@@ -500,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))
       {
@@ -659,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;
@@ -678,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))
@@ -694,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;
 }
@@ -745,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;
 
@@ -763,20 +780,20 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class class,
            || TEST_HARD_REG_BIT (reg_class_contents[(int) class],
                                  true_regnum (rld[i].reg_rtx)))
        && out == 0 && rld[i].out == 0 && rld[i].in != 0
-       && ((GET_CODE (in) == REG
-            && GET_RTX_CLASS (GET_CODE (rld[i].in)) == 'a'
+       && ((REG_P (in)
+            && GET_RTX_CLASS (GET_CODE (rld[i].in)) == RTX_AUTOINC
             && MATCHES (XEXP (rld[i].in, 0), in))
-           || (GET_CODE (rld[i].in) == REG
-               && GET_RTX_CLASS (GET_CODE (in)) == 'a'
+           || (REG_P (rld[i].in)
+               && 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))
       {
        /* Make sure reload_in ultimately has the increment,
           not the plain register.  */
-       if (GET_CODE (in) == REG)
+       if (REG_P (in))
          *p_in = rld[i].in;
        return i;
       }
@@ -803,7 +820,7 @@ reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, int output)
 
   /* If INNER is not a hard register, then INNER will not need to
      be reloaded.  */
-  if (GET_CODE (inner) != REG
+  if (!REG_P (inner)
       || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
     return 0;
 
@@ -818,7 +835,7 @@ reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, int output)
          && output
          && GET_MODE_SIZE (GET_MODE (inner)) > UNITS_PER_WORD
          && ((GET_MODE_SIZE (GET_MODE (inner)) / UNITS_PER_WORD)
-             != (int) HARD_REGNO_NREGS (REGNO (inner), GET_MODE (inner))));
+             != (int) hard_regno_nregs[REGNO (inner)][GET_MODE (inner)]));
 }
 
 /* Return nonzero if IN can be reloaded into REGNO with mode MODE without
@@ -847,14 +864,14 @@ can_reload_into (rtx in, int regno, enum machine_mode mode)
      technically this is a non-optional input-output reload, but IN is
      already a valid register, and has been chosen as the reload register.
      Speed this up, since it trivially works.  */
-  if (GET_CODE (in) == REG)
+  if (REG_P (in))
     return 1;
 
   /* To test MEMs properly, we'd have to take into account all the reloads
      that are already scheduled, which can become quite complicated.
      And since we've already handled address reloads for this MEM, it
      should always succeed anyway.  */
-  if (GET_CODE (in) == MEM)
+  if (MEM_P (in))
     return 1;
 
   /* If we can make a simple SET insn that does the job, everything should
@@ -930,7 +947,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
      it is not in a hard register, reload straight from the constant,
      since we want to get rid of such pseudo registers.
      Often this is done earlier, but not always in find_reloads_address.  */
-  if (in != 0 && GET_CODE (in) == REG)
+  if (in != 0 && REG_P (in))
     {
       int regno = REGNO (in);
 
@@ -942,7 +959,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
   /* Likewise for OUT.  Of course, OUT will never be equivalent to
      an actual constant, but it might be equivalent to a memory location
      (in the case of a parameter).  */
-  if (out != 0 && GET_CODE (out) == REG)
+  if (out != 0 && REG_P (out))
     {
       int regno = REGNO (out);
 
@@ -953,7 +970,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 
   /* If we have a read-write operand with an address side-effect,
      change either IN or OUT so the side-effect happens only once.  */
-  if (in != 0 && out != 0 && GET_CODE (in) == MEM && rtx_equal_p (in, out))
+  if (in != 0 && out != 0 && MEM_P (in) && rtx_equal_p (in, out))
     switch (GET_CODE (XEXP (in, 0)))
       {
       case POST_INC: case POST_DEC:   case POST_MODIFY:
@@ -1006,9 +1023,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
       && (CONSTANT_P (SUBREG_REG (in))
          || GET_CODE (SUBREG_REG (in)) == PLUS
          || strict_low
-         || (((GET_CODE (SUBREG_REG (in)) == REG
+         || (((REG_P (SUBREG_REG (in))
                && REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER)
-              || GET_CODE (SUBREG_REG (in)) == MEM)
+              || MEM_P (SUBREG_REG (in)))
              && ((GET_MODE_SIZE (inmode)
                   > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
 #ifdef LOAD_EXTEND_OP
@@ -1018,7 +1035,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
                      && (GET_MODE_SIZE (inmode)
                          > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
                      && INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))
-                     && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != NIL)
+                     && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != UNKNOWN)
 #endif
 #ifdef WORD_REGISTER_OPERATIONS
                  || ((GET_MODE_SIZE (inmode)
@@ -1028,7 +1045,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
                           / UNITS_PER_WORD)))
 #endif
                  ))
-         || (GET_CODE (SUBREG_REG (in)) == REG
+         || (REG_P (SUBREG_REG (in))
              && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
              /* The case where out is nonzero
                 is handled differently in the following statement.  */
@@ -1038,8 +1055,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
                       > UNITS_PER_WORD)
                   && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
                        / UNITS_PER_WORD)
-                      != (int) HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
-                                                 GET_MODE (SUBREG_REG (in)))))
+                      != (int) hard_regno_nregs[REGNO (SUBREG_REG (in))]
+                                               [GET_MODE (SUBREG_REG (in))]))
                  || ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode)))
 #ifdef SECONDARY_INPUT_RELOAD_CLASS
          || (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS
@@ -1049,7 +1066,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
                  == NO_REGS))
 #endif
 #ifdef CANNOT_CHANGE_MODE_CLASS
-         || (GET_CODE (SUBREG_REG (in)) == REG
+         || (REG_P (SUBREG_REG (in))
              && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
              && REG_CANNOT_CHANGE_MODE_P
              (REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)), inmode))
@@ -1060,11 +1077,10 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
       inloc = &SUBREG_REG (in);
       in = *inloc;
 #if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
-      if (GET_CODE (in) == MEM)
+      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);
     }
@@ -1083,9 +1099,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
     {
       enum reg_class in_class = class;
 
-      if (GET_CODE (SUBREG_REG (in)) == REG)
+      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),
@@ -1115,9 +1131,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 #endif
       && (CONSTANT_P (SUBREG_REG (out))
          || strict_low
-         || (((GET_CODE (SUBREG_REG (out)) == REG
+         || (((REG_P (SUBREG_REG (out))
                && REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER)
-              || GET_CODE (SUBREG_REG (out)) == MEM)
+              || MEM_P (SUBREG_REG (out)))
              && ((GET_MODE_SIZE (outmode)
                   > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
 #ifdef WORD_REGISTER_OPERATIONS
@@ -1128,15 +1144,15 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
                           / UNITS_PER_WORD)))
 #endif
                  ))
-         || (GET_CODE (SUBREG_REG (out)) == REG
+         || (REG_P (SUBREG_REG (out))
              && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
              && ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
                   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
                       > UNITS_PER_WORD)
                   && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
                        / UNITS_PER_WORD)
-                      != (int) HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
-                                                 GET_MODE (SUBREG_REG (out)))))
+                      != (int) hard_regno_nregs[REGNO (SUBREG_REG (out))]
+                                               [GET_MODE (SUBREG_REG (out))]))
                  || ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
 #ifdef SECONDARY_OUTPUT_RELOAD_CLASS
          || (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS
@@ -1146,7 +1162,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
                  == NO_REGS))
 #endif
 #ifdef CANNOT_CHANGE_MODE_CLASS
-         || (GET_CODE (SUBREG_REG (out)) == REG
+         || (REG_P (SUBREG_REG (out))
              && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
              && REG_CANNOT_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
                                           GET_MODE (SUBREG_REG (out)),
@@ -1158,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 (GET_CODE (out) == MEM
-         && 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);
     }
@@ -1182,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),
@@ -1193,22 +1209,22 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
     }
 
   /* If IN appears in OUT, we can't share any input-only reload for IN.  */
-  if (in != 0 && out != 0 && GET_CODE (out) == MEM
-      && (GET_CODE (in) == REG || GET_CODE (in) == MEM)
+  if (in != 0 && out != 0 && MEM_P (out)
+      && (REG_P (in) || MEM_P (in))
       && reg_overlap_mentioned_for_reload_p (in, XEXP (out, 0)))
     dont_share = 1;
 
   /* If IN is a SUBREG of a hard register, make a new REG.  This
      simplifies some of the cases below.  */
 
-  if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG
+  if (in != 0 && GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))
       && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
       && ! dont_remove_subreg)
     in = gen_rtx_REG (GET_MODE (in), subreg_regno (in));
 
   /* Similarly for OUT.  */
   if (out != 0 && GET_CODE (out) == SUBREG
-      && GET_CODE (SUBREG_REG (out)) == REG
+      && REG_P (SUBREG_REG (out))
       && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
       && ! dont_remove_subreg)
     out = gen_rtx_REG (GET_MODE (out), subreg_regno (out));
@@ -1251,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;
@@ -1262,7 +1279,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
        if (HARD_REGNO_MODE_OK (i, mode)
            && TEST_HARD_REG_BIT (reg_class_contents[(int) class], i))
          {
-           int nregs = HARD_REGNO_NREGS (i, mode);
+           int nregs = hard_regno_nregs[i][mode];
 
            int j;
            for (j = 1; j < nregs; j++)
@@ -1273,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;
        }
     }
@@ -1281,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);
 
@@ -1312,7 +1329,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 
 #ifdef SECONDARY_MEMORY_NEEDED
       /* If a memory location is needed for the copy, make one.  */
-      if (in != 0 && (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
+      if (in != 0 && (REG_P (in) || GET_CODE (in) == SUBREG)
          && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
          && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
                                      class, inmode))
@@ -1342,7 +1359,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
       n_reloads++;
 
 #ifdef SECONDARY_MEMORY_NEEDED
-      if (out != 0 && (GET_CODE (out) == REG || GET_CODE (out) == SUBREG)
+      if (out != 0 && (REG_P (out) || GET_CODE (out) == SUBREG)
          && reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
          && SECONDARY_MEMORY_NEEDED (class,
                                      REGNO_REG_CLASS (reg_or_subregno (out)),
@@ -1437,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
 
@@ -1486,7 +1502,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
         The easiest way to tell the caller that is to give a phony
         value for the incoming operand (same as outgoing one).  */
       if (rld[i].reg_rtx == out
-         && (GET_CODE (in) == REG || CONSTANT_P (in))
+         && (REG_P (in) || CONSTANT_P (in))
          && 0 != find_equiv_reg (in, this_insn, 0, REGNO (out),
                                  static_reload_reg_p, i, inmode))
        rld[i].in = out;
@@ -1504,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;
@@ -1515,13 +1531,18 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 
       for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))
        if (REG_NOTE_KIND (note) == REG_DEAD
-           && GET_CODE (XEXP (note, 0)) == REG
+           && 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->global_live_at_end,
+                                  ORIGINAL_REGNO (XEXP (note, 0))))
            && ! refers_to_regno_for_reload_p (regno,
                                               (regno
-                                               + HARD_REGNO_NREGS (regno,
-                                                                   rel_mode)),
+                                               + hard_regno_nregs[regno]
+                                                                 [rel_mode]),
                                               PATTERN (this_insn), inloc)
            /* If this is also an output reload, IN cannot be used as
               the reload register if it is set in this insn unless IN
@@ -1529,8 +1550,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
            && (out == 0 || in == out
                || ! hard_reg_set_here_p (regno,
                                          (regno
-                                          + HARD_REGNO_NREGS (regno,
-                                                              rel_mode)),
+                                          + hard_regno_nregs[regno]
+                                                            [rel_mode]),
                                          PATTERN (this_insn)))
            /* ??? Why is this code so different from the previous?
               Is there any simple coherent way to describe the two together?
@@ -1548,8 +1569,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
            && HARD_REGNO_MODE_OK (regno, outmode))
          {
            unsigned int offs;
-           unsigned int nregs = MAX (HARD_REGNO_NREGS (regno, inmode),
-                                     HARD_REGNO_NREGS (regno, outmode));
+           unsigned int nregs = MAX (hard_regno_nregs[regno][inmode],
+                                     hard_regno_nregs[regno][outmode]);
 
            for (offs = 0; offs < nregs; offs++)
              if (fixed_regs[regno + offs]
@@ -1559,7 +1580,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 
            if (offs == nregs
                && (! (refers_to_regno_for_reload_p
-                      (regno, (regno + HARD_REGNO_NREGS (regno, inmode)),
+                      (regno, (regno + hard_regno_nregs[regno][inmode]),
                                in, (rtx *)0))
                    || can_reload_into (in, regno, inmode)))
              {
@@ -1754,7 +1775,7 @@ combine_reloads (void)
                   If the same reload reg is used for both reg 69 and the
                   result to be stored in memory, then that result
                   will clobber the address of the memory ref.  */
-               && ! (GET_CODE (rld[i].in) == REG
+               && ! (REG_P (rld[i].in)
                      && reg_overlap_mentioned_for_reload_p (rld[i].in,
                                                             rld[output_reload].out))))
        && ! reload_inner_reg_of_subreg (rld[i].in, rld[i].inmode,
@@ -1823,15 +1844,15 @@ combine_reloads (void)
      up can fully hold our output reload.  */
   for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))
     if (REG_NOTE_KIND (note) == REG_DEAD
-       && GET_CODE (XEXP (note, 0)) == REG
+       && REG_P (XEXP (note, 0))
        && ! reg_overlap_mentioned_for_reload_p (XEXP (note, 0),
                                                 rld[output_reload].out)
        && REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
        && HARD_REGNO_MODE_OK (REGNO (XEXP (note, 0)), rld[output_reload].outmode)
        && TEST_HARD_REG_BIT (reg_class_contents[(int) rld[output_reload].class],
                              REGNO (XEXP (note, 0)))
-       && (HARD_REGNO_NREGS (REGNO (XEXP (note, 0)), rld[output_reload].outmode)
-           <= HARD_REGNO_NREGS (REGNO (XEXP (note, 0)), GET_MODE (XEXP (note, 0))))
+       && (hard_regno_nregs[REGNO (XEXP (note, 0))][rld[output_reload].outmode]
+           <= hard_regno_nregs[REGNO (XEXP (note, 0))][GET_MODE (XEXP (note, 0))])
        /* Ensure that a secondary or tertiary reload for this output
           won't want this register.  */
        && ((secondary_out = rld[output_reload].secondary_out_reload) == -1
@@ -1895,7 +1916,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
   /* Find the inside of any subregs.  */
   while (GET_CODE (out) == SUBREG)
     {
-      if (GET_CODE (SUBREG_REG (out)) == REG
+      if (REG_P (SUBREG_REG (out))
          && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER)
        out_offset += subreg_regno_offset (REGNO (SUBREG_REG (out)),
                                           GET_MODE (SUBREG_REG (out)),
@@ -1905,7 +1926,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
     }
   while (GET_CODE (in) == SUBREG)
     {
-      if (GET_CODE (SUBREG_REG (in)) == REG
+      if (REG_P (SUBREG_REG (in))
          && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER)
        in_offset += subreg_regno_offset (REGNO (SUBREG_REG (in)),
                                          GET_MODE (SUBREG_REG (in)),
@@ -1919,11 +1940,11 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
   class = PREFERRED_RELOAD_CLASS (in, class);
 
   /* See if OUT will do.  */
-  if (GET_CODE (out) == REG
+  if (REG_P (out)
       && REGNO (out) < FIRST_PSEUDO_REGISTER)
     {
       unsigned int regno = REGNO (out) + out_offset;
-      unsigned int nwords = HARD_REGNO_NREGS (regno, outmode);
+      unsigned int nwords = hard_regno_nregs[regno][outmode];
       rtx saved_rtx;
 
       /* When we consider whether the insn uses OUT,
@@ -1952,7 +1973,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
 
          if (i == nwords)
            {
-             if (GET_CODE (real_out) == REG)
+             if (REG_P (real_out))
                value = real_out;
              else
                value = gen_rtx_REG (outmode, regno);
@@ -1969,7 +1990,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
      Also, the result can't go in IN if IN is used within OUT,
      or if OUT is an earlyclobber and IN appears elsewhere in the insn.  */
   if (hard_regs_live_known
-      && GET_CODE (in) == REG
+      && REG_P (in)
       && REGNO (in) < FIRST_PSEUDO_REGISTER
       && (value == 0
          || find_reg_note (this_insn, REG_UNUSED, real_out))
@@ -1981,10 +2002,20 @@ 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->global_live_at_end,
+                            ORIGINAL_REGNO (in))))
     {
       unsigned int regno = REGNO (in) + in_offset;
-      unsigned int nwords = HARD_REGNO_NREGS (regno, inmode);
+      unsigned int nwords = hard_regno_nregs[regno][inmode];
 
       if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, (rtx*) 0)
          && ! hard_reg_set_here_p (regno, regno + nwords,
@@ -2007,7 +2038,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
                 dies here.  So don't bother copying value to it.  */
              if (for_real >= 0 && value == real_out)
                rld[for_real].out = 0;
-             if (GET_CODE (real_in) == REG)
+             if (REG_P (real_in))
                value = real_in;
              else
                value = gen_rtx_REG (inmode, regno);
@@ -2050,13 +2081,13 @@ hard_reg_set_here_p (unsigned int beg_regno, unsigned int end_regno, rtx x)
 
       while (GET_CODE (op0) == SUBREG)
        op0 = SUBREG_REG (op0);
-      if (GET_CODE (op0) == REG)
+      if (REG_P (op0))
        {
          unsigned int r = REGNO (op0);
 
          /* See if this reg overlaps range under consideration.  */
          if (r < end_regno
-             && r + HARD_REGNO_NREGS (r, GET_MODE (op0)) > beg_regno)
+             && r + hard_regno_nregs[r][GET_MODE (op0)] > beg_regno)
            return 1;
        }
     }
@@ -2111,9 +2142,9 @@ operands_match_p (rtx x, rtx y)
 
   if (x == y)
     return 1;
-  if ((code == REG || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG))
-      && (GET_CODE (y) == REG || (GET_CODE (y) == SUBREG
-                                 && GET_CODE (SUBREG_REG (y)) == REG)))
+  if ((code == REG || (code == SUBREG && REG_P (SUBREG_REG (x))))
+      && (REG_P (y) || (GET_CODE (y) == SUBREG
+                                 && REG_P (SUBREG_REG (y)))))
     {
       int j;
 
@@ -2144,14 +2175,17 @@ 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;
+       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;
+       j += hard_regno_nregs[j][GET_MODE (y)] - 1;
 
       return i == j;
     }
@@ -2238,7 +2272,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;
@@ -2258,104 +2292,104 @@ decompose (rtx x)
   struct decomposition val;
   int all_const = 0;
 
-  val.reg_flag = 0;
-  val.safe = 0;
-  val.base = 0;
-  if (GET_CODE (x) == 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;
-           }
-       }
+  memset (&val, 0, sizeof (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 (GET_CODE (x) == REG)
+  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);
@@ -2363,27 +2397,32 @@ 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)
-    {
-      if (GET_CODE (SUBREG_REG (x)) != REG)
+       val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
+      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));
+       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;
 }
 
@@ -2400,10 +2439,9 @@ immune_p (rtx x, rtx y, struct decomposition ydata)
   if (ydata.safe)
     return 1;
 
-  if (GET_CODE (y) != MEM)
-    abort ();
+  gcc_assert (MEM_P (y));
   /* If Y is memory and X is not, Y can't affect X.  */
-  if (GET_CODE (x) != MEM)
+  if (!MEM_P (x))
     return 1;
 
   xdata = decompose (x);
@@ -2478,9 +2516,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];
@@ -2529,7 +2569,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   /* JUMP_INSNs and CALL_INSNs are not allowed to have any output reloads;
      neither are insns that SET cc0.  Insns that use CC0 are not allowed
      to have any input reloads.  */
-  if (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN)
+  if (JUMP_P (insn) || CALL_P (insn))
     no_output_reloads = 1;
 
 #ifdef HAVE_cc0
@@ -2555,9 +2595,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
      is cheap to move between them.  If it is not, there may not be an insn
      to do the copy, so we may need a reload.  */
   if (GET_CODE (body) == SET
-      && GET_CODE (SET_DEST (body)) == REG
+      && REG_P (SET_DEST (body))
       && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER
-      && GET_CODE (SET_SRC (body)) == REG
+      && REG_P (SET_SRC (body))
       && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
       && REGISTER_MOVE_COST (GET_MODE (SET_SRC (body)),
                             REGNO_REG_CLASS (REGNO (SET_SRC (body))),
@@ -2603,62 +2643,69 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
       while ((c = *p))
        {
          p += CONSTRAINT_LEN (c, p);
-         if (c == '=')
-           modified[i] = RELOAD_WRITE;
-         else if (c == '+')
-           modified[i] = RELOAD_READ_WRITE;
-         else if (c == '%')
+         switch (c)
            {
-             /* The last operand should not be marked commutative.  */
-             if (i == noperands - 1)
-               abort ();
-
-             /* We currently only support one commutative pair of
-                operands.  Some existing asm code currently uses more
-                than one pair.  Previously, that would usually work,
-                but sometimes it would crash the compiler.  We
-                continue supporting that case as well as we can by
-                silently ignoring all but the first pair.  In the
-                future we may handle it correctly.  */
-             if (commutative < 0)
-               commutative = i;
-             else if (!this_insn_is_asm)
-               abort ();
-           }
-         else if (ISDIGIT (c))
-           {
-             c = strtoul (p - 1, &p, 10);
+           case '=':
+             modified[i] = RELOAD_WRITE;
+             break;
+           case '+':
+             modified[i] = RELOAD_READ_WRITE;
+             break;
+           case '%':
+             {
+               /* The last operand should not be marked commutative.  */
+               gcc_assert (i != noperands - 1);
+
+               /* We currently only support one commutative pair of
+                  operands.  Some existing asm code currently uses more
+                  than one pair.  Previously, that would usually work,
+                  but sometimes it would crash the compiler.  We
+                  continue supporting that case as well as we can by
+                  silently ignoring all but the first pair.  In the
+                  future we may handle it correctly.  */
+               if (commutative < 0)
+                 commutative = i;
+               else
+                 gcc_assert (this_insn_is_asm);
+             }
+             break;
+           /* Use of ISDIGIT is tempting here, but it may get expensive because
+              of locale support we don't want.  */
+           case '0': case '1': case '2': case '3': case '4':
+           case '5': case '6': case '7': case '8': case '9':
+             {
+               c = strtoul (p - 1, &p, 10);
 
-             operands_match[c][i]
-               = operands_match_p (recog_data.operand[c],
-                                   recog_data.operand[i]);
+               operands_match[c][i]
+                 = operands_match_p (recog_data.operand[c],
+                                     recog_data.operand[i]);
 
-             /* An operand may not match itself.  */
-             if (c == i)
-               abort ();
+               /* An operand may not match itself.  */
+               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.  */
-             if (commutative >= 0)
-               {
-                 if (c == commutative || c == commutative + 1)
-                   {
-                     int other = c + (c == commutative ? 1 : -1);
-                     operands_match[other][i]
-                       = operands_match_p (recog_data.operand[other],
-                                           recog_data.operand[i]);
-                   }
-                 if (i == commutative || i == commutative + 1)
-                   {
-                     int other = i + (i == commutative ? 1 : -1);
-                     operands_match[c][other]
-                       = operands_match_p (recog_data.operand[c],
-                                           recog_data.operand[other]);
-                   }
-                 /* Note that C is supposed to be less than I.
-                    No need to consider altering both C and I because in
-                    that case we would alter one into the other.  */
-               }
+               /* If C can be commuted with C+1, and C might need to match I,
+                  then C+1 might also need to match I.  */
+               if (commutative >= 0)
+                 {
+                   if (c == commutative || c == commutative + 1)
+                     {
+                       int other = c + (c == commutative ? 1 : -1);
+                       operands_match[other][i]
+                         = operands_match_p (recog_data.operand[other],
+                                             recog_data.operand[i]);
+                     }
+                   if (i == commutative || i == commutative + 1)
+                     {
+                       int other = i + (i == commutative ? 1 : -1);
+                       operands_match[c][other]
+                         = operands_match_p (recog_data.operand[c],
+                                             recog_data.operand[other]);
+                     }
+                   /* Note that C is supposed to be less than I.
+                      No need to consider altering both C and I because in
+                      that case we would alter one into the other.  */
+                 }
+             }
            }
        }
     }
@@ -2699,7 +2746,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
          /* If we now have a simple operand where we used to have a
             PLUS or MULT, re-recognize and try again.  */
-         if ((GET_RTX_CLASS (GET_CODE (*recog_data.operand_loc[i])) == 'o'
+         if ((OBJECT_P (*recog_data.operand_loc[i])
               || GET_CODE (*recog_data.operand_loc[i]) == SUBREG)
              && (GET_CODE (recog_data.operand[i]) == MULT
                  || GET_CODE (recog_data.operand[i]) == PLUS))
@@ -2745,8 +2792,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
             wider reload.  */
 
          if (replace
-             && GET_CODE (op) == MEM
-             && GET_CODE (reg) == REG
+             && MEM_P (op)
+             && REG_P (reg)
              && (GET_MODE_SIZE (GET_MODE (reg))
                  >= GET_MODE_SIZE (GET_MODE (op))))
            set_unique_reg_note (emit_insn_before (gen_rtx_USE (VOIDmode, reg),
@@ -2755,7 +2802,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
          substed_operand[i] = recog_data.operand[i] = op;
        }
-      else if (code == PLUS || GET_RTX_CLASS (code) == '1')
+      else if (code == PLUS || GET_RTX_CLASS (code) == RTX_UNARY)
        /* We can get a PLUS as an "operand" as a result of register
           elimination.  See eliminate_regs and gen_reload.  We handle
           a unary operator by reloading the operand.  */
@@ -2883,7 +2930,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
          /* If the predicate accepts a unary operator, it means that
             we need to reload the operand, but do not do this for
             match_operator and friends.  */
-         if (GET_RTX_CLASS (GET_CODE (operand)) == '1' && *p != 0)
+         if (UNARY_P (operand) && *p != 0)
            operand = XEXP (operand, 0);
 
          /* If the operand is a SUBREG, extract
@@ -2896,7 +2943,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                 it is a hard reg.  This is because it is passed
                 to reg_fits_class_p if it is a REG and all pseudos
                 return 0 from that function.  */
-             if (GET_CODE (SUBREG_REG (operand)) == REG
+             if (REG_P (SUBREG_REG (operand))
                  && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
                {
                  if (!subreg_offset_representable_p
@@ -2939,15 +2986,15 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                     ??? When is it right at this stage to have a subreg
                     of a mem that is _not_ to be handled specially?  IMO
                     those should have been reduced to just a mem.  */
-                 || ((GET_CODE (operand) == MEM
-                      || (GET_CODE (operand)== REG
+                 || ((MEM_P (operand)
+                      || (REG_P (operand)
                           && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
 #ifndef WORD_REGISTER_OPERATIONS
                      && (((GET_MODE_BITSIZE (GET_MODE (operand))
                            < BIGGEST_ALIGNMENT)
                           && (GET_MODE_SIZE (operand_mode[i])
                               > GET_MODE_SIZE (GET_MODE (operand))))
-                         || (GET_CODE (operand) == MEM && BYTES_BIG_ENDIAN)
+                         || BYTES_BIG_ENDIAN
 #ifdef LOAD_EXTEND_OP
                          || (GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
                              && (GET_MODE_SIZE (GET_MODE (operand))
@@ -2955,7 +3002,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                              && (GET_MODE_SIZE (operand_mode[i])
                                  > GET_MODE_SIZE (GET_MODE (operand)))
                              && INTEGRAL_MODE_P (GET_MODE (operand))
-                             && LOAD_EXTEND_OP (GET_MODE (operand)) != NIL)
+                             && LOAD_EXTEND_OP (GET_MODE (operand)) != UNKNOWN)
 #endif
                          )
 #endif
@@ -3050,7 +3097,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                       offsettable address was expected, then we must reject
                       this combination, because we can't reload it.  */
                    if (this_alternative_offmemok[m]
-                       && GET_CODE (recog_data.operand[m]) == MEM
+                       && MEM_P (recog_data.operand[m])
                        && this_alternative[m] == (int) NO_REGS
                        && ! this_alternative_win[m])
                      bad = 1;
@@ -3061,6 +3108,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])
@@ -3069,12 +3117,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]);
@@ -3109,20 +3171,18 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              case 'm':
                if (force_reload)
                  break;
-               if (GET_CODE (operand) == MEM
-                   || (GET_CODE (operand) == REG
+               if (MEM_P (operand)
+                   || (REG_P (operand)
                        && REGNO (operand) >= FIRST_PSEUDO_REGISTER
                        && reg_renumber[REGNO (operand)] < 0))
                  win = 1;
-               if (CONSTANT_P (operand)
-                   /* force_const_mem does not accept HIGH.  */
-                   && GET_CODE (operand) != HIGH)
+               if (CONST_POOL_OK_P (operand))
                  badop = 0;
                constmemok = 1;
                break;
 
              case '<':
-               if (GET_CODE (operand) == MEM
+               if (MEM_P (operand)
                    && ! address_reloaded[i]
                    && (GET_CODE (XEXP (operand, 0)) == PRE_DEC
                        || GET_CODE (XEXP (operand, 0)) == POST_DEC))
@@ -3130,7 +3190,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                break;
 
              case '>':
-               if (GET_CODE (operand) == MEM
+               if (MEM_P (operand)
                    && ! address_reloaded[i]
                    && (GET_CODE (XEXP (operand, 0)) == PRE_INC
                        || GET_CODE (XEXP (operand, 0)) == POST_INC))
@@ -3141,14 +3201,14 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              case 'V':
                if (force_reload)
                  break;
-               if (GET_CODE (operand) == MEM
+               if (MEM_P (operand)
                    && ! (ind_levels ? offsettable_memref_p (operand)
                          : offsettable_nonstrict_memref_p (operand))
                    /* Certain mem addresses will become offsettable
                       after they themselves are reloaded.  This is important;
                       we don't want our own handling of unoffsettables
                       to override the handling of reg_equiv_address.  */
-                   && !(GET_CODE (XEXP (operand, 0)) == REG
+                   && !(REG_P (XEXP (operand, 0))
                         && (ind_levels == 0
                             || reg_equiv_address[REGNO (XEXP (operand, 0))] != 0)))
                  win = 1;
@@ -3158,7 +3218,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              case 'o':
                if (force_reload)
                  break;
-               if ((GET_CODE (operand) == MEM
+               if ((MEM_P (operand)
                     /* If IND_LEVELS, find_reloads_address won't reload a
                        pseudo that didn't get a hard reg, so we have to
                        reject that case.  */
@@ -3166,8 +3226,8 @@ 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]))
-                   || (GET_CODE (operand) == REG
+                        || address_reloaded[i] == 1))
+                   || (REG_P (operand)
                        && REGNO (operand) >= FIRST_PSEUDO_REGISTER
                        && reg_renumber[REGNO (operand)] < 0
                        /* If reg_equiv_address is nonzero, we will be
@@ -3178,9 +3238,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                             && offsettable_memref_p (reg_equiv_mem[REGNO (operand)]))
                            || (reg_equiv_address[REGNO (operand)] != 0))))
                  win = 1;
-               /* force_const_mem does not accept HIGH.  */
-               if ((CONSTANT_P (operand) && GET_CODE (operand) != HIGH)
-                   || GET_CODE (operand) == MEM)
+               if (CONST_POOL_OK_P (operand)
+                   || MEM_P (operand))
                  badop = 0;
                constmemok = 1;
                offmemok = 1;
@@ -3215,10 +3274,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                  break;
              case 'i':
                if (CONSTANT_P (operand)
-#ifdef LEGITIMATE_PIC_OPERAND_P
-                   && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (operand))
-#endif
-                   )
+                   && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (operand)))
                  win = 1;
                break;
 
@@ -3253,13 +3309,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                    && GET_CODE (operand) != PLUS
                    /* A SCRATCH is not a valid operand.  */
                    && GET_CODE (operand) != SCRATCH
-#ifdef LEGITIMATE_PIC_OPERAND_P
                    && (! CONSTANT_P (operand)
                        || ! flag_pic
                        || LEGITIMATE_PIC_OPERAND_P (operand))
-#endif
                    && (GENERAL_REGS == ALL_REGS
-                       || GET_CODE (operand) != REG
+                       || !REG_P (operand)
                        || (REGNO (operand) >= FIRST_PSEUDO_REGISTER
                            && reg_renumber[REGNO (operand)] < 0)))
                  win = 1;
@@ -3282,13 +3336,13 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                          win = 1;
                        /* If the address was already reloaded,
                           we win as well.  */
-                       else if (GET_CODE (operand) == MEM
-                                && address_reloaded[i])
+                       else if (MEM_P (operand)
+                                && address_reloaded[i] == 1)
                          win = 1;
                        /* Likewise if the address will be reloaded because
                           reg_equiv_address is nonzero.  For reg_equiv_mem
                           we have to check.  */
-                       else if (GET_CODE (operand) == REG
+                       else if (REG_P (operand)
                                 && REGNO (operand) >= FIRST_PSEUDO_REGISTER
                                 && reg_renumber[REGNO (operand)] < 0
                                 && ((reg_equiv_mem[REGNO (operand)] != 0
@@ -3299,8 +3353,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                        /* 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 ((CONSTANT_P (operand) && GET_CODE (operand) != HIGH)
-                           || GET_CODE (operand) == MEM)
+                       if (CONST_POOL_OK_P (operand)
+                           || MEM_P (operand))
                          badop = 0;
                        constmemok = 1;
                        offmemok = 1;
@@ -3332,7 +3386,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                if (GET_MODE (operand) == BLKmode)
                  break;
                winreg = 1;
-               if (GET_CODE (operand) == REG
+               if (REG_P (operand)
                    && reg_fits_class_p (operand, this_alternative[i],
                                         offset, GET_MODE (recog_data.operand[i])))
                  win = 1;
@@ -3362,7 +3416,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              if (badop)
                bad = 1;
              /* Alternative loses if it has no regs for a reg operand.  */
-             if (GET_CODE (operand) == REG
+             if (REG_P (operand)
                  && this_alternative[i] == (int) NO_REGS
                  && this_alternative_matches[i] < 0)
                bad = 1;
@@ -3375,9 +3429,7 @@ 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 (CONSTANT_P (operand)
-                 /* force_const_mem does not accept HIGH.  */
-                 && GET_CODE (operand) != HIGH
+             if (CONST_POOL_OK_P (operand)
                  && ((PREFERRED_RELOAD_CLASS (operand,
                                               (enum reg_class) this_alternative[i])
                       == NO_REGS)
@@ -3420,7 +3472,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                 case where we are forcing a constant into memory and
                 it will then win since we don't want to have a different
                 alternative match then.  */
-             if (! (GET_CODE (operand) == REG
+             if (! (REG_P (operand)
                     && REGNO (operand) >= FIRST_PSEUDO_REGISTER)
                  && GET_CODE (operand) != SCRATCH
                  && ! (const_to_mem && constmemok))
@@ -3457,7 +3509,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]))
@@ -3487,22 +3540,19 @@ 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++)
              /* Is this an input operand or a memory ref?  */
-             if ((GET_CODE (recog_data.operand[j]) == MEM
+             if ((MEM_P (recog_data.operand[j])
                   || modified[j] != RELOAD_WRITE)
                  && j != i
                  /* Ignore things like match_operator operands.  */
@@ -3516,10 +3566,10 @@ 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
-                     && (GET_CODE (recog_data.operand[j]) == REG
+                 if (SMALL_REGISTER_CLASS_P (this_alternative[i])
+                     && (REG_P (recog_data.operand[j])
                          || GET_CODE (recog_data.operand[j]) == SUBREG))
                    {
                      losers++;
@@ -3636,6 +3686,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;
@@ -3664,7 +3718,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;
@@ -3751,9 +3805,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
      into registers are here changed into memory references.  */
   for (i = 0; i < noperands; i++)
     if (! goal_alternative_win[i]
-       && CONSTANT_P (recog_data.operand[i])
-       /* force_const_mem does not accept HIGH.  */
-       && GET_CODE (recog_data.operand[i]) != HIGH
+       && CONST_POOL_OK_P (recog_data.operand[i])
        && ((PREFERRED_RELOAD_CLASS (recog_data.operand[i],
                                     (enum reg_class) goal_alternative[i])
             == NO_REGS)
@@ -3770,6 +3822,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++)
@@ -3792,7 +3865,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
           so we don't bother with it.  It may not be worth doing.  */
        else if (goal_alternative_matched[i] == -1
                 && goal_alternative_offmemok[i]
-                && GET_CODE (recog_data.operand[i]) == MEM)
+                && MEM_P (recog_data.operand[i]))
          {
            operand_reloadnum[i]
              = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
@@ -3874,11 +3947,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;
@@ -3887,7 +3960,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
@@ -3898,8 +3971,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
        while (GET_CODE (operand) == SUBREG)
          operand = SUBREG_REG (operand);
-       if ((GET_CODE (operand) == MEM
-            || (GET_CODE (operand) == REG
+       if ((MEM_P (operand)
+            || (REG_P (operand)
                 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
            /* If this is only for an output, the optional reload would not
               actually cause us to use a register now, just note that
@@ -3939,8 +4012,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
           we then need to emit a USE and/or a CLOBBER so that reload
           inheritance will do the right thing.  */
        else if (replace
-                && (GET_CODE (operand) == MEM
-                    || (GET_CODE (operand) == REG
+                && (MEM_P (operand)
+                    || (REG_P (operand)
                         && REGNO (operand) >= FIRST_PSEUDO_REGISTER
                         && reg_renumber [REGNO (operand)] < 0)))
          {
@@ -3948,7 +4021,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
            while (GET_CODE (operand) == SUBREG)
              operand = SUBREG_REG (operand);
-           if (GET_CODE (operand) == REG)
+           if (REG_P (operand))
              {
                if (modified[i] != RELOAD_WRITE)
                  /* We mark the USE with QImode so that we recognize
@@ -3975,8 +4048,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
        while (GET_CODE (operand) == SUBREG)
          operand = SUBREG_REG (operand);
-       if ((GET_CODE (operand) == MEM
-            || (GET_CODE (operand) == REG
+       if ((MEM_P (operand)
+            || (REG_P (operand)
                 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
            && ((enum reg_class) goal_alternative[goal_alternative_matches[i]]
                != NO_REGS))
@@ -4011,7 +4084,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
          /* If we're replacing an operand with a LABEL_REF, we need
             to make sure that there's a REG_LABEL note attached to
             this instruction.  */
-         if (GET_CODE (insn) != JUMP_INSN
+         if (!JUMP_P (insn)
              && GET_CODE (substitution) == LABEL_REF
              && !find_reg_note (insn, REG_LABEL, XEXP (substitution, 0)))
            REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
@@ -4051,7 +4124,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   for (i = 0; i < n_reloads; i++)
     if (rld[i].reg_rtx == 0
        && rld[i].in != 0
-       && GET_CODE (rld[i].in) == REG
+       && REG_P (rld[i].in)
        && rld[i].out == 0)
       {
        rld[i].reg_rtx
@@ -4333,10 +4406,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.  */
@@ -4356,7 +4428,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   for (i = 0; i < n_reloads; i++)
     if (rld[i].when_needed == RELOAD_FOR_INPUT
        && GET_CODE (PATTERN (insn)) == SET
-       && GET_CODE (SET_DEST (PATTERN (insn))) == REG
+       && REG_P (SET_DEST (PATTERN (insn)))
        && SET_SRC (PATTERN (insn)) == rld[i].in)
       {
        rtx dest = SET_DEST (PATTERN (insn));
@@ -4366,7 +4438,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
            && TEST_HARD_REG_BIT (reg_class_contents[rld[i].class], regno)
            && HARD_REGNO_MODE_OK (regno, rld[i].mode))
          {
-           int nr = HARD_REGNO_NREGS (regno, rld[i].mode);
+           int nr = hard_regno_nregs[regno][rld[i].mode];
            int ok = 1, nri;
 
            for (nri = 1; nri < nr; nri ++)
@@ -4485,16 +4557,16 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
       return tem;
     }
 
-  if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG)
+  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;
@@ -4512,8 +4584,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;
        }
 
@@ -4627,8 +4698,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
@@ -4643,13 +4715,14 @@ 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
      reload if not.  We first handle the cases where we need not reload
      or where we must reload in a non-standard way.  */
 
-  if (GET_CODE (ad) == REG)
+  if (REG_P (ad))
     {
       regno = REGNO (ad);
 
@@ -4683,9 +4756,9 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 
              if (ind_levels > 0
                  && strict_memory_address_p (mode, tem)
-                 && (GET_CODE (XEXP (tem, 0)) == REG
+                 && (REG_P (XEXP (tem, 0))
                      || (GET_CODE (XEXP (tem, 0)) == PLUS
-                         && GET_CODE (XEXP (XEXP (tem, 0), 0)) == REG
+                         && REG_P (XEXP (XEXP (tem, 0), 0))
                          && CONSTANT_P (XEXP (XEXP (tem, 0), 1)))))
                {
                  /* TEM is not the same as what we'll be replacing the
@@ -4738,7 +4811,7 @@ 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
-         && GET_CODE (XEXP (ad, 0)) == REG
+         && REG_P (XEXP (ad, 0))
          && reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0)
        return 0;
 
@@ -4766,7 +4839,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
@@ -4787,7 +4860,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
      frame and stack pointers is not its initial value.  In that case the
      pseudo will have been replaced by a MEM referring to the
      stack pointer.  */
-  if (GET_CODE (ad) == MEM)
+  if (MEM_P (ad))
     {
       /* First ensure that the address in this MEM is valid.  Then, unless
         indirect addresses are valid, reload the MEM into a register.  */
@@ -4813,10 +4886,10 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 
       if (ind_levels == 0
          || (GET_CODE (XEXP (tem, 0)) == SYMBOL_REF && ! indirect_symref_ok)
-         || GET_CODE (XEXP (tem, 0)) == MEM
-         || ! (GET_CODE (XEXP (tem, 0)) == REG
+         || MEM_P (XEXP (tem, 0))
+         || ! (REG_P (XEXP (tem, 0))
                || (GET_CODE (XEXP (tem, 0)) == PLUS
-                   && GET_CODE (XEXP (XEXP (tem, 0), 0)) == REG
+                   && REG_P (XEXP (XEXP (tem, 0), 0))
                    && GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT)))
        {
          /* Must use TEM here, not AD, since it is the one that will
@@ -4837,7 +4910,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
      targets (namely SH) we can also get too large displacements from
      big-endian corrections.  */
   else if (GET_CODE (ad) == PLUS
-          && GET_CODE (XEXP (ad, 0)) == REG
+          && REG_P (XEXP (ad, 0))
           && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
           && REG_MODE_OK_FOR_BASE_P (XEXP (ad, 0), mode)
           && GET_CODE (XEXP (ad, 1)) == CONST_INT)
@@ -4888,7 +4961,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
@@ -4896,62 +4971,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
-          && GET_CODE (XEXP (XEXP (ad, 0), 0)) == REG
-          && 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;
 
-  else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
-          && GET_CODE (XEXP (ad, 0)) == PLUS
-          && GET_CODE (XEXP (XEXP (ad, 0), 1)) == REG
-          && 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
+      operand = XEXP (XEXP (ad, 0), op_index);
+      if (!REG_P (operand) || REGNO (operand) >= FIRST_PSEUDO_REGISTER)
+       continue;
+
+      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
@@ -5143,12 +5218,12 @@ subst_indexed_address (rtx addr)
     {
       /* Try to find a register to replace.  */
       op0 = XEXP (addr, 0), op1 = XEXP (addr, 1), op2 = 0;
-      if (GET_CODE (op0) == REG
+      if (REG_P (op0)
          && (regno = REGNO (op0)) >= FIRST_PSEUDO_REGISTER
          && reg_renumber[regno] < 0
          && reg_equiv_constant[regno] != 0)
        op0 = reg_equiv_constant[regno];
-      else if (GET_CODE (op1) == REG
+      else if (REG_P (op1)
               && (regno = REGNO (op1)) >= FIRST_PSEUDO_REGISTER
               && reg_renumber[regno] < 0
               && reg_equiv_constant[regno] != 0)
@@ -5209,7 +5284,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.
 
@@ -5232,8 +5308,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:
@@ -5276,12 +5367,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;
          }
@@ -5317,22 +5408,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
              {
@@ -5367,6 +5458,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;
@@ -5375,8 +5468,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
@@ -5387,67 +5479,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));
+
+       /* A register that is incremented cannot be constant!  */
+       gcc_assert (regno < FIRST_PSEUDO_REGISTER
+                   || reg_equiv_constant[regno] == 0);
 
-           if (reg_renumber[regno] >= 0)
-             regno = reg_renumber[regno];
+       /* 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);
 
-           /* We require a base register here...  */
-           if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
+           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;
 
@@ -5455,16 +5542,15 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
     case POST_DEC:
     case PRE_INC:
     case PRE_DEC:
-      if (GET_CODE (XEXP (x, 0)) == REG)
+      if (REG_P (XEXP (x, 0)))
        {
          int regno = REGNO (XEXP (x, 0));
          int value = 0;
          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.  */
@@ -5501,9 +5587,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;
 
@@ -5515,11 +5600,11 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
                 memory location, since this will make it harder to
                 reuse address reloads, and increases register pressure.
                 Also don't do this if we can probably update x directly.  */
-             rtx equiv = (GET_CODE (XEXP (x, 0)) == MEM
+             rtx equiv = (MEM_P (XEXP (x, 0))
                           ? XEXP (x, 0)
                           : reg_equiv_mem[regno]);
              int icode = (int) add_optab->handlers[(int) Pmode].insn_code;
-             if (insn && GET_CODE (insn) == INSN && equiv
+             if (insn && NONJUMP_INSN_P (insn) && equiv
                  && memory_operand (equiv, GET_MODE (equiv))
 #ifdef HAVE_cc0
                  && ! sets_cc0_p (PATTERN (insn))
@@ -5539,8 +5624,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);
                }
@@ -5548,8 +5632,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
@@ -5564,7 +5647,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
          return value;
        }
 
-      else if (GET_CODE (XEXP (x, 0)) == MEM)
+      else if (MEM_P (XEXP (x, 0)))
        {
          /* This is probably the result of a substitution, by eliminate_regs,
             of an equivalent address for a pseudo that was not allocated to a
@@ -5589,8 +5672,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));
@@ -5619,7 +5701,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;
 
@@ -5630,8 +5712,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;
          }
@@ -5641,8 +5722,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;
          }
@@ -5665,12 +5745,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;
          }
@@ -5682,7 +5761,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;
          }
@@ -5690,7 +5769,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
       return 0;
 
     case SUBREG:
-      if (GET_CODE (SUBREG_REG (x)) == REG)
+      if (REG_P (SUBREG_REG (x)))
        {
          /* If this is a SUBREG of a hard register and the resulting register
             is of the wrong class, reload the whole SUBREG.  This avoids
@@ -5699,12 +5778,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;
                }
@@ -5713,8 +5790,7 @@ 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])
                {
@@ -5744,6 +5820,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
       }
   }
 
+#undef REG_OK_FOR_CONTEXT
   return 0;
 }
 \f
@@ -5870,7 +5947,7 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
                        return x;
                      base = XEXP (base, 0);
                    }
-                 if (GET_CODE (base) != REG
+                 if (!REG_P (base)
                      || (REGNO_POINTER_ALIGN (REGNO (base))
                          < outer_size * BITS_PER_UNIT))
                    return x;
@@ -5928,10 +6005,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);
@@ -5945,7 +6021,7 @@ subst_reloads (rtx insn)
             REG_LABEL note to indicate to flow which label this
             register refers to.  */
          if (GET_CODE (*r->where) == LABEL_REF
-             && GET_CODE (insn) == JUMP_INSN)
+             && JUMP_P (insn))
            REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
                                                  XEXP (*r->where, 0),
                                                  REG_NOTES (insn));
@@ -5986,8 +6062,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
@@ -5999,8 +6075,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);
 }
@@ -6092,7 +6167,7 @@ find_replacement (rtx *loc)
 
             ??? Is it actually still ever a SUBREG?  If so, why?  */
 
-         if (GET_CODE (reloadreg) == REG)
+         if (REG_P (reloadreg))
            return gen_rtx_REG (GET_MODE (*loc),
                                (REGNO (reloadreg) +
                                 subreg_regno_offset (REGNO (SUBREG_REG (*loc)),
@@ -6140,7 +6215,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)
 {
@@ -6169,27 +6244,25 @@ 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
              && regno < r + (r < FIRST_PSEUDO_REGISTER
-                             ? HARD_REGNO_NREGS (r, GET_MODE (x))
+                             ? hard_regno_nregs[r][GET_MODE (x)]
                              : 1));
 
     case SUBREG:
       /* If this is a SUBREG of a hard reg, we can see exactly which
         registers are being modified.  Otherwise, handle normally.  */
-      if (GET_CODE (SUBREG_REG (x)) == REG
+      if (REG_P (SUBREG_REG (x))
          && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
        {
          unsigned int inner_regno = subreg_regno (x);
          unsigned int inner_endregno
            = inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
-                            ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
+                            ? hard_regno_nregs[inner_regno][GET_MODE (x)] : 1);
 
          return endregno > inner_regno && regno < inner_endregno;
        }
@@ -6203,14 +6276,14 @@ refers_to_regno_for_reload_p (unsigned int regno, unsigned int endregno,
             treat each word individually.  */
          && ((GET_CODE (SET_DEST (x)) == SUBREG
               && loc != &SUBREG_REG (SET_DEST (x))
-              && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG
+              && REG_P (SUBREG_REG (SET_DEST (x)))
               && REGNO (SUBREG_REG (SET_DEST (x))) >= FIRST_PSEUDO_REGISTER
               && refers_to_regno_for_reload_p (regno, endregno,
                                                SUBREG_REG (SET_DEST (x)),
                                                loc))
              /* If the output is an earlyclobber operand, this is
                 a conflict.  */
-             || ((GET_CODE (SET_DEST (x)) != REG
+             || ((!REG_P (SET_DEST (x))
                   || earlyclobber_operand_p (SET_DEST (x)))
                  && refers_to_regno_for_reload_p (regno, endregno,
                                                   SET_DEST (x), loc))))
@@ -6271,7 +6344,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
 
   /* Overly conservative.  */
   if (GET_CODE (x) == STRICT_LOW_PART
-      || GET_RTX_CLASS (GET_CODE (x)) == 'a')
+      || GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC)
     x = XEXP (x, 0);
 
   /* If either argument is a constant, then modifying X can not affect IN.  */
@@ -6286,7 +6359,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
                                      SUBREG_BYTE (x),
                                      GET_MODE (x));
     }
-  else if (GET_CODE (x) == REG)
+  else if (REG_P (x))
     {
       regno = REGNO (x);
 
@@ -6297,26 +6370,27 @@ 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 (GET_CODE (x) == MEM)
+  else if (MEM_P (x))
     return refers_to_mem_for_reload_p (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
         allocation when spuriously changing a RELOAD_FOR_OUTPUT_ADDRESS
         into a RELOAD_OTHER on behalf of another RELOAD_OTHER.  */
-      while (GET_CODE (in) == MEM)
+      while (MEM_P (in))
        in = XEXP (in, 0);
-      if (GET_CODE (in) == REG)
+      if (REG_P (in))
        return 0;
       else if (GET_CODE (in) == PLUS)
        return (reg_overlap_mentioned_for_reload_p (x, XEXP (in, 0))
@@ -6324,11 +6398,9 @@ 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);
+                     ? hard_regno_nregs[regno][GET_MODE (x)] : 1);
 
   return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
 }
@@ -6336,23 +6408,23 @@ 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;
   int i;
 
-  if (GET_CODE (x) == MEM)
+  if (MEM_P (x))
     return 1;
 
-  if (GET_CODE (x) == REG)
+  if (REG_P (x))
     return (REGNO (x) >= FIRST_PSEUDO_REGISTER
            && 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--)
     if (fmt[i] == 'e'
-       && (GET_CODE (XEXP (x, i)) == MEM
+       && (MEM_P (XEXP (x, i))
            || refers_to_mem_for_reload_p (XEXP (x, i))))
       return 1;
 
@@ -6405,9 +6477,9 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
 
   if (goal == 0)
     regno = goalreg;
-  else if (GET_CODE (goal) == REG)
+  else if (REG_P (goal))
     regno = REGNO (goal);
-  else if (GET_CODE (goal) == MEM)
+  else if (MEM_P (goal))
     {
       enum rtx_code code = GET_CODE (XEXP (goal, 0));
       if (MEM_VOLATILE_P (goal))
@@ -6451,11 +6523,11 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
     {
       p = PREV_INSN (p);
       num++;
-      if (p == 0 || GET_CODE (p) == CODE_LABEL
+      if (p == 0 || LABEL_P (p)
          || num > PARAM_VALUE (PARAM_MAX_RELOAD_SEARCH_INSNS))
        return 0;
 
-      if (GET_CODE (p) == INSN
+      if (NONJUMP_INSN_P (p)
          /* If we don't want spill regs ...  */
          && (! (reload_reg_p != 0
                 && reload_reg_p != (short *) (HOST_WIDE_INT) 1)
@@ -6464,7 +6536,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))
@@ -6501,7 +6573,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                      && ((rtx_equal_p (XEXP (tem, 0), goal)
                           && (valueno
                               = true_regnum (valtry = SET_DEST (pat))) >= 0)
-                         || (GET_CODE (SET_DEST (pat)) == REG
+                         || (REG_P (SET_DEST (pat))
                              && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
                              && (GET_MODE_CLASS (GET_MODE (XEXP (tem, 0)))
                                  == MODE_FLOAT)
@@ -6516,7 +6588,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                              && (valueno = true_regnum (valtry)) >= 0)))
                  || (goal_const && (tem = find_reg_note (p, REG_EQUIV,
                                                          NULL_RTX))
-                     && GET_CODE (SET_DEST (pat)) == REG
+                     && REG_P (SET_DEST (pat))
                      && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
                      && (GET_MODE_CLASS (GET_MODE (XEXP (tem, 0)))
                          == MODE_FLOAT)
@@ -6539,7 +6611,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                {
                  int i;
 
-                 for (i = HARD_REGNO_NREGS (valueno, mode) - 1; i >= 0; i--)
+                 for (i = hard_regno_nregs[valueno][mode] - 1; i >= 0; i--)
                    if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
                                             valueno + i))
                      break;
@@ -6581,20 +6653,22 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
   if (goal_mem && value == SET_DEST (single_set (where))
       && refers_to_regno_for_reload_p (valueno,
                                       (valueno
-                                       + HARD_REGNO_NREGS (valueno, mode)),
+                                       + hard_regno_nregs[valueno][mode]),
                                       goal, (rtx*) 0))
     return 0;
 
   /* Reject registers that overlap GOAL.  */
 
+  if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER)
+    nregs = hard_regno_nregs[regno][mode];
+  else
+    nregs = 1;
+  valuenregs = hard_regno_nregs[valueno][mode];
+
   if (!goal_mem && !goal_const
-      && regno + (int) HARD_REGNO_NREGS (regno, mode) > valueno
-      && regno < valueno + (int) HARD_REGNO_NREGS (valueno, mode))
+      && regno + nregs > valueno && regno < valueno + valuenregs)
     return 0;
 
-  nregs = HARD_REGNO_NREGS (regno, mode);
-  valuenregs = HARD_REGNO_NREGS (valueno, mode);
-
   /* Reject VALUE if it is one of the regs reserved for reloads.
      Reload1 knows how to reuse them anyway, and it would get
      confused if we allocated one without its knowledge.
@@ -6619,8 +6693,8 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
        if (rld[i].reg_rtx != 0 && rld[i].in)
          {
            int regno1 = REGNO (rld[i].reg_rtx);
-           int nregs1 = HARD_REGNO_NREGS (regno1,
-                                          GET_MODE (rld[i].reg_rtx));
+           int nregs1 = hard_regno_nregs[regno1]
+                                        [GET_MODE (rld[i].reg_rtx)];
            if (regno1 < valueno + valuenregs
                && regno1 + nregs1 > valueno)
              return 0;
@@ -6644,7 +6718,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
 
       /* Don't trust the conversion past a function call
         if either of the two is in a call-clobbered register, or memory.  */
-      if (GET_CODE (p) == CALL_INSN)
+      if (CALL_P (p))
        {
          int i;
 
@@ -6653,17 +6727,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))
@@ -6686,15 +6758,14 @@ 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 (GET_CODE (dest) == REG)
+             if (REG_P (dest))
                {
                  int xregno = REGNO (dest);
                  int xnregs;
                  if (REGNO (dest) < FIRST_PSEUDO_REGISTER)
-                   xnregs = HARD_REGNO_NREGS (xregno, GET_MODE (dest));
+                   xnregs = hard_regno_nregs[xregno][GET_MODE (dest)];
                  else
                    xnregs = 1;
                  if (xregno < regno + nregs && xregno + xnregs > regno)
@@ -6708,10 +6779,10 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                  if (xregno == STACK_POINTER_REGNUM && need_stable_sp)
                    return 0;
                }
-             else if (goal_mem && GET_CODE (dest) == MEM
+             else if (goal_mem && MEM_P (dest)
                       && ! push_operand (dest, GET_MODE (dest)))
                return 0;
-             else if (GET_CODE (dest) == MEM && regno >= FIRST_PSEUDO_REGISTER
+             else if (MEM_P (dest) && regno >= FIRST_PSEUDO_REGISTER
                       && reg_equiv_memory_loc[regno] != 0)
                return 0;
              else if (need_stable_sp && push_operand (dest, GET_MODE (dest)))
@@ -6730,15 +6801,14 @@ 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 (GET_CODE (dest) == REG)
+                     if (REG_P (dest))
                        {
                          int xregno = REGNO (dest);
                          int xnregs;
                          if (REGNO (dest) < FIRST_PSEUDO_REGISTER)
-                           xnregs = HARD_REGNO_NREGS (xregno, GET_MODE (dest));
+                           xnregs = hard_regno_nregs[xregno][GET_MODE (dest)];
                          else
                            xnregs = 1;
                          if (xregno < regno + nregs
@@ -6754,10 +6824,10 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                          if (xregno == STACK_POINTER_REGNUM && need_stable_sp)
                            return 0;
                        }
-                     else if (goal_mem && GET_CODE (dest) == MEM
+                     else if (goal_mem && MEM_P (dest)
                               && ! push_operand (dest, GET_MODE (dest)))
                        return 0;
-                     else if (GET_CODE (dest) == MEM && regno >= FIRST_PSEUDO_REGISTER
+                     else if (MEM_P (dest) && regno >= FIRST_PSEUDO_REGISTER
                               && reg_equiv_memory_loc[regno] != 0)
                        return 0;
                      else if (need_stable_sp
@@ -6767,7 +6837,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                }
            }
 
-         if (GET_CODE (p) == CALL_INSN && CALL_INSN_FUNCTION_USAGE (p))
+         if (CALL_P (p) && CALL_INSN_FUNCTION_USAGE (p))
            {
              rtx link;
 
@@ -6779,11 +6849,11 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                    {
                      rtx dest = SET_DEST (pat);
 
-                     if (GET_CODE (dest) == REG)
+                     if (REG_P (dest))
                        {
                          int xregno = REGNO (dest);
                          int xnregs
-                           = HARD_REGNO_NREGS (xregno, GET_MODE (dest));
+                           = hard_regno_nregs[xregno][GET_MODE (dest)];
 
                          if (xregno < regno + nregs
                              && xregno + xnregs > regno)
@@ -6797,7 +6867,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                            return 0;
                        }
 
-                     else if (goal_mem && GET_CODE (dest) == MEM
+                     else if (goal_mem && MEM_P (dest)
                               && ! push_operand (dest, GET_MODE (dest)))
                        return 0;
                      else if (need_stable_sp
@@ -6817,7 +6887,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
 
            for (link = REG_NOTES (p); link; link = XEXP (link, 1))
              if (REG_NOTE_KIND (link) == REG_INC
-                 && GET_CODE (XEXP (link, 0)) == REG)
+                 && REG_P (XEXP (link, 0)))
                {
                  int incno = REGNO (XEXP (link, 0));
                  if (incno < regno + nregs && incno >= regno)
@@ -6892,18 +6962,24 @@ 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))
-      && GET_CODE (XEXP (PATTERN (insn), 0)) == REG)
+      && REG_P (XEXP (PATTERN (insn), 0)))
     {
       unsigned int test = REGNO (XEXP (PATTERN (insn), 0));
 
@@ -6919,7 +6995,7 @@ regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
          rtx elt = XVECEXP (PATTERN (insn), 0, i);
          if ((GET_CODE (elt) == CLOBBER
               || (sets && GET_CODE (PATTERN (insn)) == SET))
-             && GET_CODE (XEXP (elt, 0)) == REG)
+             && REG_P (XEXP (elt, 0)))
            {
              unsigned int test = REGNO (XEXP (elt, 0));
 
@@ -6944,8 +7020,8 @@ reload_adjust_reg_for_mode (rtx reloadreg, enum machine_mode mode)
   regno = REGNO (reloadreg);
 
   if (WORDS_BIG_ENDIAN)
-    regno += HARD_REGNO_NREGS (regno, GET_MODE (reloadreg))
-      - HARD_REGNO_NREGS (regno, mode);
+    regno += (int) hard_regno_nregs[regno][GET_MODE (reloadreg)]
+      - (int) hard_regno_nregs[regno][mode];
 
   return gen_rtx_REG (mode, regno);
 }
@@ -6965,8 +7041,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