OSDN Git Service

* config/avr/avr-protos.h (avr_output_addr_vec_elt): Prototype.
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index 01286ba..86d80c1 100644 (file)
@@ -19,7 +19,6 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-
 /* This file contains subroutines used only from the file reload1.c.
    It knows how to scan one insn for operands and values
    that need to be copied into registers to make valid code.
@@ -71,7 +70,6 @@ NOTE SIDE EFFECTS:
 2 happens only when REPLACE is 1, which is only when
 actually doing the reloads, not when just counting them.
 
-
 Using a reload register for several reloads in one insn:
 
 When an insn has reloads, it is considered as having three parts:
@@ -243,6 +241,7 @@ static int push_secondary_reload PARAMS ((int, rtx, int, int, enum reg_class,
                                        enum insn_code *));
 #endif
 static enum reg_class find_valid_class PARAMS ((enum machine_mode, int));
+static int reload_inner_reg_of_subreg PARAMS ((rtx, enum machine_mode));
 static int push_reload         PARAMS ((rtx, rtx, rtx *, rtx *, enum reg_class,
                                       enum machine_mode, enum machine_mode,
                                       int, int, int, enum reload_type));
@@ -272,8 +271,6 @@ static void find_reloads_address_part PARAMS ((rtx, rtx *, enum reg_class,
 static rtx find_reloads_subreg_address PARAMS ((rtx, int, int, enum reload_type,
                                              int, rtx));
 static int find_inc_amount     PARAMS ((rtx, rtx));
-extern void debug_reload_to_stream PARAMS ((FILE *));
-extern void debug_reload PARAMS ((void));
 \f
 #ifdef HAVE_SECONDARY_RELOADS
 
@@ -414,11 +411,11 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
      can not use secondary reloads, you must work around the problem some
      other way.
 
-     Allow this when MODE is not reload_mode and assume that the generated
-     code handles this case (it does on the Alpha, which is the only place
-     this currently happens).  */
+     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 && mode == reload_mode)
+  if (in_p && class == reload_class && icode == CODE_FOR_nothing
+      && t_icode == CODE_FOR_nothing)
     abort ();
 
   /* If we need a tertiary reload, see if we have one we can reuse or else
@@ -650,7 +647,7 @@ get_secondary_mem (x, mode, opnum, type)
 void
 clear_secondary_mem ()
 {
-  bzero ((char *) secondary_memlocs, sizeof secondary_memlocs);
+  memset ((char *) secondary_memlocs, 0, sizeof secondary_memlocs);
 }
 #endif /* SECONDARY_MEMORY_NEEDED */
 \f
@@ -767,6 +764,45 @@ find_reusable_reload (p_in, out, class, type, opnum, dont_share)
   return n_reloads;
 }
 
+/* Return nonzero if X is a SUBREG which will require reloading of its
+   SUBREG_REG expression.  */
+
+static int
+reload_inner_reg_of_subreg (x, mode)
+     rtx x;
+     enum machine_mode mode;
+{
+  rtx inner;
+
+  /* Only SUBREGs are problematical.  */
+  if (GET_CODE (x) != SUBREG)
+    return 0;
+
+  inner = SUBREG_REG (x);
+
+  /* If INNER is a constant, then INNER must be reloaded.  */
+  if (CONSTANT_P (inner))
+    return 1;
+
+  /* If INNER is not a hard register, then INNER will not need to
+     be reloaded.  */
+  if (GET_CODE (inner) != REG
+      || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
+    return 0;
+
+  /* If INNER is not ok for MODE, then INNER will need reloading.  */
+  if (! HARD_REGNO_MODE_OK (REGNO (inner) + SUBREG_WORD (x), mode))
+    return 1;
+
+  /* If the outer part is a word or smaller, INNER larger than a
+     word and the number of regs for INNER is not the same as the
+     number of words in INNER, then INNER will need reloading.  */
+  return (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+         && GET_MODE_SIZE (GET_MODE (inner)) > UNITS_PER_WORD
+         && ((GET_MODE_SIZE (GET_MODE (inner)) / UNITS_PER_WORD)
+             != HARD_REGNO_NREGS (REGNO (inner), GET_MODE (inner))));
+}
+
 /* Record one reload that needs to be performed.
    IN is an rtx saying where the data are to be found before this instruction.
    OUT says where they must be stored after the instruction.
@@ -910,7 +946,8 @@ push_reload (in, out, inloc, outloc, class,
   if (in != 0 && GET_CODE (in) == SUBREG
       && (SUBREG_WORD (in) == 0 || strict_low)
 #ifdef CLASS_CANNOT_CHANGE_MODE
-      && class != CLASS_CANNOT_CHANGE_MODE
+      && (class != CLASS_CANNOT_CHANGE_MODE
+         || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode))
 #endif
       && (CONSTANT_P (SUBREG_REG (in))
          || GET_CODE (SUBREG_REG (in)) == PLUS
@@ -993,20 +1030,7 @@ push_reload (in, out, inloc, outloc, class,
   /* Similar issue for (SUBREG constant ...) if it was not handled by the
      code above.  This can happen if SUBREG_WORD != 0.  */
 
-  if (in != 0 && GET_CODE (in) == SUBREG
-      && (CONSTANT_P (SUBREG_REG (in))
-         || (GET_CODE (SUBREG_REG (in)) == REG
-             && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
-             && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (in))
-                                       + SUBREG_WORD (in),
-                                       inmode)
-                 || (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
-                     && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
-                         > UNITS_PER_WORD)
-                     && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
-                          / UNITS_PER_WORD)
-                         != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
-                                              GET_MODE (SUBREG_REG (in)))))))))
+  if (in != 0 && reload_inner_reg_of_subreg (in, inmode))
     {
       /* This relies on the fact that emit_reload_insns outputs the
         instructions for input reloads of type RELOAD_OTHER in the same
@@ -1028,7 +1052,9 @@ push_reload (in, out, inloc, outloc, class,
   if (out != 0 && GET_CODE (out) == SUBREG
       && (SUBREG_WORD (out) == 0 || strict_low)
 #ifdef CLASS_CANNOT_CHANGE_MODE
-      && class != CLASS_CANNOT_CHANGE_MODE
+      && (class != CLASS_CANNOT_CHANGE_MODE
+         || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
+                                          outmode))
 #endif
       && (CONSTANT_P (SUBREG_REG (out))
          || strict_low
@@ -1093,18 +1119,7 @@ push_reload (in, out, inloc, outloc, class,
      However, we must reload the inner reg *as well as* the subreg in
      that case.  In this case, the inner reg is an in-out reload.  */
 
-  if (out != 0 && GET_CODE (out) == SUBREG
-      && GET_CODE (SUBREG_REG (out)) == REG
-      && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
-      && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (out)) + SUBREG_WORD (out),
-                               outmode)
-         || (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)
-                 != HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
-                                      GET_MODE (SUBREG_REG (out)))))))
+  if (out != 0 && reload_inner_reg_of_subreg (out, outmode))
     {
       /* This relies on the fact that emit_reload_insns outputs the
         instructions for output reloads of type RELOAD_OTHER in reverse
@@ -1543,7 +1558,7 @@ remove_address_replacements (in_rtx)
   char reload_flags[MAX_RELOADS];
   int something_changed = 0;
 
-  bzero (reload_flags, sizeof reload_flags);
+  memset (reload_flags, 0, sizeof reload_flags);
   for (i = 0, j = 0; i < n_replacements; i++)
     {
       if (loc_mentioned_in_p (replacements[i].where, in_rtx))
@@ -1655,6 +1670,7 @@ combine_reloads ()
                && ! (GET_CODE (rld[i].in) == REG
                      && reg_overlap_mentioned_for_reload_p (rld[i].in,
                                                             rld[output_reload].out))))
+       && ! reload_inner_reg_of_subreg (rld[i].in, rld[i].inmode)
        && (reg_class_size[(int) rld[i].class]
            || SMALL_REGISTER_CLASSES)
        /* We will allow making things slightly worse by combining an
@@ -2158,26 +2174,26 @@ decompose (x)
          || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
        {
          val.base = XEXP (addr, 0);
-         val.start = - GET_MODE_SIZE (GET_MODE (x));
+         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
+       {
+         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;
-           }
-       }
-      
+           {
+             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);
@@ -2296,7 +2312,7 @@ immune_p (x, y, ydata)
   if (GET_CODE (x) != MEM)
     return 1;
 
-  xdata =  decompose (x);
+  xdata = decompose (x);
 
   if (! rtx_equal_p (xdata.base, ydata.base))
     {
@@ -2318,7 +2334,6 @@ immune_p (x, y, ydata)
       return 0;
     }
 
-
   return (xdata.start >= ydata.end || ydata.start >= xdata.end);
 }
 
@@ -2384,6 +2399,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
   int no_input_reloads = 0, no_output_reloads = 0;
   int n_alternatives;
   int this_alternative[MAX_RECOG_OPERANDS];
+  char this_alternative_match_win[MAX_RECOG_OPERANDS];
   char this_alternative_win[MAX_RECOG_OPERANDS];
   char this_alternative_offmemok[MAX_RECOG_OPERANDS];
   char this_alternative_earlyclobber[MAX_RECOG_OPERANDS];
@@ -2395,6 +2411,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
   int operand_reloadnum[MAX_RECOG_OPERANDS];
   int goal_alternative_matches[MAX_RECOG_OPERANDS];
   int goal_alternative_matched[MAX_RECOG_OPERANDS];
+  char goal_alternative_match_win[MAX_RECOG_OPERANDS];
   char goal_alternative_win[MAX_RECOG_OPERANDS];
   char goal_alternative_offmemok[MAX_RECOG_OPERANDS];
   char goal_alternative_earlyclobber[MAX_RECOG_OPERANDS];
@@ -2434,7 +2451,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
   /* The eliminated forms of any secondary memory locations are per-insn, so
      clear them out here.  */
 
-  bzero ((char *) secondary_memlocs_elim, sizeof secondary_memlocs_elim);
+  memset ((char *) secondary_memlocs_elim, 0, sizeof secondary_memlocs_elim);
 #endif
 
   /* Dispose quickly of (set (reg..) (reg..)) if both have hard regs and it
@@ -2726,6 +2743,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        {
          register char *p = constraints[i];
          register int win = 0;
+         int did_match = 0;
          /* 0 => this operand can be reloaded somehow for this alternative */
          int badop = 1;
          /* 0 => this operand can be reloaded if the alternative allows regs.  */
@@ -2824,6 +2842,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 
          this_alternative[i] = (int) NO_REGS;
          this_alternative_win[i] = 0;
+         this_alternative_match_win[i] = 0;
          this_alternative_offmemok[i] = 0;
          this_alternative_earlyclobber[i] = 0;
          this_alternative_matches[i] = -1;
@@ -2863,7 +2882,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              case '#':
                /* Ignore rest of this alternative as far as
                   reloading is concerned.  */
-               while (*p && *p != ',') p++;
+               while (*p && *p != ',')
+                 p++;
                break;
 
              case '0':  case '1':  case '2':  case '3':  case '4':
@@ -2887,9 +2907,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                       only on one side of its diagonal.  */
                    ? (operands_match
                       [(c == commutative || c == commutative + 1)
-                      ? 2*commutative + 1 - c : c]
+                      ? 2 * commutative + 1 - c : c]
                       [(i == commutative || i == commutative + 1)
-                      ? 2*commutative + 1 - i : i])
+                      ? 2 * commutative + 1 - i : i])
                    : operands_match[c][i])
                  {
                    /* If we are matching a non-offsettable address where an
@@ -2901,7 +2921,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                        && ! this_alternative_win[c])
                      bad = 1;
 
-                   win = this_alternative_win[c];
+                   did_match = this_alternative_win[c];
                  }
                else
                  {
@@ -2937,12 +2957,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                   operand also had to match the same thing as this
                   operand, we don't know how to do that.  So reject this
                   alternative.  */
-               if (! win || force_reload)
+               if (! did_match || force_reload)
                  for (j = 0; j < i; j++)
                    if (this_alternative_matches[j]
                        == this_alternative_matches[i])
                      badop = 1;
-
                break;
 
              case 'p':
@@ -3125,21 +3144,18 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                  = (int) reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
                goto reg;
 
+             default:
+               if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
+                 {
 #ifdef EXTRA_CONSTRAINT
-             case 'Q':
-             case 'R':
-             case 'S':
-             case 'T':
-             case 'U':
-               if (EXTRA_CONSTRAINT (operand, c))
-                 win = 1;
-               break;
+                   if (EXTRA_CONSTRAINT (operand, c))
+                     win = 1;
 #endif
+                   break;
+                 }
 
-             default:
                this_alternative[i]
                  = (int) reg_class_subunion[this_alternative[i]][(int) REG_CLASS_FROM_LETTER (c)];
-
              reg:
                if (GET_MODE (operand) == BLKmode)
                  break;
@@ -3162,6 +3178,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
          this_alternative_earlyclobber[i] = earlyclobber;
          if (win && ! force_reload)
            this_alternative_win[i] = 1;
+         else if (did_match && ! force_reload)
+           this_alternative_match_win[i] = 1;
          else
            {
              int const_to_mem = 0;
@@ -3221,7 +3239,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                       && ! const_to_mem)
                bad = 1;
 
-
              /* We prefer to reload pseudos over reloading other things,
                 since such reloads may be able to be eliminated later.
                 If we are reloading a SCRATCH, we won't be generating any
@@ -3264,8 +3281,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
             Don't do this if the preferred class has only one register
             because we might otherwise exhaust the class.  */
 
-
-         if (! win && this_alternative[i] != (int) NO_REGS
+         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)
            {
@@ -3291,7 +3308,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 
       for (i = 0; i < noperands; i++)
        if (this_alternative_earlyclobber[i]
-           && this_alternative_win[i])
+           && (this_alternative_win[i] || this_alternative_match_win[i]))
          {
            struct decomposition early_data;
 
@@ -3334,6 +3351,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                    {
                      losers++;
                      this_alternative_win[j] = 0;
+                     this_alternative_match_win[j] = 0;
                    }
                  else
                    break;
@@ -3344,11 +3362,13 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              {
                losers++;
                this_alternative_win[i] = 0;
+               this_alternative_match_win[j] = 0;
                for (j = 0; j < noperands; j++)
                  if (this_alternative_matches[j] == i
-                     && this_alternative_win[j])
+                     && this_alternative_match_win[j])
                    {
                      this_alternative_win[j] = 0;
+                     this_alternative_match_win[j] = 0;
                      losers++;
                    }
              }
@@ -3367,7 +3387,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
            }
          for (i = 0; i < noperands; i++)
            {
-             goal_alternative_win[i] = 1;
+             goal_alternative_win[i] = this_alternative_win[i];
+             goal_alternative_match_win[i] = this_alternative_match_win[i];
              goal_alternative[i] = this_alternative[i];
              goal_alternative_offmemok[i] = this_alternative_offmemok[i];
              goal_alternative_matches[i] = this_alternative_matches[i];
@@ -3395,6 +3416,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
            {
              goal_alternative[i] = this_alternative[i];
              goal_alternative_win[i] = this_alternative_win[i];
+             goal_alternative_match_win[i] = this_alternative_match_win[i];
              goal_alternative_offmemok[i] = this_alternative_offmemok[i];
              goal_alternative_matches[i] = this_alternative_matches[i];
              goal_alternative_earlyclobber[i]
@@ -3476,12 +3498,15 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 
   for (i = 0; i < noperands; i++)
     goal_alternative_matched[i] = -1;
-
   for (i = 0; i < noperands; i++)
     if (! goal_alternative_win[i]
        && goal_alternative_matches[i] >= 0)
       goal_alternative_matched[goal_alternative_matches[i]] = i;
 
+  for (i = 0; i < noperands; i++)
+    goal_alternative_win[i] |= goal_alternative_match_win[i];
+
   /* If the best alternative is with operands 1 and 2 swapped,
      consider them swapped before reporting the reloads.  Update the
      operand numbers of any reloads already pushed.  */
@@ -3499,7 +3524,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
       tem = *recog_data.operand_loc[commutative];
       *recog_data.operand_loc[commutative]
        = *recog_data.operand_loc[commutative + 1];
-      *recog_data.operand_loc[commutative+1] = tem;
+      *recog_data.operand_loc[commutative + 1] = tem;
 
       for (i = 0; i < n_reloads; i++)
        {
@@ -3935,8 +3960,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
            {
              int secondary_in_reload = rld[i].secondary_in_reload;
 
-             rld[secondary_in_reload].when_needed
-               = RELOAD_FOR_OPADDR_ADDR;
+             rld[secondary_in_reload].when_needed = RELOAD_FOR_OPADDR_ADDR;
 
              /* If there's a tertiary reload we have to change it also.  */
              if (secondary_in_reload > 0
@@ -3951,8 +3975,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
            {
              int secondary_out_reload = rld[i].secondary_out_reload;
 
-             rld[secondary_out_reload].when_needed
-               = RELOAD_FOR_OPADDR_ADDR;
+             rld[secondary_out_reload].when_needed = RELOAD_FOR_OPADDR_ADDR;
 
              /* If there's a tertiary reload we have to change it also.  */
              if (secondary_out_reload
@@ -4006,7 +4029,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
     int first_op_addr_num = -2;
     int first_inpaddr_num[MAX_RECOG_OPERANDS];
     int first_outpaddr_num[MAX_RECOG_OPERANDS];
-    int need_change= 0;
+    int need_change = 0;
     /* We use last_op_addr_reload and the contents of the above arrays
        first as flags - -2 means no instance encountered, -1 means exactly
        one instance encountered.
@@ -4513,7 +4536,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
 
       else if (regno < FIRST_PSEUDO_REGISTER
               && REGNO_MODE_OK_FOR_BASE_P (regno, mode)
-              && ! regno_clobbered_p (regno, this_insn))
+              && ! regno_clobbered_p (regno, this_insn, mode, 0))
        return 0;
 
       /* If we do not have one of the cases above, we must do the reload.  */
@@ -5119,12 +5142,12 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
           of another register or by a constant value.  Thus, these
           operands must match.  */
        if (op0 != XEXP (op1, 0))
-         abort();
+         abort ();
 
        /* Require index register (or constant).  Let's just handle the
           register case in the meantime... If the target allows
           auto-modify by a constant then we could try replacing a pseudo
-          register with its equivalent constant where applicable. */
+          register with its equivalent constant where applicable.  */
        if (REG_P (XEXP (op1, 1)))
          if (!REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
            find_reloads_address_1 (mode, XEXP (op1, 1), 1, &XEXP (op1, 1),
@@ -5132,7 +5155,9 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
 
        if (REG_P (XEXP (op1, 0)))
          {
-           register int regno = REGNO (XEXP (op1, 0));
+           rtx link;
+           int regno = REGNO (XEXP (op1, 0));
+           int reloadnum;
 
            /* A register that is incremented cannot be constant!  */
            if (regno >= FIRST_PSEUDO_REGISTER
@@ -5155,15 +5180,17 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
                       write back the value after reading it, hence we actually
                       need two registers.  */
                    find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
-                                         &XEXP (tem, 0), opnum, type,
+                                         &XEXP (tem, 0), opnum,
+                                         RELOAD_OTHER,
                                          ind_levels, insn);
 
                    /* Then reload the memory location into a base
                       register.  */
-                   push_reload (tem, tem, &XEXP (x, 0), &XEXP (op1, 0),
-                                BASE_REG_CLASS, GET_MODE (x), GET_MODE (x),
-                                0, 0, opnum, RELOAD_OTHER);
-                   break;
+                   reloadnum = push_reload (tem, tem, &XEXP (x, 0),
+                                            &XEXP (op1, 0), BASE_REG_CLASS,
+                                            GET_MODE (x), GET_MODE (x), 0,
+                                            0, opnum, RELOAD_OTHER);
+                   goto reg_inc;
                  }
              }
 
@@ -5173,15 +5200,22 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
            /* We require a base register here...  */
            if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
              {
-               push_reload (XEXP (op1, 0), XEXP (x, 0),
-                            &XEXP (op1, 0), &XEXP (x, 0), 
-                            BASE_REG_CLASS,
-                            GET_MODE (x), GET_MODE (x), 0, 0,
-                            opnum, RELOAD_OTHER);
+               reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
+                                        &XEXP (op1, 0), &XEXP (x, 0),
+                                        BASE_REG_CLASS,
+                                        GET_MODE (x), GET_MODE (x), 0, 0,
+                                        opnum, RELOAD_OTHER);
              }
+
+           /* Update the REG_INC notes.  */
+         reg_inc:
+           for (link = REG_NOTES (this_insn); link; link = XEXP (link, 1))
+             if (REG_NOTE_KIND (link) == REG_INC
+                 && REGNO (XEXP (link, 0)) == regno)
+               push_replacement (&XEXP (link, 0), reloadnum, VOIDmode);
          }
        else
-         abort();
+         abort ();
       }
       return 0;
 
@@ -5267,21 +5301,18 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
                        && ((*insn_data[icode].operand[1].predicate)
                            (equiv, Pmode))))
                {
-                 loc = &XEXP (x, 0);
+                 /* We use the original pseudo for loc, so that
+                    emit_reload_insns() knows which pseudo this
+                    reload refers to and updates the pseudo rtx, not
+                    its equivalent memory location, as well as the
+                    corresponding entry in reg_last_reload_reg.  */
+                 loc = &XEXP (x_orig, 0);
                  x = XEXP (x, 0);
                  reloadnum
                    = push_reload (x, x, loc, loc,
                                   (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
                                   GET_MODE (x), GET_MODE (x), 0, 0,
                                   opnum, RELOAD_OTHER);
-
-                 /* If we created a new MEM based on reg_equiv_mem[REGNO], then
-                    LOC above is part of the new MEM, not the MEM in INSN.
-
-                    We must also replace the address of the MEM in INSN.  */
-                 if (&XEXP (x_orig, 0) != loc)
-                   push_replacement (&XEXP (x_orig, 0), reloadnum, VOIDmode);
-
                }
              else
                {
@@ -5421,7 +5452,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
           in this insn, reload it into some other register to be safe.
           The CLOBBER is supposed to make the register unavailable
           from before this insn to after it.  */
-       if (regno_clobbered_p (regno, this_insn))
+       if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0))
          {
            push_reload (x, NULL_RTX, loc, NULL_PTR,
                         (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
@@ -5519,18 +5550,7 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels)
     {
       rtx tem;
 
-      /* If this is a CONST_INT, it could have been created by a
-        plus_constant call in eliminate_regs, which means it may be
-        on the reload_obstack.  reload_obstack will be freed later, so
-        we can't allow such RTL to be put in the constant pool.  There
-        is code in force_const_mem to check for this case, but it doesn't
-        work because we have already popped off the reload_obstack, so
-        rtl_obstack == saveable_obstack is true at this point.  */
-      if (GET_CODE (x) == CONST_INT)
-       tem = x = force_const_mem (mode, GEN_INT (INTVAL (x)));
-      else
-       tem = x = force_const_mem (mode, x);
-
+      tem = x = force_const_mem (mode, x);
       find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
                            opnum, type, ind_levels, 0);
     }
@@ -5542,12 +5562,7 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels)
     {
       rtx tem;
 
-      /* See comment above.  */
-      if (GET_CODE (XEXP (x, 1)) == CONST_INT)
-       tem = force_const_mem (GET_MODE (x), GEN_INT (INTVAL (XEXP (x, 1))));
-      else
-       tem = force_const_mem (GET_MODE (x), XEXP (x, 1));
-
+      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),
                            opnum, type, ind_levels, 0);
@@ -5916,7 +5931,7 @@ refers_to_regno_for_reload_p (regno, endregno, x, loc)
       else if (fmt[i] == 'E')
        {
          register int j;
-         for (j = XVECLEN (x, i) - 1; j >=0; j--)
+         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
            if (loc != &XVECEXP (x, i, j)
                && refers_to_regno_for_reload_p (regno, endregno,
                                                 XVECEXP (x, i, j), loc))
@@ -6181,16 +6196,29 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
                      && (valtry
                          = operand_subword (SET_DEST (pat), 1, 0, VOIDmode))
                      && (valueno = true_regnum (valtry)) >= 0)))
-           if (other >= 0
-               ? valueno == other
-               : ((unsigned) valueno < FIRST_PSEUDO_REGISTER
-                  && TEST_HARD_REG_BIT (reg_class_contents[(int) class],
-                                        valueno)))
-             {
-               value = valtry;
-               where = p;
-               break;
-             }
+           {
+             if (other >= 0)
+               {
+                 if (valueno != other)
+                   continue;
+               }
+             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;
+               }
+             value = valtry;
+             where = p;
+             break;
+           }
        }
     }
 
@@ -6288,10 +6316,10 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
       if (GET_CODE (p) == CALL_INSN)
        {
          int i;
-         
+
          if (goal_mem || need_stable_sp)
            return 0;
-         
+
          if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER)
            for (i = 0; i < nregs; ++i)
              if (call_used_regs[regno + i])
@@ -6309,7 +6337,7 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
        return 0;
 #endif
 
-      if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
+      if (INSN_P (p))
        {
          pat = PATTERN (p);
 
@@ -6432,7 +6460,7 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
                              && xregno + xnregs > regno)
                            return 0;
                          else if (xregno < valueno + valuenregs
-                             && xregno + xnregs > valueno)
+                                  && xregno + xnregs > valueno)
                            return 0;
                          else if (goal_mem_addr_varies
                                   && reg_overlap_mentioned_for_reload_p (dest,
@@ -6505,11 +6533,11 @@ find_inc_amount (x, inced)
               && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
               && XEXP (addr, 0) == inced
               && GET_CODE (XEXP (XEXP (addr, 1), 1)) == CONST_INT)
-       { 
-         i = INTVAL (XEXP (XEXP (addr, 1), 1));
-         return i < 0 ? -i : i;
-       }
-   }
+       {
+         i = INTVAL (XEXP (XEXP (addr, 1), 1));
+         return i < 0 ? -i : i;
+       }
+    }
 
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
@@ -6535,16 +6563,27 @@ find_inc_amount (x, inced)
   return 0;
 }
 \f
-/* Return 1 if register REGNO is the subject of a clobber in insn INSN.  */
+/* Return 1 if register REGNO is the subject of a clobber in insn INSN.
+   If SETS is nonzero, also consider SETs.  */
 
 int
-regno_clobbered_p (regno, insn)
+regno_clobbered_p (regno, insn, mode, sets)
      unsigned int regno;
      rtx insn;
+     enum machine_mode mode;
+     int sets;
 {
-  if (GET_CODE (PATTERN (insn)) == CLOBBER
+  int nregs = HARD_REGNO_NREGS (regno, mode);
+  int endregno = regno + nregs;
+
+  if ((GET_CODE (PATTERN (insn)) == CLOBBER
+       || (sets && GET_CODE (PATTERN (insn)) == SET))
       && GET_CODE (XEXP (PATTERN (insn), 0)) == REG)
-    return REGNO (XEXP (PATTERN (insn), 0)) == regno;
+    {
+      int test = REGNO (XEXP (PATTERN (insn), 0));
+
+      return test >= regno && test < endregno;
+    }
 
   if (GET_CODE (PATTERN (insn)) == PARALLEL)
     {
@@ -6553,9 +6592,15 @@ regno_clobbered_p (regno, insn)
       for (; i >= 0; i--)
        {
          rtx elt = XVECEXP (PATTERN (insn), 0, i);
-         if (GET_CODE (elt) == CLOBBER && GET_CODE (XEXP (elt, 0)) == REG
-             && REGNO (XEXP (elt, 0)) == regno)
-           return 1;
+         if ((GET_CODE (elt) == CLOBBER
+              || (sets && GET_CODE (PATTERN (insn)) == SET))
+             && GET_CODE (XEXP (elt, 0)) == REG)
+           {
+             int test = REGNO (XEXP (elt, 0));
+             
+             if (test >= regno && test < endregno)
+               return 1;
+           }
        }
     }
 
@@ -6620,7 +6665,7 @@ debug_reload_to_stream (f)
        fprintf (f, ", optional");
 
       if (rld[r].nongroup)
-       fprintf (stderr, ", nongroup");
+       fprintf (f, ", nongroup");
 
       if (rld[r].inc != 0)
        fprintf (f, ", inc by %d", rld[r].inc);
@@ -6664,13 +6709,13 @@ debug_reload_to_stream (f)
       prefix = "\n\t";
       if (rld[r].secondary_in_icode != CODE_FOR_nothing)
        {
-         fprintf (stderr, "%ssecondary_in_icode = %s", prefix,
+         fprintf (f, "%ssecondary_in_icode = %s", prefix,
                   insn_data[rld[r].secondary_in_icode].name);
          prefix = ", ";
        }
 
       if (rld[r].secondary_out_icode != CODE_FOR_nothing)
-       fprintf (stderr, "%ssecondary_out_icode = %s", prefix,
+       fprintf (f, "%ssecondary_out_icode = %s", prefix,
                 insn_data[rld[r].secondary_out_icode].name);
 
       fprintf (f, "\n");