OSDN Git Service

2009-08-14 Douglas B Rupp <rupp@gnat.com>
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index a391c45..257acd0 100644 (file)
@@ -1,6 +1,6 @@
 /* Search an insn for pseudo regs that must be in hard regs and are not.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -363,7 +363,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
   sri.icode = CODE_FOR_nothing;
   sri.prev_sri = prev_sri;
   rclass = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
-  icode = sri.icode;
+  icode = (enum insn_code) sri.icode;
 
   /* If we don't need any secondary registers, done.  */
   if (rclass == NO_REGS && icode == CODE_FOR_nothing)
@@ -525,7 +525,7 @@ secondary_reload_class (bool in_p, enum reg_class rclass,
   sri.icode = CODE_FOR_nothing;
   sri.prev_sri = NULL;
   rclass = targetm.secondary_reload (in_p, x, rclass, mode, &sri);
-  icode = sri.icode;
+  icode = (enum insn_code) sri.icode;
 
   /* If there are no secondary reloads at all, we return NO_REGS.
      If an intermediate register is needed, we return its class.  */
@@ -685,15 +685,16 @@ find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
 
       if (bad || !good)
        continue;
-      cost = REGISTER_MOVE_COST (outer, rclass, dest_class);
+      cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass, dest_class);
 
       if ((reg_class_size[rclass] > best_size
           && (best_cost < 0 || best_cost >= cost))
          || best_cost > cost)
        {
-         best_class = rclass;
+         best_class = (enum reg_class) rclass;
          best_size = reg_class_size[rclass];
-         best_cost = REGISTER_MOVE_COST (outer, rclass, dest_class);
+         best_cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass,
+                                         dest_class);
        }
     }
 
@@ -1403,13 +1404,36 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
              else
                remove_address_replacements (rld[i].in);
            }
-         rld[i].in = in;
-         rld[i].in_reg = in_reg;
+         /* When emitting reloads we don't necessarily look at the in-
+            and outmode, but also directly at the operands (in and out).
+            So we can't simply overwrite them with whatever we have found
+            for this (to-be-merged) reload, we have to "merge" that too.
+            Reusing another reload already verified that we deal with the
+            same operands, just possibly in different modes.  So we
+            overwrite the operands only when the new mode is larger.
+            See also PR33613.  */
+         if (!rld[i].in
+             || GET_MODE_SIZE (GET_MODE (in))
+                  > GET_MODE_SIZE (GET_MODE (rld[i].in)))
+           rld[i].in = in;
+         if (!rld[i].in_reg
+             || (in_reg
+                 && GET_MODE_SIZE (GET_MODE (in_reg))
+                    > GET_MODE_SIZE (GET_MODE (rld[i].in_reg))))
+           rld[i].in_reg = in_reg;
        }
       if (out != 0)
        {
-         rld[i].out = out;
-         rld[i].out_reg = outloc ? *outloc : 0;
+         if (!rld[i].out
+             || (out
+                 && GET_MODE_SIZE (GET_MODE (out))
+                    > GET_MODE_SIZE (GET_MODE (rld[i].out))))
+           rld[i].out = out;
+         if (outloc
+             && (!rld[i].out_reg
+                 || GET_MODE_SIZE (GET_MODE (*outloc))
+                    > GET_MODE_SIZE (GET_MODE (rld[i].out_reg))))
+           rld[i].out_reg = *outloc;
        }
       if (reg_class_subset_p (rclass, rld[i].rclass))
        rld[i].rclass = rclass;
@@ -1493,7 +1517,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
         value for the incoming operand (same as outgoing one).  */
       if (rld[i].reg_rtx == out
          && (REG_P (in) || CONSTANT_P (in))
-         && 0 != find_equiv_reg (in, this_insn, 0, REGNO (out),
+         && 0 != find_equiv_reg (in, this_insn, NO_REGS, REGNO (out),
                                  static_reload_reg_p, i, inmode))
        rld[i].in = out;
     }
@@ -1526,8 +1550,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
            && reg_mentioned_p (XEXP (note, 0), in)
            /* Check that a former pseudo is valid; see find_dummy_reload.  */
            && (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
-               || (!bitmap_bit_p (DF_LIVE_OUT (ENTRY_BLOCK_PTR),
-                                  ORIGINAL_REGNO (XEXP (note, 0)))
+               || (! bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
+                                   ORIGINAL_REGNO (XEXP (note, 0)))
                    && hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] == 1))
            && ! refers_to_regno_for_reload_p (regno,
                                               end_hard_regno (rel_mode,
@@ -2004,7 +2028,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
             can ignore the conflict).  We must never introduce writes
             to such hardregs, as they would clobber the other live
             pseudo.  See PR 20973.  */
-          || (!bitmap_bit_p (DF_LIVE_OUT (ENTRY_BLOCK_PTR),
+          || (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
                             ORIGINAL_REGNO (in))
              /* Similarly, only do this if we can be sure that the death
                 note is still valid.  global can assign some hardreg to
@@ -2111,11 +2135,15 @@ hard_reg_set_here_p (unsigned int beg_regno, unsigned int end_regno, rtx x)
 int
 strict_memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
 {
+#ifdef GO_IF_LEGITIMATE_ADDRESS
   GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
   return 0;
 
  win:
   return 1;
+#else
+  return targetm.legitimate_address_p (mode, addr, 1);
+#endif
 }
 \f
 /* Like rtx_equal_p except that it allows a REG and a SUBREG to match
@@ -2365,12 +2393,12 @@ decompose (rtx x)
          offset = XEXP (offset, 0);
        if (GET_CODE (offset) == PLUS)
          {
-           if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
+           if (CONST_INT_P (XEXP (offset, 0)))
              {
                base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
                offset = XEXP (offset, 0);
              }
-           else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
+           else if (CONST_INT_P (XEXP (offset, 1)))
              {
                base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
                offset = XEXP (offset, 1);
@@ -2381,7 +2409,7 @@ decompose (rtx x)
                offset = const0_rtx;
              }
          }
-       else if (GET_CODE (offset) != CONST_INT)
+       else if (!CONST_INT_P (offset))
          {
            base = gen_rtx_PLUS (GET_MODE (base), base, offset);
            offset = const0_rtx;
@@ -2390,7 +2418,7 @@ decompose (rtx x)
        if (all_const && GET_CODE (base) == PLUS)
          base = gen_rtx_CONST (GET_MODE (base), base);
        
-       gcc_assert (GET_CODE (offset) == CONST_INT);
+       gcc_assert (CONST_INT_P (offset));
        
        val.start = INTVAL (offset);
        val.end = val.start + GET_MODE_SIZE (GET_MODE (x));
@@ -2542,7 +2570,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   enum reload_usage { RELOAD_READ, RELOAD_READ_WRITE, RELOAD_WRITE } modified[MAX_RECOG_OPERANDS];
   int no_input_reloads = 0, no_output_reloads = 0;
   int n_alternatives;
-  int this_alternative[MAX_RECOG_OPERANDS];
+  enum reg_class 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];
@@ -2972,12 +3000,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              if (REG_P (SUBREG_REG (operand))
                  && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
                {
-                 if (!subreg_offset_representable_p
-                       (REGNO (SUBREG_REG (operand)),
-                        GET_MODE (SUBREG_REG (operand)),
-                        SUBREG_BYTE (operand),
-                        GET_MODE (operand)))
-                    force_reload = 1;
+                 if (simplify_subreg_regno (REGNO (SUBREG_REG (operand)),
+                                            GET_MODE (SUBREG_REG (operand)),
+                                            SUBREG_BYTE (operand),
+                                            GET_MODE (operand)) < 0)
+                   force_reload = 1;
                  offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
                                                 GET_MODE (SUBREG_REG (operand)),
                                                 SUBREG_BYTE (operand),
@@ -3037,7 +3064,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                force_reload = 1;
            }
 
-         this_alternative[i] = (int) NO_REGS;
+         this_alternative[i] = NO_REGS;
          this_alternative_win[i] = 0;
          this_alternative_match_win[i] = 0;
          this_alternative_offmemok[i] = 0;
@@ -3124,7 +3151,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                       this combination, because we can't reload it.  */
                    if (this_alternative_offmemok[m]
                        && MEM_P (recog_data.operand[m])
-                       && this_alternative[m] == (int) NO_REGS
+                       && this_alternative[m] == NO_REGS
                        && ! this_alternative_win[m])
                      bad = 1;
 
@@ -3140,7 +3167,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                    if (this_alternative_win[m])
                      losers++;
                    this_alternative_win[m] = 0;
-                   if (this_alternative[m] == (int) NO_REGS)
+                   if (this_alternative[m] == NO_REGS)
                      bad = 1;
                    /* But count the pair only once in the total badness of
                       this alternative, if the pair can be a dummy reload.
@@ -3189,8 +3216,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              case 'p':
                /* All necessary reloads for an address_operand
                   were handled in find_reloads_address.  */
-               this_alternative[i]
-                 = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
+               this_alternative[i] = base_reg_class (VOIDmode, ADDRESS,
+                                                     SCRATCH);
                win = 1;
                badop = 0;
                break;
@@ -3295,7 +3322,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                break;
 
              case 's':
-               if (GET_CODE (operand) == CONST_INT
+               if (CONST_INT_P (operand)
                    || (GET_CODE (operand) == CONST_DOUBLE
                        && GET_MODE (operand) == VOIDmode))
                  break;
@@ -3306,7 +3333,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                break;
 
              case 'n':
-               if (GET_CODE (operand) == CONST_INT
+               if (CONST_INT_P (operand)
                    || (GET_CODE (operand) == CONST_DOUBLE
                        && GET_MODE (operand) == VOIDmode))
                  win = 1;
@@ -3320,7 +3347,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
              case 'N':
              case 'O':
              case 'P':
-               if (GET_CODE (operand) == CONST_INT
+               if (CONST_INT_P (operand)
                    && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p))
                  win = 1;
                break;
@@ -3349,7 +3376,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
              case 'r':
                this_alternative[i]
-                 = (int) reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
+                 = reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
                goto reg;
 
              default:
@@ -3395,8 +3422,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
                        /* If we didn't already win, we can reload
                           the address into a base register.  */
-                       this_alternative[i]
-                         = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
+                       this_alternative[i] = base_reg_class (VOIDmode,
+                                                             ADDRESS,
+                                                             SCRATCH);
                        badop = 0;
                        break;
                      }
@@ -3408,9 +3436,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                  }
 
                this_alternative[i]
-                 = (int) (reg_class_subunion
-                          [this_alternative[i]]
-                          [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
+                 = (reg_class_subunion
+                    [this_alternative[i]]
+                    [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
              reg:
                if (GET_MODE (operand) == BLKmode)
                  break;
@@ -3427,7 +3455,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
          /* If this operand could be handled with a reg,
             and some reg is allowed, then this operand can be handled.  */
-         if (winreg && this_alternative[i] != (int) NO_REGS)
+         if (winreg && this_alternative[i] != NO_REGS)
            badop = 0;
 
          /* Record which operands fit this alternative.  */
@@ -3446,7 +3474,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                bad = 1;
              /* Alternative loses if it has no regs for a reg operand.  */
              if (REG_P (operand)
-                 && this_alternative[i] == (int) NO_REGS
+                 && this_alternative[i] == NO_REGS
                  && this_alternative_matches[i] < 0)
                bad = 1;
 
@@ -3459,14 +3487,13 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                 precisely the same as in the code below that calls
                 force_const_mem.  */
              if (CONST_POOL_OK_P (operand)
-                 && ((PREFERRED_RELOAD_CLASS (operand,
-                                              (enum reg_class) this_alternative[i])
+                 && ((PREFERRED_RELOAD_CLASS (operand, this_alternative[i])
                       == NO_REGS)
                      || no_input_reloads)
                  && operand_mode[i] != VOIDmode)
                {
                  const_to_mem = 1;
-                 if (this_alternative[i] != (int) NO_REGS)
+                 if (this_alternative[i] != NO_REGS)
                    losers++;
                }
 
@@ -3486,19 +3513,17 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                 LIMIT_RELOAD_CLASS, but we don't check that
                 here.  */
 
-             if (! CONSTANT_P (operand)
-                 && (enum reg_class) this_alternative[i] != NO_REGS)
+             if (! CONSTANT_P (operand) && this_alternative[i] != NO_REGS)
                {
-                 if (PREFERRED_RELOAD_CLASS
-                       (operand, (enum reg_class) this_alternative[i])
+                 if (PREFERRED_RELOAD_CLASS (operand, this_alternative[i])
                      == NO_REGS)
                    reject = 600;
 
 #ifdef PREFERRED_OUTPUT_RELOAD_CLASS
                  if (operand_type[i] == RELOAD_FOR_OUTPUT
-                     && PREFERRED_OUTPUT_RELOAD_CLASS
-                          (operand, (enum reg_class) this_alternative[i])
-                        == NO_REGS)
+                     && (PREFERRED_OUTPUT_RELOAD_CLASS (operand,
+                                                       this_alternative[i])
+                         == NO_REGS))
                    reject = 600;
 #endif
                }
@@ -3546,7 +3571,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
             because we might otherwise exhaust the class.  */
 
          if (! win && ! did_match
-             && this_alternative[i] != (int) NO_REGS
+             && this_alternative[i] != NO_REGS
              && GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
              && reg_class_size [(int) preferred_class[i]] > 0
              && ! SMALL_REGISTER_CLASS_P (preferred_class[i]))
@@ -3560,7 +3585,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                     common case anyway.  */
                  if (reg_class_subset_p (preferred_class[i],
                                          this_alternative[i]))
-                   this_alternative[i] = (int) preferred_class[i];
+                   this_alternative[i] = preferred_class[i];
                  else
                    reject += (2 + 2 * pref_or_nothing[i]);
                }
@@ -3843,49 +3868,61 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   /* Any constants that aren't allowed and can't be reloaded
      into registers are here changed into memory references.  */
   for (i = 0; i < noperands; i++)
-    if (! goal_alternative_win[i]
-       && CONST_POOL_OK_P (recog_data.operand[i])
-       && ((PREFERRED_RELOAD_CLASS (recog_data.operand[i],
-                                    (enum reg_class) goal_alternative[i])
-            == NO_REGS)
-           || no_input_reloads)
-       && operand_mode[i] != VOIDmode)
+    if (! goal_alternative_win[i])
       {
-       int this_address_reloaded;
+       rtx op = recog_data.operand[i];
+       rtx subreg = NULL_RTX;
+       rtx plus = NULL_RTX;
+       enum machine_mode mode = operand_mode[i];
+
+       /* Reloads of SUBREGs of CONSTANT RTXs are handled later in
+          push_reload so we have to let them pass here.  */
+       if (GET_CODE (op) == SUBREG)
+         {
+           subreg = op;
+           op = SUBREG_REG (op);
+           mode = GET_MODE (op);
+         }
 
-       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,
-                                &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;
-      }
+       if (GET_CODE (op) == PLUS)
+         {
+           plus = op;
+           op = XEXP (op, 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);
+       if (CONST_POOL_OK_P (op)
+           && ((PREFERRED_RELOAD_CLASS (op,
+                                        (enum reg_class) goal_alternative[i])
+                == NO_REGS)
+               || no_input_reloads)
+           && mode != VOIDmode)
+         {
+           int this_address_reloaded;
+           rtx tem = force_const_mem (mode, op);
 
-       substed_operand[i] = recog_data.operand[i]
-         = find_reloads_toplev (tem, i, address_type[i],
-                                ind_levels, 0, insn, NULL);
+           /* If we stripped a SUBREG or a PLUS above add it back.  */
+           if (plus != NULL_RTX)
+             tem = gen_rtx_PLUS (mode, XEXP (plus, 0), tem);
+
+           if (subreg != NULL_RTX)
+             tem = gen_rtx_SUBREG (operand_mode[i], tem, SUBREG_BYTE (subreg));
+
+           this_address_reloaded = 0;
+           substed_operand[i] = recog_data.operand[i]
+             = find_reloads_toplev (tem, i, address_type[i], ind_levels,
+                                    0, insn, &this_address_reloaded);
+
+           /* If the alternative accepts constant pool refs directly
+              there will be no reload needed at all.  */
+           if (plus == NULL_RTX
+               && subreg == NULL_RTX
+               && 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;
+         }
       }
 
   /* Record the values of the earlyclobber operands for the caller.  */
@@ -4196,7 +4233,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   /* If we detected error and replaced asm instruction by USE, forget about the
      reloads.  */
   if (GET_CODE (PATTERN (insn)) == USE
-      && GET_CODE (XEXP (PATTERN (insn), 0)) == CONST_INT)
+      && CONST_INT_P (XEXP (PATTERN (insn), 0)))
     n_reloads = 0;
 
   /* Perhaps an output reload can be combined with another
@@ -4523,7 +4560,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
    is null.  */
 
 static bool
-alternative_allows_const_pool_ref (rtx mem, const char *constraint, int altnum)
+alternative_allows_const_pool_ref (rtx mem ATTRIBUTE_UNUSED,
+                                  const char *constraint, int altnum)
 {
   int c;
 
@@ -4733,7 +4771,8 @@ make_memloc (rtx ad, int regno)
   /* We must rerun eliminate_regs, in case the elimination
      offsets have changed.  */
   rtx tem
-    = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0, NULL_RTX), 0);
+    = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], VOIDmode, NULL_RTX),
+           0);
 
   /* If TEM might contain a pseudo, we must copy it to avoid
      modifying it when we do the substitution for the reload.  */
@@ -4896,7 +4935,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
+         && CONST_INT_P (XEXP (ad, 1))
          && REG_P (XEXP (ad, 0))
          && reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0)
        return 0;
@@ -4976,7 +5015,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
          || ! (REG_P (XEXP (tem, 0))
                || (GET_CODE (XEXP (tem, 0)) == PLUS
                    && REG_P (XEXP (XEXP (tem, 0), 0))
-                   && GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT)))
+                   && CONST_INT_P (XEXP (XEXP (tem, 0), 1)))))
        {
          /* Must use TEM here, not AD, since it is the one that will
             have any subexpressions reloaded, if needed.  */
@@ -4998,7 +5037,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
   else if (GET_CODE (ad) == PLUS
           && REG_P (XEXP (ad, 0))
           && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
-          && GET_CODE (XEXP (ad, 1)) == CONST_INT
+          && CONST_INT_P (XEXP (ad, 1))
           && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
                                   CONST_INT))
 
@@ -5072,7 +5111,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 
       inner_code = GET_CODE (XEXP (ad, 0));
       if (!(GET_CODE (ad) == PLUS 
-           && GET_CODE (XEXP (ad, 1)) == CONST_INT
+           && CONST_INT_P (XEXP (ad, 1))
            && (inner_code == PLUS || inner_code == LO_SUM)))
        continue;
 
@@ -5228,7 +5267,7 @@ subst_reg_equivs (rtx ad, rtx insn)
     case PLUS:
       /* Quickly dispose of a common case.  */
       if (XEXP (ad, 0) == frame_pointer_rtx
-         && GET_CODE (XEXP (ad, 1)) == CONST_INT)
+         && CONST_INT_P (XEXP (ad, 1)))
        return ad;
       break;
 
@@ -5262,9 +5301,9 @@ form_sum (rtx x, rtx y)
   if (mode == VOIDmode)
     mode = Pmode;
 
-  if (GET_CODE (x) == CONST_INT)
+  if (CONST_INT_P (x))
     return plus_constant (y, INTVAL (x));
-  else if (GET_CODE (y) == CONST_INT)
+  else if (CONST_INT_P (y))
     return plus_constant (x, INTVAL (y));
   else if (CONSTANT_P (x))
     tem = x, x = y, y = tem;
@@ -6073,7 +6112,7 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
                  base = XEXP (tem, 0);
                  if (GET_CODE (base) == PLUS)
                    {
-                     if (GET_CODE (XEXP (base, 1)) == CONST_INT
+                     if (CONST_INT_P (XEXP (base, 1))
                          && INTVAL (XEXP (base, 1)) % outer_size != 0)
                        return x;
                      base = XEXP (base, 0);
@@ -6094,18 +6133,26 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
              /* For some processors an address may be valid in the
                 original mode but not in a smaller mode.  For
                 example, ARM accepts a scaled index register in
-                SImode but not in HImode.  Similarly, the address may
-                have been valid before the subreg offset was added,
-                but not afterwards.  find_reloads_address
-                assumes that we pass it a valid address, and doesn't
-                force a reload.  This will probably be fine if
-                find_reloads_address finds some reloads.  But if it
-                doesn't find any, then we may have just converted a
-                valid address into an invalid one.  Check for that
-                here.  */
-             if (reloaded != 1
-                 && !strict_memory_address_p (GET_MODE (tem),
-                                              XEXP (tem, 0)))
+                SImode but not in HImode.  Note that this is only
+                a problem if the address in reg_equiv_mem is already
+                invalid in the new mode; other cases would be fixed
+                by find_reloads_address as usual.
+
+                ??? We attempt to handle such cases here by doing an
+                additional reload of the full address after the
+                usual processing by find_reloads_address.  Note that
+                this may not work in the general case, but it seems
+                to cover the cases where this situation currently
+                occurs.  A more general fix might be to reload the
+                *value* instead of the address, but this would not
+                be expected by the callers of this routine as-is.
+
+                If find_reloads_address already completed replaced
+                the address, there is nothing further to do.  */
+             if (reloaded == 0
+                 && reg_equiv_mem[regno] != 0
+                 && !strict_memory_address_p (GET_MODE (x),
+                                              XEXP (reg_equiv_mem[regno], 0)))
                push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
                             base_reg_class (GET_MODE (tem), MEM, SCRATCH),
                             GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
@@ -6509,7 +6556,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
   /* If either argument is a constant, then modifying X can not affect IN.  */
   if (CONSTANT_P (x) || CONSTANT_P (in))
     return 0;
-  else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
+  else if (GET_CODE (x) == SUBREG && MEM_P (SUBREG_REG (x)))
     return refers_to_mem_for_reload_p (in);
   else if (GET_CODE (x) == SUBREG)
     {
@@ -6743,7 +6790,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other,
                          || (REG_P (SET_DEST (pat))
                              && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
                              && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
-                             && GET_CODE (goal) == CONST_INT
+                             && CONST_INT_P (goal)
                              && 0 != (goaltry
                                       = operand_subword (XEXP (tem, 0), 0, 0,
                                                          VOIDmode))
@@ -6757,7 +6804,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other,
                      && REG_P (SET_DEST (pat))
                      && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
                      && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
-                     && GET_CODE (goal) == CONST_INT
+                     && CONST_INT_P (goal)
                      && 0 != (goaltry = operand_subword (XEXP (tem, 0), 1, 0,
                                                          VOIDmode))
                      && rtx_equal_p (goal, goaltry)
@@ -7085,7 +7132,7 @@ find_inc_amount (rtx x, rtx inced)
               && GET_CODE (XEXP (addr, 1)) == PLUS
               && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
               && XEXP (addr, 0) == inced
-              && GET_CODE (XEXP (XEXP (addr, 1), 1)) == CONST_INT)
+              && CONST_INT_P (XEXP (XEXP (addr, 1), 1)))
        {
          i = INTVAL (XEXP (XEXP (addr, 1), 1));
          return i < 0 ? -i : i;