OSDN Git Service

gcc/ada/
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index 243b65b..0492ee8 100644 (file)
@@ -1,13 +1,13 @@
 /* Search an insn for pseudo regs that must be in hard regs and are not.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006  Free Software Foundation,
-   Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* This file contains subroutines used only from the file reload1.c.
    It knows how to scan one insn for operands and values
@@ -112,6 +111,7 @@ a register with any other reload.  */
 #include "toplev.h"
 #include "params.h"
 #include "target.h"
+#include "df.h"
 
 /* True if X is a constant that can be forced into the constant pool.  */
 #define CONST_POOL_OK_P(X)                     \
@@ -263,7 +263,7 @@ static rtx find_dummy_reload (rtx, rtx, rtx *, rtx *, enum machine_mode,
 static int hard_reg_set_here_p (unsigned int, unsigned int, rtx);
 static struct decomposition decompose (rtx);
 static int immune_p (rtx, rtx, struct decomposition);
-static int alternative_allows_memconst (const char *, int);
+static bool alternative_allows_const_pool_ref (rtx, const char *, int);
 static rtx find_reloads_toplev (rtx, int, enum reload_type, int, int, rtx,
                                int *);
 static rtx make_memloc (rtx, int);
@@ -454,6 +454,8 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
        if (MERGE_TO_OTHER (secondary_type, rld[s_reload].when_needed,
                            opnum, rld[s_reload].opnum))
          rld[s_reload].when_needed = RELOAD_OTHER;
+
+       break;
       }
 
   if (s_reload == n_reloads)
@@ -922,29 +924,33 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
   if (outmode == VOIDmode && out != 0)
     outmode = GET_MODE (out);
 
-  /* If IN is a pseudo register everywhere-equivalent to a constant, and
-     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 find_reloads and friends until now missed to replace a pseudo
+     with a constant of reg_equiv_constant something went wrong
+     beforehand.
+     Note that it can't simply be done here if we missed it earlier
+     since the constant might need to be pushed into the literal pool
+     and the resulting memref would probably need further
+     reloading.  */
   if (in != 0 && REG_P (in))
     {
       int regno = REGNO (in);
 
-      if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
-         && reg_equiv_constant[regno] != 0)
-       in = reg_equiv_constant[regno];
+      gcc_assert (regno < FIRST_PSEUDO_REGISTER
+                 || reg_renumber[regno] >= 0
+                 || reg_equiv_constant[regno] == NULL_RTX);
     }
 
-  /* 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).  */
+  /* reg_equiv_constant only contains constants which are obviously
+     not appropriate as destination.  So if we would need to replace
+     the destination pseudo with a constant we are in real
+     trouble.  */
   if (out != 0 && REG_P (out))
     {
       int regno = REGNO (out);
 
-      if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
-         && reg_equiv_constant[regno] != 0)
-       out = reg_equiv_constant[regno];
+      gcc_assert (regno < FIRST_PSEUDO_REGISTER
+                 || reg_renumber[regno] >= 0
+                 || reg_equiv_constant[regno] == NULL_RTX);
     }
 
   /* If we have a read-write operand with an address side-effect,
@@ -1259,17 +1265,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
        }
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        if (HARD_REGNO_MODE_OK (i, mode)
-           && TEST_HARD_REG_BIT (reg_class_contents[(int) class], i))
-         {
-           int nregs = hard_regno_nregs[i][mode];
-
-           int j;
-           for (j = 1; j < nregs; j++)
-             if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class], i + j))
-               break;
-           if (j == nregs)
-             break;
-         }
+           && in_hard_reg_set_p (reg_class_contents[(int) class], mode, i))
+         break;
       if (i == FIRST_PSEUDO_REGISTER)
        {
          error_for_asm (this_insn, "impossible register constraint "
@@ -1527,24 +1524,21 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
            && REG_P (XEXP (note, 0))
            && (regno = REGNO (XEXP (note, 0))) < FIRST_PSEUDO_REGISTER
            && reg_mentioned_p (XEXP (note, 0), in)
-           /* Check that we don't use a hardreg for an uninitialized
-              pseudo.  See also find_dummy_reload().  */
+           /* Check that a former pseudo is valid; see find_dummy_reload.  */
            && (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
-               || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
-                                  ORIGINAL_REGNO (XEXP (note, 0))))
+               || (!bitmap_bit_p (DF_LIVE_OUT (ENTRY_BLOCK_PTR),
+                                  ORIGINAL_REGNO (XEXP (note, 0)))
+                   && hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] == 1))
            && ! refers_to_regno_for_reload_p (regno,
-                                              (regno
-                                               + hard_regno_nregs[regno]
-                                                                 [rel_mode]),
+                                              end_hard_regno (rel_mode,
+                                                              regno),
                                               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
               is also OUT.  */
            && (out == 0 || in == out
                || ! hard_reg_set_here_p (regno,
-                                         (regno
-                                          + hard_regno_nregs[regno]
-                                                            [rel_mode]),
+                                         end_hard_regno (rel_mode, regno),
                                          PATTERN (this_insn)))
            /* ??? Why is this code so different from the previous?
               Is there any simple coherent way to describe the two together?
@@ -1573,8 +1567,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]),
-                               in, (rtx *)0))
+                      (regno, end_hard_regno (inmode, regno), in, (rtx *) 0))
                    || can_reload_into (in, regno, inmode)))
              {
                rld[i].reg_rtx = gen_rtx_REG (rel_mode, regno);
@@ -1691,7 +1684,7 @@ remove_address_replacements (rtx in_rtx)
 static void
 combine_reloads (void)
 {
-  int i;
+  int i, regno;
   int output_reload = -1;
   int secondary_out = -1;
   rtx note;
@@ -1838,34 +1831,32 @@ combine_reloads (void)
   for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))
     if (REG_NOTE_KIND (note) == REG_DEAD
        && 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)
+       && !reg_overlap_mentioned_for_reload_p (XEXP (note, 0),
+                                               rld[output_reload].out)
+       && (regno = REGNO (XEXP (note, 0))) < FIRST_PSEUDO_REGISTER
+       && HARD_REGNO_MODE_OK (regno, rld[output_reload].outmode)
        && TEST_HARD_REG_BIT (reg_class_contents[(int) rld[output_reload].class],
-                             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))])
+                             regno)
+       && (hard_regno_nregs[regno][rld[output_reload].outmode]
+           <= hard_regno_nregs[regno][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
-           || (! (TEST_HARD_REG_BIT
-                  (reg_class_contents[(int) rld[secondary_out].class],
-                   REGNO (XEXP (note, 0))))
+           || (!(TEST_HARD_REG_BIT
+                 (reg_class_contents[(int) rld[secondary_out].class], regno))
                && ((secondary_out = rld[secondary_out].secondary_out_reload) == -1
-                   ||  ! (TEST_HARD_REG_BIT
-                          (reg_class_contents[(int) rld[secondary_out].class],
-                           REGNO (XEXP (note, 0)))))))
-       && ! fixed_regs[REGNO (XEXP (note, 0))]
-       /* Check that we don't use a hardreg for an uninitialized
-          pseudo.  See also find_dummy_reload().  */
+                   || !(TEST_HARD_REG_BIT
+                        (reg_class_contents[(int) rld[secondary_out].class],
+                         regno)))))
+       && !fixed_regs[regno]
+       /* Check that a former pseudo is valid; see find_dummy_reload.  */
        && (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
-           || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
-                              ORIGINAL_REGNO (XEXP (note, 0)))))
+           || (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
+                              ORIGINAL_REGNO (XEXP (note, 0)))
+               && hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] == 1)))
       {
        rld[output_reload].reg_rtx
-         = gen_rtx_REG (rld[output_reload].outmode,
-                        REGNO (XEXP (note, 0)));
+         = gen_rtx_REG (rld[output_reload].outmode, regno);
        return;
       }
 }
@@ -2005,16 +1996,24 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
                                has a real mode.  */
                             (GET_MODE (out) != VOIDmode
                              ? GET_MODE (out) : outmode))
-        /* But only do all this if we can be sure, that this input
-           operand doesn't correspond with an uninitialized pseudoreg.
-           global can assign some hardreg to it, which is the same as
-          a different pseudo also currently live (as it can ignore the
-          conflict).  So we never must introduce writes to such hardregs,
-          as they would clobber the other live pseudo using the same.
-          See also PR20973.  */
       && (ORIGINAL_REGNO (in) < FIRST_PSEUDO_REGISTER
-          || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
-                            ORIGINAL_REGNO (in))))
+         /* However only do this if we can be sure that this input
+            operand doesn't correspond with an uninitialized pseudo.
+            global can assign some hardreg to it that is the same as
+            the one assigned to a different, also live pseudo (as it
+            can ignore the conflict).  We must never introduce writes
+            to such hardregs, as they would clobber the other live
+            pseudo.  See PR 20973.  */
+          || (!bitmap_bit_p (DF_LIVE_OUT (ENTRY_BLOCK_PTR),
+                            ORIGINAL_REGNO (in))
+             /* Similarly, only do this if we can be sure that the death
+                note is still valid.  global can assign some hardreg to
+                the pseudo referenced in the note and simultaneously a
+                subword of this hardreg to a different, also live pseudo,
+                because only another subword of the hardreg is actually
+                used in the insn.  This cannot happen if the pseudo has
+                been assigned exactly one hardreg.  See PR 33732.  */
+             && hard_regno_nregs[REGNO (in)][GET_MODE (in)] == 1)))
     {
       unsigned int regno = REGNO (in) + in_offset;
       unsigned int nwords = hard_regno_nregs[regno][inmode];
@@ -2089,7 +2088,7 @@ hard_reg_set_here_p (unsigned int beg_regno, unsigned int end_regno, rtx x)
 
          /* See if this reg overlaps range under consideration.  */
          if (r < end_regno
-             && r + hard_regno_nregs[r][GET_MODE (op0)] > beg_regno)
+             && end_hard_regno (GET_MODE (op0), r) > beg_regno)
            return 1;
        }
     }
@@ -2223,6 +2222,7 @@ operands_match_p (rtx x, rtx y)
     {
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_FIXED:
       return 0;
 
     case LABEL_REF:
@@ -2409,7 +2409,7 @@ decompose (rtx x)
        }
       else
        /* A hard reg.  */
-       val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
+       val.end = end_hard_regno (GET_MODE (x), val.start);
       break;
 
     case SUBREG:
@@ -2807,7 +2807,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              && MEM_P (op)
              && REG_P (reg)
              && (GET_MODE_SIZE (GET_MODE (reg))
-                 >= GET_MODE_SIZE (GET_MODE (op))))
+                 >= GET_MODE_SIZE (GET_MODE (op)))
+             && reg_equiv_constant[REGNO (reg)] == 0)
            set_unique_reg_note (emit_insn_before (gen_rtx_USE (VOIDmode, reg),
                                                   insn),
                                 REG_EQUAL, reg_equiv_memory_loc[REGNO (reg)]);
@@ -3837,13 +3838,19 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
            || no_input_reloads)
        && operand_mode[i] != VOIDmode)
       {
+       int this_address_reloaded;
+
+       this_address_reloaded = 0;
        substed_operand[i] = recog_data.operand[i]
          = find_reloads_toplev (force_const_mem (operand_mode[i],
                                                  recog_data.operand[i]),
                                 i, address_type[i], ind_levels, 0, insn,
-                                NULL);
-       if (alternative_allows_memconst (recog_data.constraints[i],
-                                        goal_alternative_number))
+                                &this_address_reloaded);
+       if (alternative_allows_const_pool_ref (this_address_reloaded == 0
+                                              ? substed_operand[i]
+                                              : NULL,
+                                              recog_data.constraints[i],
+                                              goal_alternative_number))
          goal_alternative_win[i] = 1;
       }
 
@@ -4114,13 +4121,18 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
          *recog_data.operand_loc[i] = substitution;
 
-         /* If we're replacing an operand with a LABEL_REF, we need
-            to make sure that there's a REG_LABEL note attached to
+         /* If we're replacing an operand with a LABEL_REF, we need to
+            make sure that there's a REG_LABEL_OPERAND note attached to
             this instruction.  */
-         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,
+         if (GET_CODE (substitution) == LABEL_REF
+             && !find_reg_note (insn, REG_LABEL_OPERAND,
+                                XEXP (substitution, 0))
+             /* For a JUMP_P, if it was a branch target it must have
+                already been recorded as such.  */
+             && (!JUMP_P (insn)
+                 || !label_is_jump_target_p (XEXP (substitution, 0),
+                                             insn)))
+           REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND,
                                                  XEXP (substitution, 0),
                                                  REG_NOTES (insn));
        }
@@ -4468,7 +4480,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
     if (rld[i].when_needed == RELOAD_FOR_INPUT
        && GET_CODE (PATTERN (insn)) == SET
        && REG_P (SET_DEST (PATTERN (insn)))
-       && SET_SRC (PATTERN (insn)) == rld[i].in
+       && (SET_SRC (PATTERN (insn)) == rld[i].in
+           || SET_SRC (PATTERN (insn)) == rld[i].in_reg)
        && !elimination_target_reg_p (SET_DEST (PATTERN (insn))))
       {
        rtx dest = SET_DEST (PATTERN (insn));
@@ -4493,13 +4506,16 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   return retval;
 }
 
-/* Return 1 if alternative number ALTNUM in constraint-string CONSTRAINT
-   accepts a memory operand with constant address.  */
+/* Return true if alternative number ALTNUM in constraint-string
+   CONSTRAINT is guaranteed to accept a reloaded constant-pool reference.
+   MEM gives the reference if it didn't need any reloads, otherwise it
+   is null.  */
 
-static int
-alternative_allows_memconst (const char *constraint, int altnum)
+static bool
+alternative_allows_const_pool_ref (rtx mem, const char *constraint, int altnum)
 {
   int c;
+
   /* Skip alternatives before the one requested.  */
   while (altnum > 0)
     {
@@ -4507,12 +4523,25 @@ alternative_allows_memconst (const char *constraint, int altnum)
       altnum--;
     }
   /* Scan the requested alternative for 'm' or 'o'.
-     If one of them is present, this alternative accepts memory constants.  */
+     If one of them is present, this alternative accepts the result of
+     passing a constant-pool reference through find_reloads_toplev.
+
+     The same is true of extra memory constraints if the address
+     was reloaded into a register.  However, the target may elect
+     to disallow the original constant address, forcing it to be
+     reloaded into a register instead.  */
   for (; (c = *constraint) && c != ',' && c != '#';
        constraint += CONSTRAINT_LEN (c, constraint))
-    if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c, constraint))
-      return 1;
-  return 0;
+    {
+      if (c == 'm' || c == 'o')
+       return true;
+#ifdef EXTRA_CONSTRAINT_STR
+      if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
+         && (mem == NULL || EXTRA_CONSTRAINT_STR (mem, c, constraint)))
+       return true;
+#endif
+    }
+  return false;
 }
 \f
 /* Scan X for memory references and scan the addresses for reloading.
@@ -4613,14 +4642,6 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
       int regno = REGNO (SUBREG_REG (x));
       rtx tem;
 
-      if (subreg_lowpart_p (x)
-         && regno >= FIRST_PSEUDO_REGISTER
-         && reg_renumber[regno] < 0
-         && reg_equiv_constant[regno] != 0
-         && (tem = gen_lowpart_common (GET_MODE (x),
-                                       reg_equiv_constant[regno])) != 0)
-       return tem;
-
       if (regno >= FIRST_PSEUDO_REGISTER
          && reg_renumber[regno] < 0
          && reg_equiv_constant[regno] != 0)
@@ -4629,6 +4650,15 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
            simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno],
                                 GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
          gcc_assert (tem);
+         if (CONSTANT_P (tem) && !LEGITIMATE_CONSTANT_P (tem))
+           {
+             tem = force_const_mem (GET_MODE (x), tem);
+             i = find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
+                                       &XEXP (tem, 0), opnum, type,
+                                       ind_levels, insn);
+             if (address_reloaded)
+               *address_reloaded = i;
+           }
          return tem;
        }
 
@@ -4770,15 +4800,12 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
     {
       regno = REGNO (ad);
 
-      /* If the register is equivalent to an invariant expression, substitute
-        the invariant, and eliminate any eliminable register references.  */
-      tem = reg_equiv_constant[regno];
-      if (tem != 0
-         && (tem = eliminate_regs (tem, mode, insn))
-         && strict_memory_address_p (mode, tem))
+      if (reg_equiv_constant[regno] != 0)
        {
-         *loc = ad = tem;
-         return 0;
+         find_reloads_address_part (reg_equiv_constant[regno], loc,
+                                    base_reg_class (mode, MEM, SCRATCH),
+                                    GET_MODE (ad), opnum, type, ind_levels);
+         return 1;
        }
 
       tem = reg_equiv_memory_loc[regno];
@@ -5153,6 +5180,7 @@ subst_reg_equivs (rtx ad, rtx insn)
     case CONST_INT:
     case CONST:
     case CONST_DOUBLE:
+    case CONST_FIXED:
     case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
@@ -5473,16 +5501,12 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
 
        else if (code0 == REG && code1 == REG)
          {
-           if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
-               && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
+           if (REGNO_OK_FOR_INDEX_P (REGNO (op1))
+               && regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
              return 0;
-           else if (REGNO_OK_FOR_INDEX_P (REGNO (op1))
-                    && regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
+           else if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
+                    && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
              return 0;
-           else if (regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
-             find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
-                                     &XEXP (x, 0), opnum, type, ind_levels,
-                                     insn);
            else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
              find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
                                      &XEXP (x, 1), opnum, type, ind_levels,
@@ -5491,16 +5515,20 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
              find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
                                      &XEXP (x, 0), opnum, type, ind_levels,
                                      insn);
+           else if (regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
+             find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+                                     &XEXP (x, 0), opnum, type, ind_levels,
+                                     insn);
            else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)))
              find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
                                      &XEXP (x, 1), opnum, type, ind_levels,
                                      insn);
            else
              {
-               find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+               find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
                                        &XEXP (x, 0), opnum, type, ind_levels,
                                        insn);
-               find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
+               find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
                                        &XEXP (x, 1), opnum, type, ind_levels,
                                        insn);
              }
@@ -5673,8 +5701,10 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
                }
            }
 
-         /* If we have a hard register that is ok as an index,
-            don't make a reload.  If an autoincrement of a nice register
+         /* If we have a hard register that is ok in this incdec context,
+            don't make a reload.  If the register isn't nice enough for
+            autoincdec, we can reload it.  But, if an autoincrement of a
+            register that we here verified as playing nice, still outside
             isn't "valid", it must be that no autoincrement is "valid".
             If that is true and something made an autoincrement anyway,
             this must be a special context where one is allowed.
@@ -5687,7 +5717,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
          if (reg_renumber[regno] >= 0)
            regno = reg_renumber[regno];
          if (regno >= FIRST_PSEUDO_REGISTER
-             || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+             || !REG_OK_FOR_CONTEXT (context, regno, mode, code,
                                      index_code))
            {
              int reloadnum;
@@ -5703,7 +5733,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
              rtx equiv = (MEM_P (XEXP (x, 0))
                           ? XEXP (x, 0)
                           : reg_equiv_mem[regno]);
-             int icode = (int) add_optab->handlers[(int) Pmode].insn_code;
+             int icode = (int) optab_handler (add_optab, Pmode)->insn_code;
              if (insn && NONJUMP_INSN_P (insn) && equiv
                  && memory_operand (equiv, GET_MODE (equiv))
 #ifdef HAVE_cc0
@@ -5731,7 +5761,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
              else
                {
                  reloadnum
-                   = push_reload (x, NULL_RTX, loc, (rtx*) 0,
+                   = push_reload (x, x, loc, (rtx*) 0,
                                   context_reg_class,
                                   GET_MODE (x), GET_MODE (x), 0, 0,
                                   opnum, type);
@@ -5936,10 +5966,8 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class class,
       && (! LEGITIMATE_CONSTANT_P (x)
          || PREFERRED_RELOAD_CLASS (x, class) == NO_REGS))
     {
-      rtx tem;
-
-      tem = x = force_const_mem (mode, x);
-      find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
+      x = force_const_mem (mode, x);
+      find_reloads_address (mode, &x, XEXP (x, 0), &XEXP (x, 0),
                            opnum, type, ind_levels, 0);
     }
 
@@ -5952,7 +5980,7 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class class,
 
       tem = force_const_mem (GET_MODE (x), XEXP (x, 1));
       x = gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0), tem);
-      find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
+      find_reloads_address (mode, &XEXP (x, 1), XEXP (tem, 0), &XEXP (tem, 0),
                            opnum, type, ind_levels, 0);
     }
 
@@ -6022,6 +6050,8 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
 
              XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
              PUT_MODE (tem, GET_MODE (x));
+             if (MEM_OFFSET (tem))
+               set_mem_offset (tem, plus_constant (MEM_OFFSET (tem), offset));
 
              /* If this was a paradoxical subreg that we replaced, the
                 resulting memory must be sufficiently aligned to allow
@@ -6134,17 +6164,15 @@ subst_reloads (rtx insn)
            }
 #endif /* DEBUG_RELOAD */
 
-         /* If we're replacing a LABEL_REF with a register, add a
-            REG_LABEL note to indicate to flow which label this
+         /* If we're replacing a LABEL_REF with a register, there must
+            already be an indication (to e.g. flow) which label this
             register refers to.  */
-         if (GET_CODE (*r->where) == LABEL_REF
-             && JUMP_P (insn))
-           {
-             REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
-                                                   XEXP (*r->where, 0),
-                                                   REG_NOTES (insn));
-             JUMP_LABEL (insn) = XEXP (*r->where, 0);
-          }
+         gcc_assert (GET_CODE (*r->where) != LABEL_REF
+                     || !JUMP_P (insn)
+                     || find_reg_note (insn,
+                                       REG_LABEL_OPERAND,
+                                       XEXP (*r->where, 0))
+                     || label_is_jump_target_p (XEXP (*r->where, 0), insn));
 
          /* Encapsulate RELOADREG so its machine mode matches what
             used to be there.  Note that gen_lowpart_common will
@@ -6500,7 +6528,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
          return 0;
        }
 
-      endregno = regno + hard_regno_nregs[regno][GET_MODE (x)];
+      endregno = END_HARD_REGNO (x);
 
       return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
     }
@@ -6733,17 +6761,9 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
                }
              else if ((unsigned) valueno >= FIRST_PSEUDO_REGISTER)
                continue;
-             else
-               {
-                 int 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;
-                 if (i >= 0)
-                   continue;
-               }
+             else if (!in_hard_reg_set_p (reg_class_contents[(int) class],
+                                         mode, valueno))
+               continue;
              value = valtry;
              where = p;
              break;
@@ -6777,9 +6797,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
      and is also a register that appears in the address of GOAL.  */
 
   if (goal_mem && value == SET_DEST (single_set (where))
-      && refers_to_regno_for_reload_p (valueno,
-                                      (valueno
-                                       + hard_regno_nregs[valueno][mode]),
+      && refers_to_regno_for_reload_p (valueno, end_hard_regno (mode, valueno),
                                       goal, (rtx*) 0))
     return 0;