OSDN Git Service

Fix mips64vr4100-elf build failure.
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index f1674f7..1604a7b 100644 (file)
@@ -1,5 +1,5 @@
 /* Search an insn for pseudo regs that must be in hard regs and are not.
-   Copyright (C) 1987, 88, 89, 92-6, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -87,8 +87,8 @@ a register with any other reload.  */
 
 #define REG_OK_STRICT
 
-#include <stdio.h>
 #include "config.h"
+#include "system.h"
 #include "rtl.h"
 #include "insn-config.h"
 #include "insn-codes.h"
@@ -99,10 +99,20 @@ a register with any other reload.  */
 #include "flags.h"
 #include "real.h"
 #include "output.h"
+#include "expr.h"
+#include "toplev.h"
 
 #ifndef REGISTER_MOVE_COST
 #define REGISTER_MOVE_COST(x, y) 2
 #endif
+
+#ifndef REGNO_MODE_OK_FOR_BASE_P
+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) REGNO_OK_FOR_BASE_P (REGNO)
+#endif
+
+#ifndef REG_MODE_OK_FOR_BASE_P
+#define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO)
+#endif
 \f
 /* The variables set up by `find_reloads' are:
 
@@ -119,6 +129,8 @@ a register with any other reload.  */
    reload_optional       char, nonzero for an optional reload.
                           Optional reloads are ignored unless the
                           value is already sitting in a register.
+   reload_nongroup       char, nonzero when a reload must use a register
+                          not already allocated to a group.
    reload_inc            int, positive amount to increment or decrement by if
                           reload_in is a PRE_DEC, PRE_INC, POST_DEC, POST_INC.
                           Ignored otherwise (don't assume it is zero).
@@ -166,6 +178,7 @@ enum machine_mode reload_inmode[MAX_RELOADS];
 enum machine_mode reload_outmode[MAX_RELOADS];
 rtx reload_reg_rtx[MAX_RELOADS];
 char reload_optional[MAX_RELOADS];
+char reload_nongroup[MAX_RELOADS];
 int reload_inc[MAX_RELOADS];
 rtx reload_in_reg[MAX_RELOADS];
 char reload_nocombine[MAX_RELOADS];
@@ -251,7 +264,7 @@ static int this_insn_is_asm;
 static int hard_regs_live_known;
 
 /* Indexed by hard reg number,
-   element is nonegative if hard reg has been spilled.
+   element is nonnegative if hard reg has been spilled.
    This vector is passed to `find_reloads' as an argument
    and is not changed here.  */
 static short *static_reload_reg_p;
@@ -288,9 +301,20 @@ static int output_reloadnum;
         || (when1) == RELOAD_FOR_OPERAND_ADDRESS       \
         || (when1) == RELOAD_FOR_OTHER_ADDRESS))
 
+  /* If we are going to reload an address, compute the reload type to
+     use.  */
+#define ADDR_TYPE(type)                                        \
+  ((type) == RELOAD_FOR_INPUT_ADDRESS                  \
+   ? RELOAD_FOR_INPADDR_ADDRESS                                \
+   : ((type) == RELOAD_FOR_OUTPUT_ADDRESS              \
+      ? RELOAD_FOR_OUTADDR_ADDRESS                     \
+      : (type)))
+
+#ifdef HAVE_SECONDARY_RELOADS
 static int push_secondary_reload PROTO((int, rtx, int, int, enum reg_class,
                                        enum machine_mode, enum reload_type,
                                        enum insn_code *));
+#endif
 static enum reg_class find_valid_class PROTO((enum machine_mode, int));
 static int push_reload         PROTO((rtx, rtx, rtx *, rtx *, enum reg_class,
                                       enum machine_mode, enum machine_mode,
@@ -299,7 +323,7 @@ static void push_replacement        PROTO((rtx *, int, enum machine_mode));
 static void combine_reloads    PROTO((void));
 static rtx find_dummy_reload   PROTO((rtx, rtx, rtx *, rtx *,
                                       enum machine_mode, enum machine_mode,
-                                      enum reg_class, int));
+                                      enum reg_class, int, int));
 static int earlyclobber_operand_p PROTO((rtx));
 static int hard_reg_set_here_p PROTO((int, int, rtx));
 static struct decomposition decompose PROTO((rtx));
@@ -308,11 +332,11 @@ static int alternative_allows_memconst PROTO((char *, int));
 static rtx find_reloads_toplev PROTO((rtx, int, enum reload_type, int, int));
 static rtx make_memloc         PROTO((rtx, int));
 static int find_reloads_address        PROTO((enum machine_mode, rtx *, rtx, rtx *,
-                                      int, enum reload_type, int));
+                                      int, enum reload_type, int, rtx));
 static rtx subst_reg_equivs    PROTO((rtx));
 static rtx subst_indexed_address PROTO((rtx));
-static int find_reloads_address_1 PROTO((rtx, int, rtx *, int,
-                                        enum reload_type,int));
+static int find_reloads_address_1 PROTO((enum machine_mode, rtx, int, rtx *,
+                                        int, enum reload_type,int, rtx));
 static void find_reloads_address_part PROTO((rtx, rtx *, enum reg_class,
                                             enum machine_mode, int,
                                             enum reload_type, int));
@@ -348,10 +372,12 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
   enum machine_mode t_mode = VOIDmode;
   enum insn_code t_icode = CODE_FOR_nothing;
   enum reload_type secondary_type;
-  int i;
   int s_reload, t_reload = -1;
 
-  if (type == RELOAD_FOR_INPUT_ADDRESS || type == RELOAD_FOR_OUTPUT_ADDRESS)
+  if (type == RELOAD_FOR_INPUT_ADDRESS
+      || type == RELOAD_FOR_OUTPUT_ADDRESS
+      || type == RELOAD_FOR_INPADDR_ADDRESS
+      || type == RELOAD_FOR_OUTADDR_ADDRESS)
     secondary_type = type;
   else
     secondary_type = in_p ? RELOAD_FOR_INPUT_ADDRESS : RELOAD_FOR_OUTPUT_ADDRESS;
@@ -475,11 +501,7 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
                          == CODE_FOR_nothing))
                || (! in_p &&(reload_secondary_out_icode[t_reload]
                              == CODE_FOR_nothing)))
-           && (reg_class_size[(int) t_class] == 1
-#ifdef SMALL_REGISTER_CLASSES
-               || SMALL_REGISTER_CLASSES
-#endif
-               )
+           && (reg_class_size[(int) t_class] == 1 || SMALL_REGISTER_CLASSES)
            && MERGABLE_RELOADS (secondary_type,
                                 reload_when_needed[t_reload],
                                 opnum, reload_opnum[t_reload]))
@@ -509,6 +531,7 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
          reload_outmode[t_reload] = ! in_p ? t_mode : VOIDmode;
          reload_reg_rtx[t_reload] = 0;
          reload_optional[t_reload] = optional;
+         reload_nongroup[t_reload] = 0;
          reload_inc[t_reload] = 0;
          /* Maybe we could combine these, but it seems too tricky.  */
          reload_nocombine[t_reload] = 1;
@@ -536,11 +559,7 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
            || (! in_p && reload_secondary_out_reload[s_reload] == t_reload))
        && ((in_p && reload_secondary_in_icode[s_reload] == t_icode)
            || (! in_p && reload_secondary_out_icode[s_reload] == t_icode))
-       && (reg_class_size[(int) class] == 1
-#ifdef SMALL_REGISTER_CLASSES
-           || SMALL_REGISTER_CLASSES
-#endif
-           )
+       && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
        && MERGABLE_RELOADS (secondary_type, reload_when_needed[s_reload],
                             opnum, reload_opnum[s_reload]))
       {
@@ -562,6 +581,17 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
 
   if (s_reload == n_reloads)
     {
+#ifdef SECONDARY_MEMORY_NEEDED
+      /* If we need a memory location to copy between the two reload regs,
+        set it up now.  Note that we do the input case before making
+        the reload and the output case after.  This is due to the 
+        way reloads are output.  */
+
+      if (in_p && icode == CODE_FOR_nothing
+         && SECONDARY_MEMORY_NEEDED (class, reload_class, mode))
+       get_secondary_mem (x, reload_mode, opnum, type);
+#endif
+
       /* We need to make a new secondary reload for this register class.  */
       reload_in[s_reload] = reload_out[s_reload] = 0;
       reload_reg_class[s_reload] = class;
@@ -570,6 +600,7 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
       reload_outmode[s_reload] = ! in_p ? mode : VOIDmode;
       reload_reg_rtx[s_reload] = 0;
       reload_optional[s_reload] = optional;
+      reload_nongroup[s_reload] = 0;
       reload_inc[s_reload] = 0;
       /* Maybe we could combine these, but it seems too tricky.  */
       reload_nocombine[s_reload] = 1;
@@ -586,13 +617,6 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
       n_reloads++;
 
 #ifdef SECONDARY_MEMORY_NEEDED
-      /* If we need a memory location to copy between the two reload regs,
-        set it up now.  */
-
-      if (in_p && icode == CODE_FOR_nothing
-         && SECONDARY_MEMORY_NEEDED (class, reload_class, mode))
-       get_secondary_mem (x, mode, opnum, type);
-
       if (! in_p && icode == CODE_FOR_nothing
          && SECONDARY_MEMORY_NEEDED (reload_class, class, mode))
        get_secondary_mem (x, mode, opnum, type);
@@ -673,7 +697,7 @@ get_secondary_mem (x, mode, opnum, type)
               : RELOAD_OTHER);
 
       find_reloads_address (mode, NULL_PTR, XEXP (loc, 0), &XEXP (loc, 0),
-                           opnum, type, 0);
+                           opnum, type, 0, 0);
     }
 
   secondary_memlocs_elim[(int) mode][opnum] = loc;
@@ -813,10 +837,10 @@ push_reload (in, out, inloc, outloc, class,
     {
       if (GET_CODE (XEXP (in, 0)) == POST_INC
          || GET_CODE (XEXP (in, 0)) == POST_DEC)
-       in = gen_rtx (MEM, GET_MODE (in), XEXP (XEXP (in, 0), 0));
+       in = gen_rtx_MEM (GET_MODE (in), XEXP (XEXP (in, 0), 0));
       if (GET_CODE (XEXP (in, 0)) == PRE_INC
          || GET_CODE (XEXP (in, 0)) == PRE_DEC)
-       out = gen_rtx (MEM, GET_MODE (out), XEXP (XEXP (out, 0), 0));
+       out = gen_rtx_MEM (GET_MODE (out), XEXP (XEXP (out, 0), 0));
     }
 
   /* If we are reloading a (SUBREG constant ...), really reload just the
@@ -869,6 +893,13 @@ push_reload (in, out, inloc, outloc, class,
                      && INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))
                      && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != NIL)
 #endif
+#ifdef WORD_REGISTER_OPERATIONS
+                 || ((GET_MODE_SIZE (inmode)
+                      < GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
+                     && ((GET_MODE_SIZE (inmode) - 1) / UNITS_PER_WORD ==
+                         ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) - 1)
+                          / UNITS_PER_WORD)))
+#endif
                  ))
          || (GET_CODE (SUBREG_REG (in)) == REG
              && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
@@ -906,7 +937,7 @@ push_reload (in, out, inloc, outloc, class,
       in_subreg_loc = inloc;
       inloc = &SUBREG_REG (in);
       in = *inloc;
-#ifndef LOAD_EXTEND_OP
+#if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
       if (GET_CODE (in) == MEM)
        /* This is supposed to happen only for paradoxical subregs made by
           combine.c.  (SUBREG (MEM)) isn't supposed to occur other ways.  */
@@ -968,7 +999,15 @@ push_reload (in, out, inloc, outloc, class,
                && REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER)
               || GET_CODE (SUBREG_REG (out)) == MEM)
              && ((GET_MODE_SIZE (outmode)
-                  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))))
+                  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
+#ifdef WORD_REGISTER_OPERATIONS
+                 || ((GET_MODE_SIZE (outmode)
+                      < GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
+                     && ((GET_MODE_SIZE (outmode) - 1) / UNITS_PER_WORD ==
+                         ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - 1)
+                          / UNITS_PER_WORD)))
+#endif
+                 ))
          || (GET_CODE (SUBREG_REG (out)) == REG
              && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
              && ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
@@ -1002,7 +1041,7 @@ push_reload (in, out, inloc, outloc, class,
       out_subreg_loc = outloc;
       outloc = &SUBREG_REG (out);
       out = *outloc; 
-#ifndef LOAD_EXTEND_OP
+#if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
      if (GET_CODE (out) == MEM
          && GET_MODE_SIZE (GET_MODE (out)) > GET_MODE_SIZE (outmode))
        abort ();
@@ -1055,16 +1094,16 @@ push_reload (in, out, inloc, outloc, class,
   if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG
       && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
       && ! dont_remove_subreg)
-    in = gen_rtx (REG, GET_MODE (in),
-                 REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
+    in = gen_rtx_REG (GET_MODE (in),
+                     REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
 
   /* Similarly for OUT.  */
   if (out != 0 && GET_CODE (out) == SUBREG
       && GET_CODE (SUBREG_REG (out)) == REG
       && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
       && ! dont_remove_subreg)
-    out = gen_rtx (REG, GET_MODE (out),
-                 REGNO (SUBREG_REG (out)) + SUBREG_WORD (out));
+    out = gen_rtx_REG (GET_MODE (out),
+                      REGNO (SUBREG_REG (out)) + SUBREG_WORD (out));
 
   /* Narrow down the class of register wanted if that is
      desirable on this machine for efficiency.  */
@@ -1155,11 +1194,7 @@ push_reload (in, out, inloc, outloc, class,
            ||
            (out != 0 && MATCHES (reload_out[i], out)
             && (in == 0 || reload_in[i] == 0 || MATCHES (reload_in[i], in))))
-       && (reg_class_size[(int) class] == 1
-#ifdef SMALL_REGISTER_CLASSES
-           || SMALL_REGISTER_CLASSES
-#endif
-           )
+       && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
        && MERGABLE_RELOADS (type, reload_when_needed[i],
                             opnum, reload_opnum[i]))
       break;
@@ -1191,11 +1226,7 @@ push_reload (in, out, inloc, outloc, class,
                   || GET_CODE (in) == PRE_INC
                   || GET_CODE (in) == PRE_DEC)
               && MATCHES (XEXP (in, 0), reload_in[i])))
-         && (reg_class_size[(int) class] == 1
-#ifdef SMALL_REGISTER_CLASSES
-             || SMALL_REGISTER_CLASSES
-#endif
-             )
+         && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
          && MERGABLE_RELOADS (type, reload_when_needed[i],
                               opnum, reload_opnum[i]))
        {
@@ -1229,6 +1260,15 @@ push_reload (in, out, inloc, outloc, class,
       /* We found no existing reload suitable for re-use.
         So add an additional reload.  */
 
+#ifdef SECONDARY_MEMORY_NEEDED
+      /* If a memory location is needed for the copy, make one.  */
+      if (in != 0 && GET_CODE (in) == REG
+         && REGNO (in) < FIRST_PSEUDO_REGISTER
+         && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
+                                    class, inmode))
+       get_secondary_mem (in, inmode, opnum, type);
+#endif
+
       i = n_reloads;
       reload_in[i] = in;
       reload_out[i] = out;
@@ -1237,6 +1277,7 @@ push_reload (in, out, inloc, outloc, class,
       reload_outmode[i] = outmode;
       reload_reg_rtx[i] = 0;
       reload_optional[i] = optional;
+      reload_nongroup[i] = 0;
       reload_inc[i] = 0;
       reload_nocombine[i] = 0;
       reload_in_reg[i] = inloc ? *inloc : 0;
@@ -1251,13 +1292,6 @@ push_reload (in, out, inloc, outloc, class,
       n_reloads++;
 
 #ifdef SECONDARY_MEMORY_NEEDED
-      /* If a memory location is needed for the copy, make one.  */
-      if (in != 0 && GET_CODE (in) == REG
-         && REGNO (in) < FIRST_PSEUDO_REGISTER
-         && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
-                                    class, inmode))
-       get_secondary_mem (in, inmode, opnum, type);
-
       if (out != 0 && GET_CODE (out) == REG
          && REGNO (out) < FIRST_PSEUDO_REGISTER
          && SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (REGNO (out)),
@@ -1358,7 +1392,8 @@ push_reload (in, out, inloc, outloc, class,
     {
       reload_reg_rtx[i] = find_dummy_reload (in, out, inloc, outloc,
                                             inmode, outmode,
-                                            reload_reg_class[i], i);
+                                            reload_reg_class[i], i,
+                                            earlyclobber_operand_p (out));
 
       /* If the outgoing register already contains the same value
         as the incoming one, we can dispense with loading it.
@@ -1424,7 +1459,7 @@ push_reload (in, out, inloc, outloc, class,
            && TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno)
            && !fixed_regs[regno])
          {
-           reload_reg_rtx[i] = gen_rtx (REG, inmode, regno);
+           reload_reg_rtx[i] = gen_rtx_REG (inmode, regno);
            break;
          }
     }
@@ -1471,6 +1506,21 @@ transfer_replacements (to, from)
       replacements[i].what = to;
 }
 \f
+/* Remove all replacements in reload FROM.  */
+void
+remove_replacements (from)
+     int from;
+{
+  int i, j;
+
+  for (i = 0, j = 0; i < n_replacements; i++)
+    {
+      if (replacements[i].what == from)
+        continue;
+      replacements[j++] = replacements[i];
+    }
+}
+\f
 /* If there is only one output reload, and it is not for an earlyclobber
    operand, try to combine it with a (logically unrelated) input reload
    to reduce the number of reload registers needed.
@@ -1520,6 +1570,7 @@ combine_reloads ()
     if (reload_in[i] && ! reload_optional[i] && ! reload_nocombine[i]
        /* Life span of this reload must not extend past main insn.  */
        && reload_when_needed[i] != RELOAD_FOR_OUTPUT_ADDRESS
+       && reload_when_needed[i] != RELOAD_FOR_OUTADDR_ADDRESS
        && reload_when_needed[i] != RELOAD_OTHER
        && (CLASS_MAX_NREGS (reload_reg_class[i], reload_inmode[i])
            == CLASS_MAX_NREGS (reload_reg_class[output_reload],
@@ -1534,17 +1585,12 @@ combine_reloads ()
            || rtx_equal_p (secondary_memlocs_elim[(int) reload_outmode[output_reload]][reload_opnum[i]],
                            secondary_memlocs_elim[(int) reload_outmode[output_reload]][reload_opnum[output_reload]]))
 #endif
-       && (
-#ifdef SMALL_REGISTER_CLASSES
-           SMALL_REGISTER_CLASSES
-#else
-           0
-#endif
-             ? reload_reg_class[i] == reload_reg_class[output_reload]
-             : (reg_class_subset_p (reload_reg_class[i],
-                                    reload_reg_class[output_reload])
-                || reg_class_subset_p (reload_reg_class[output_reload],
-                                       reload_reg_class[i])))
+       && (SMALL_REGISTER_CLASSES
+           ? (reload_reg_class[i] == reload_reg_class[output_reload])
+           : (reg_class_subset_p (reload_reg_class[i],
+                                  reload_reg_class[output_reload])
+              || reg_class_subset_p (reload_reg_class[output_reload],
+                                     reload_reg_class[i])))
        && (MATCHES (reload_in[i], reload_out[output_reload])
            /* Args reversed because the first arg seems to be
               the one that we imagine being modified
@@ -1561,10 +1607,7 @@ combine_reloads ()
                      && reg_overlap_mentioned_for_reload_p (reload_in[i],
                                                             reload_out[output_reload]))))
        && (reg_class_size[(int) reload_reg_class[i]]
-#ifdef SMALL_REGISTER_CLASSES
-            || SMALL_REGISTER_CLASSES
-#endif
-           )
+           || SMALL_REGISTER_CLASSES)
        /* We will allow making things slightly worse by combining an
           input and an output, but no worse than that.  */
        && (reload_when_needed[i] == RELOAD_FOR_INPUT
@@ -1647,9 +1690,9 @@ combine_reloads ()
                            REGNO (XEXP (note, 0)))))))
        && ! fixed_regs[REGNO (XEXP (note, 0))])
       {
-       reload_reg_rtx[output_reload] = gen_rtx (REG,
-                                                reload_outmode[output_reload],
-                                                REGNO (XEXP (note, 0)));
+       reload_reg_rtx[output_reload]
+         = gen_rtx_REG (reload_outmode[output_reload],
+                        REGNO (XEXP (note, 0)));
        return;
       }
 }
@@ -1667,16 +1710,22 @@ combine_reloads ()
    to be computed, clear out reload_out[FOR_REAL].
 
    If FOR_REAL is -1, this should not be done, because this call
-   is just to see if a register can be found, not to find and install it.  */
+   is just to see if a register can be found, not to find and install it.
+
+   EARLYCLOBBER is non-zero if OUT is an earlyclobber operand.  This
+   puts an additional constraint on being able to use IN for OUT since
+   IN must not appear elsewhere in the insn (it is assumed that IN itself
+   is safe from the earlyclobber).  */
 
 static rtx
 find_dummy_reload (real_in, real_out, inloc, outloc,
-                  inmode, outmode, class, for_real)
+                  inmode, outmode, class, for_real, earlyclobber)
      rtx real_in, real_out;
      rtx *inloc, *outloc;
      enum machine_mode inmode, outmode;
      enum reg_class class;
      int for_real;
+     int earlyclobber;
 {
   rtx in = real_in;
   rtx out = real_out;
@@ -1747,7 +1796,7 @@ find_dummy_reload (real_in, real_out, inloc, outloc,
              if (GET_CODE (real_out) == REG)
                value = real_out;
              else
-               value = gen_rtx (REG, outmode, regno);
+               value = gen_rtx_REG (outmode, regno);
            }
        }
 
@@ -1758,7 +1807,8 @@ find_dummy_reload (real_in, real_out, inloc, outloc,
      or if OUT dies in this insn (like the quotient in a divmod insn).
      We can't use IN unless it is dies in this insn,
      which means we must know accurately which hard regs are live.
-     Also, the result can't go in IN if IN is used within OUT.  */
+     Also, the result can't go in IN if IN is used within OUT,
+     or if OUT is an earlyclobber and IN appears elsewhere in the insn.  */
   if (hard_regs_live_known
       && GET_CODE (in) == REG
       && REGNO (in) < FIRST_PSEUDO_REGISTER
@@ -1779,7 +1829,10 @@ find_dummy_reload (real_in, real_out, inloc, outloc,
 
       if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, NULL_PTR)
          && ! hard_reg_set_here_p (regno, regno + nwords,
-                                   PATTERN (this_insn)))
+                                   PATTERN (this_insn))
+         && (! earlyclobber
+             || ! refers_to_regno_for_reload_p (regno, regno + nwords,
+                                                PATTERN (this_insn), inloc)))
        {
          int i;
          for (i = 0; i < nwords; i++)
@@ -1797,7 +1850,7 @@ find_dummy_reload (real_in, real_out, inloc, outloc,
              if (GET_CODE (real_in) == REG)
                value = real_in;
              else
-               value = gen_rtx (REG, inmode, regno);
+               value = gen_rtx_REG (inmode, regno);
            }
        }
     }
@@ -2044,6 +2097,7 @@ decompose (x)
 
   val.reg_flag = 0;
   val.safe = 0;
+  val.base = 0;
   if (GET_CODE (x) == MEM)
     {
       rtx base, offset = 0;
@@ -2089,28 +2143,28 @@ decompose (x)
        {
          if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
            {
-             base = gen_rtx (PLUS, GET_MODE (base), base, XEXP (offset, 1));
+             base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
              offset = XEXP (offset, 0);
            }
          else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
            {
-             base = gen_rtx (PLUS, GET_MODE (base), base, XEXP (offset, 0));
+             base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
              offset = XEXP (offset, 1);
            }
          else
            {
-             base = gen_rtx (PLUS, GET_MODE (base), base, offset);
+             base = gen_rtx_PLUS (GET_MODE (base), base, offset);
              offset = const0_rtx;
            }
        }
       else if (GET_CODE (offset) != CONST_INT)
        {
-         base = gen_rtx (PLUS, GET_MODE (base), base, offset);
+         base = gen_rtx_PLUS (GET_MODE (base), base, offset);
          offset = const0_rtx;
        }
 
       if (all_const && GET_CODE (base) == PLUS)
-       base = gen_rtx (CONST, GET_MODE (base), base);
+       base = gen_rtx_CONST (GET_MODE (base), base);
 
       if (GET_CODE (offset) != CONST_INT)
        abort ();
@@ -2283,6 +2337,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
   int goal_alternative_swapped;
   int best;
   int commutative;
+  int changed;
   char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS];
   rtx substed_operand[MAX_RECOG_OPERANDS];
   rtx body = PATTERN (insn);
@@ -2376,7 +2431,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                  {
                    error_for_asm (insn, "operand constraints differ in number of alternatives");
                    /* Avoid further trouble with this insn.  */
-                   PATTERN (insn) = gen_rtx (USE, VOIDmode, const0_rtx);
+                   PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
                    n_reloads = 0;
                    return;
                  }
@@ -2429,7 +2484,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
       /* Scan this operand's constraint to see if it is an output operand, 
         an in-out operand, is commutative, or should match another.  */
 
-      while (c = *p++)
+      while ((c = *p++))
        {
          if (c == '=')
            modified[i] = RELOAD_WRITE;
@@ -2517,7 +2572,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        {
          find_reloads_address (VOIDmode, NULL_PTR,
                                recog_operand[i], recog_operand_loc[i],
-                               i, operand_type[i], ind_levels);
+                               i, operand_type[i], ind_levels, insn);
 
          /* If we now have a simple operand where we used to have a 
             PLUS or MULT, re-recognize and try again.  */
@@ -2540,16 +2595,34 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                                    recog_operand_loc[i],
                                    XEXP (recog_operand[i], 0),
                                    &XEXP (recog_operand[i], 0),
-                                   i, address_type[i], ind_levels))
+                                   i, address_type[i], ind_levels, insn))
            address_reloaded[i] = 1;
          substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
        }
       else if (code == SUBREG)
-       substed_operand[i] = recog_operand[i] = *recog_operand_loc[i]
-         = find_reloads_toplev (recog_operand[i], i, address_type[i],
-                                ind_levels,
-                                set != 0
-                                && &SET_DEST (set) == recog_operand_loc[i]);
+       {
+         rtx reg = SUBREG_REG (recog_operand[i]);
+         rtx op
+           = find_reloads_toplev (recog_operand[i], i, address_type[i],
+                                  ind_levels,
+                                  set != 0
+                                  && &SET_DEST (set) == recog_operand_loc[i]);
+
+         /* If we made a MEM to load (a part of) the stackslot of a pseudo
+            that didn't get a hard register, emit a USE with a REG_EQUAL
+            note in front so that we might inherit a previous, possibly
+            wider reload.  */
+            
+         if (GET_CODE (op) == MEM
+             && GET_CODE (reg) == REG
+             && (GET_MODE_SIZE (GET_MODE (reg))
+                 >= GET_MODE_SIZE (GET_MODE (op))))
+            REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode, reg), insn))
+              = gen_rtx_EXPR_LIST (REG_EQUAL,
+                                  reg_equiv_memory_loc[REGNO (reg)], NULL_RTX);
+
+         substed_operand[i] = recog_operand[i] = *recog_operand_loc[i] = op;
+       }
       else if (code == PLUS || GET_RTX_CLASS (code) == '1')
        /* We can get a PLUS as an "operand" as a result of register
           elimination.  See eliminate_regs and gen_reload.  We handle
@@ -2568,8 +2641,16 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
          register int regno = REGNO (recog_operand[i]);
          if (reg_equiv_constant[regno] != 0
              && (set == 0 || &SET_DEST (set) != recog_operand_loc[i]))
-           substed_operand[i] = recog_operand[i]
-             = reg_equiv_constant[regno];
+           {
+             /* Record the existing mode so that the check if constants are
+                allowed will work when operand_mode isn't specified. */
+
+             if (operand_mode[i] == VOIDmode)
+               operand_mode[i] = GET_MODE (recog_operand[i]);
+
+             substed_operand[i] = recog_operand[i]
+               = reg_equiv_constant[regno];
+           }
 #if 0 /* This might screw code in reload1.c to delete prior output-reload
         that feeds this insn.  */
          if (reg_equiv_mem[regno] != 0)
@@ -2589,26 +2670,23 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              if (rtx_varies_p (address))
                address = copy_rtx (address);
 
-             /* If this is an output operand, we must output a CLOBBER
-                after INSN so find_equiv_reg knows REGNO is being written. 
-                Mark this insn specially, do we can put our output reloads
-                after it.  */
-
-             if (modified[i] != RELOAD_READ)
-               PUT_MODE (emit_insn_after (gen_rtx (CLOBBER, VOIDmode,
-                                                   recog_operand[i]),
-                                          insn),
-                         DImode);
+             /* Emit a USE that shows what register is being used/modified.  */
+             REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode,
+                                                       recog_operand[i]),
+                                          insn))
+               = gen_rtx_EXPR_LIST (REG_EQUAL,
+                                    reg_equiv_memory_loc[regno],
+                                    NULL_RTX);
 
              *recog_operand_loc[i] = recog_operand[i]
-               = gen_rtx (MEM, GET_MODE (recog_operand[i]), address);
+               = gen_rtx_MEM (GET_MODE (recog_operand[i]), address);
              RTX_UNCHANGING_P (recog_operand[i])
                = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
              find_reloads_address (GET_MODE (recog_operand[i]),
                                    recog_operand_loc[i],
                                    XEXP (recog_operand[i], 0),
                                    &XEXP (recog_operand[i], 0),
-                                   i, address_type[i], ind_levels);
+                                   i, address_type[i], ind_levels, insn);
              substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
            }
        }
@@ -2638,7 +2716,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
      or got the wrong kind of hard reg.  For this, we must consider
      all the operands together against the register constraints.  */
 
-  best = MAX_RECOG_OPERANDS + 300;
+  best = MAX_RECOG_OPERANDS * 2 + 600;
 
   swapped = 0;
   goal_alternative_swapped = 0;
@@ -2693,8 +2771,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
          int earlyclobber = 0;
 
          /* If the predicate accepts a unary operator, it means that
-             we need to reload the operand.  */
-         if (GET_RTX_CLASS (GET_CODE (operand)) == '1')
+             we need to reload the operand, but do not do this for
+            match_operator and friends.  */
+         if (GET_RTX_CLASS (GET_CODE (operand)) == '1' && *p != 0)
            operand = XEXP (operand, 0);
 
          /* If the operand is a SUBREG, extract
@@ -2705,7 +2784,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
            {
              offset += SUBREG_WORD (operand);
              operand = SUBREG_REG (operand);
-             /* Force reload if this is a constant or PLUS or if there may may
+             /* Force reload if this is a constant or PLUS or if there may
                 be a problem accessing OPERAND in the outer mode.  */
              if (CONSTANT_P (operand)
                  || GET_CODE (operand) == PLUS
@@ -2723,10 +2802,20 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                     register access.  If the data is, in fact, in memory we
                     must always load using the size assumed to be in the
                     register and let the insn do the different-sized 
-                    accesses.  */
+                    accesses.
+
+                    This is doubly true if WORD_REGISTER_OPERATIONS.  In 
+                    this case eliminate_regs has left non-paradoxical
+                    subregs for push_reloads to see.  Make sure it does
+                    by forcing the reload.
+
+                    ??? When is it right at this stage to have a subreg
+                    of a mem that is _not_ to be handled specialy?  IMO
+                    those should have been reduced to just a mem.  */
                  || ((GET_CODE (operand) == MEM
                       || (GET_CODE (operand)== REG
                           && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
+#ifndef WORD_REGISTER_OPERATIONS
                      && (((GET_MODE_BITSIZE (GET_MODE (operand))
                            < BIGGEST_ALIGNMENT)
                           && (GET_MODE_SIZE (operand_mode[i])
@@ -2741,7 +2830,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                              && INTEGRAL_MODE_P (GET_MODE (operand))
                              && LOAD_EXTEND_OP (GET_MODE (operand)) != NIL)
 #endif
-                         ))
+                         )
+#endif
+                     )
                  /* Subreg of a hard reg which can't handle the subreg's mode
                     or which would handle that mode in the wrong number of
                     registers for subregging to work.  */
@@ -2792,11 +2883,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                break;
 
              case '?':
-               reject += 3;
+               reject += 6;
                break;
 
              case '!':
-               reject = 300;
+               reject = 600;
                break;
 
              case '#':
@@ -2832,7 +2923,18 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                        [(i == commutative || i == commutative + 1)
                         ? 2*commutative + 1 - i : i])
                    : operands_match[c][i])
-                 win = this_alternative_win[c];
+                 {
+                   /* If we are matching a non-offsettable address where an
+                      offsettable address was expected, then we must reject
+                      this combination, because we can't reload it.  */
+                   if (this_alternative_offmemok[c]
+                       && GET_CODE (recog_operand[c]) == MEM
+                       && this_alternative[c] == (int) NO_REGS
+                       && ! this_alternative_win[c])
+                     bad = 1;
+
+                   win = this_alternative_win[c];
+                 }
                else
                  {
                    /* Operands don't match.  */
@@ -2850,7 +2952,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                      = find_dummy_reload (recog_operand[i], recog_operand[c],
                                           recog_operand_loc[i], recog_operand_loc[c],
                                           operand_mode[i], operand_mode[c],
-                                          this_alternative[c], -1);
+                                          this_alternative[c], -1,
+                                          this_alternative_earlyclobber[c]);
 
                    if (value != 0)
                      losers--;
@@ -2887,7 +2990,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                        && REGNO (operand) >= FIRST_PSEUDO_REGISTER
                        && reg_renumber[REGNO (operand)] < 0))
                  win = 1;
-               if (CONSTANT_P (operand))
+               if (CONSTANT_P (operand)
+                   /* force_const_mem does not accept HIGH.  */
+                   && GET_CODE (operand) != HIGH)
                  badop = 0;
                constmemok = 1;
                break;
@@ -2962,7 +3067,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                             && offsettable_memref_p (reg_equiv_mem[REGNO (operand)]))
                            || (reg_equiv_address[REGNO (operand)] != 0))))
                  win = 1;
-               if (CONSTANT_P (operand) || GET_CODE (operand) == MEM)
+               /* force_const_mem does not accept HIGH.  */
+               if ((CONSTANT_P (operand) && GET_CODE (operand) != HIGH)
+                   || GET_CODE (operand) == MEM)
                  badop = 0;
                constmemok = 1;
                offmemok = 1;
@@ -3112,16 +3219,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                  && this_alternative_matches[i] < 0)
                bad = 1;
 
-             /* Alternative loses if it requires a type of reload not
-                permitted for this insn.  We can always reload SCRATCH
-                and objects with a REG_UNUSED note.  */
-             if (GET_CODE (operand) != SCRATCH
-                 && modified[i] != RELOAD_READ && no_output_reloads
-                 && ! find_reg_note (insn, REG_UNUSED, operand))
-               bad = 1;
-             else if (modified[i] != RELOAD_WRITE && no_input_reloads)
-               bad = 1;
-
              /* If this is a constant that is reloaded into the desired
                 class by copying it to memory first, count that as another
                 reload.  This is consistent with other code and is
@@ -3133,9 +3230,10 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              if (CONSTANT_P (operand)
                  /* force_const_mem does not accept HIGH.  */
                  && GET_CODE (operand) != HIGH
-                 && (PREFERRED_RELOAD_CLASS (operand,
+                 && ((PREFERRED_RELOAD_CLASS (operand,
                                              (enum reg_class) this_alternative[i])
-                     == NO_REGS)
+                      == NO_REGS)
+                     || no_input_reloads)
                  && operand_mode[i] != VOIDmode)
                {
                  const_to_mem = 1;
@@ -3155,6 +3253,18 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                      == NO_REGS))
                bad = 1;
 
+             /* Alternative loses if it requires a type of reload not
+                permitted for this insn.  We can always reload SCRATCH
+                and objects with a REG_UNUSED note.  */
+             else if (GET_CODE (operand) != SCRATCH
+                 && modified[i] != RELOAD_READ && no_output_reloads
+                 && ! find_reg_note (insn, REG_UNUSED, operand))
+               bad = 1;
+             else if (modified[i] != RELOAD_WRITE && no_input_reloads
+                      && ! 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
@@ -3167,6 +3277,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                     && REGNO (operand) >= FIRST_PSEUDO_REGISTER)
                  && GET_CODE (operand) != SCRATCH
                  && ! (const_to_mem && constmemok))
+               reject += 2;
+
+             /* Input reloads can be inherited more often than output
+                reloads can be removed, so penalize output reloads.  */
+             if (operand_type[i] != RELOAD_FOR_INPUT
+                 && GET_CODE (operand) != SCRATCH)
                reject++;
            }
 
@@ -3207,7 +3323,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                                          this_alternative[i]))
                    this_alternative[i] = (int) preferred_class[i];
                  else
-                   reject += (1 + pref_or_nothing[i]);
+                   reject += (2 + 2 * pref_or_nothing[i]);
                }
            }
        }
@@ -3314,9 +3430,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 
       /* REJECT, set by the ! and ? constraint characters and when a register
         would be reloaded into a non-preferred class, discourages the use of
-        this alternative for a reload goal.  REJECT is incremented by three
-        for each ? and one for each non-preferred class.  */
-      losers = losers * 3 + reject;
+        this alternative for a reload goal.  REJECT is incremented by six
+        for each ? and two for each non-preferred class.  */
+      losers = losers * 6 + reject;
 
       /* If this alternative can be made to work by reloading,
         and it needs less reloading than the others checked so far,
@@ -3390,7 +3506,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        abort ();
       error_for_asm (insn, "inconsistent operand constraints in an `asm'");
       /* Avoid further trouble with this insn.  */
-      PATTERN (insn) = gen_rtx (USE, VOIDmode, const0_rtx);
+      PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
       n_reloads = 0;
       return;
     }
@@ -3475,9 +3591,10 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        && CONSTANT_P (recog_operand[i])
        /* force_const_mem does not accept HIGH.  */
        && GET_CODE (recog_operand[i]) != HIGH
-       && (PREFERRED_RELOAD_CLASS (recog_operand[i],
+       && ((PREFERRED_RELOAD_CLASS (recog_operand[i],
                                    (enum reg_class) goal_alternative[i])
-           == NO_REGS)
+            == NO_REGS)
+           || no_input_reloads)
        && operand_mode[i] != VOIDmode)
       {
        *recog_operand_loc[i] = recog_operand[i]
@@ -3527,26 +3644,35 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
               we must change these to RELOAD_FOR_INPUT_ADDRESS.  */
 
            if (modified[i] == RELOAD_WRITE)
-             for (j = 0; j < n_reloads; j++)
-               if (reload_opnum[j] == i
-                   && reload_when_needed[j] == RELOAD_FOR_OUTPUT_ADDRESS)
-                 reload_when_needed[j] = RELOAD_FOR_INPUT_ADDRESS;
+             {
+               for (j = 0; j < n_reloads; j++)
+                 {
+                   if (reload_opnum[j] == i)
+                     {
+                       if (reload_when_needed[j] == RELOAD_FOR_OUTPUT_ADDRESS)
+                         reload_when_needed[j] = RELOAD_FOR_INPUT_ADDRESS;
+                       else if (reload_when_needed[j]
+                                == RELOAD_FOR_OUTADDR_ADDRESS)
+                         reload_when_needed[j] = RELOAD_FOR_INPADDR_ADDRESS;
+                     }
+                 }
+             }
          }
        else if (goal_alternative_matched[i] == -1)
-         operand_reloadnum[i] =
-           push_reload (modified[i] != RELOAD_WRITE ? recog_operand[i] : 0,
-                        modified[i] != RELOAD_READ ? recog_operand[i] : 0,
-                        (modified[i] != RELOAD_WRITE ?
-                         recog_operand_loc[i] : 0),
-                        modified[i] != RELOAD_READ ? recog_operand_loc[i] : 0,
-                        (enum reg_class) goal_alternative[i],
-                        (modified[i] == RELOAD_WRITE
-                         ? VOIDmode : operand_mode[i]),
-                        (modified[i] == RELOAD_READ
-                         ? VOIDmode : operand_mode[i]),
-                        (insn_code_number < 0 ? 0
-                         : insn_operand_strict_low[insn_code_number][i]),
-                        0, i, operand_type[i]);
+         operand_reloadnum[i]
+           push_reload (modified[i] != RELOAD_WRITE ? recog_operand[i] : 0,
+                          modified[i] != RELOAD_READ ? recog_operand[i] : 0,
+                          (modified[i] != RELOAD_WRITE
+                           ? recog_operand_loc[i] : 0),
+                          modified[i] != RELOAD_READ ? recog_operand_loc[i] : 0,
+                          (enum reg_class) goal_alternative[i],
+                          (modified[i] == RELOAD_WRITE
+                           ? VOIDmode : operand_mode[i]),
+                          (modified[i] == RELOAD_READ
+                           ? VOIDmode : operand_mode[i]),
+                          (insn_code_number < 0 ? 0
+                           : insn_operand_strict_low[insn_code_number][i]),
+                          0, i, operand_type[i]);
        /* In a matching pair of operands, one must be input only
           and the other must be output only.
           Pass the input operand as IN and the other as OUT.  */
@@ -3584,7 +3710,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
          {
            error_for_asm (insn, "inconsistent operand constraints in an `asm'");
            /* Avoid further trouble with this insn.  */
-           PATTERN (insn) = gen_rtx (USE, VOIDmode, const0_rtx);
+           PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
            n_reloads = 0;
            return;
          }
@@ -3717,9 +3843,13 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 
       for (j = i + 1; j < n_reloads; j++)
        if ((reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
-            || reload_when_needed[i] == RELOAD_FOR_OUTPUT_ADDRESS)
+            || reload_when_needed[i] == RELOAD_FOR_OUTPUT_ADDRESS
+            || reload_when_needed[i] == RELOAD_FOR_INPADDR_ADDRESS
+            || reload_when_needed[i] == RELOAD_FOR_OUTADDR_ADDRESS)
            && (reload_when_needed[j] == RELOAD_FOR_INPUT_ADDRESS
-               || reload_when_needed[j] == RELOAD_FOR_OUTPUT_ADDRESS)
+               || reload_when_needed[j] == RELOAD_FOR_OUTPUT_ADDRESS
+               || reload_when_needed[j] == RELOAD_FOR_INPADDR_ADDRESS
+               || reload_when_needed[j] == RELOAD_FOR_OUTADDR_ADDRESS)
            && rtx_equal_p (reload_in[i], reload_in[j])
            && (operand_reloadnum[reload_opnum[i]] < 0
                || reload_optional[operand_reloadnum[reload_opnum[i]]])
@@ -3733,7 +3863,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              if (replacements[k].what == j)
                replacements[k].what = i;
 
-           reload_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
+           if (reload_when_needed[i] == RELOAD_FOR_INPADDR_ADDRESS
+               || reload_when_needed[i] == RELOAD_FOR_OUTADDR_ADDRESS)
+             reload_when_needed[i] = RELOAD_FOR_OPADDR_ADDR;
+           else
+             reload_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
            reload_in[j] = 0;
          }
     }
@@ -3762,20 +3896,23 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        reload_when_needed[i] = address_type[reload_opnum[i]];
 
       if ((reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
-          || reload_when_needed[i] == RELOAD_FOR_OUTPUT_ADDRESS)
+          || reload_when_needed[i] == RELOAD_FOR_OUTPUT_ADDRESS
+          || reload_when_needed[i] == RELOAD_FOR_INPADDR_ADDRESS
+          || reload_when_needed[i] == RELOAD_FOR_OUTADDR_ADDRESS)
          && (operand_reloadnum[reload_opnum[i]] < 0
              || reload_optional[operand_reloadnum[reload_opnum[i]]]))
        {
          /* If we have a secondary reload to go along with this reload,
             change its type to RELOAD_FOR_OPADDR_ADDR.  */
 
-         if (reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
+         if ((reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
+              || reload_when_needed[i] == RELOAD_FOR_INPADDR_ADDRESS)
              && reload_secondary_in_reload[i] != -1)
            {
              int secondary_in_reload = reload_secondary_in_reload[i];
 
-             reload_when_needed[secondary_in_reload] = 
-               RELOAD_FOR_OPADDR_ADDR;
+             reload_when_needed[secondary_in_reload]
+               RELOAD_FOR_OPADDR_ADDR;
 
              /* If there's a tertiary reload we have to change it also.  */
              if (secondary_in_reload > 0
@@ -3784,13 +3921,14 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                  = RELOAD_FOR_OPADDR_ADDR;
            }
 
-         if (reload_when_needed[i] == RELOAD_FOR_OUTPUT_ADDRESS
+         if ((reload_when_needed[i] == RELOAD_FOR_OUTPUT_ADDRESS
+              || reload_when_needed[i] == RELOAD_FOR_OUTADDR_ADDRESS)
              && reload_secondary_out_reload[i] != -1)
            {
              int secondary_out_reload = reload_secondary_out_reload[i];
 
-             reload_when_needed[secondary_out_reload] = 
-               RELOAD_FOR_OPADDR_ADDR;
+             reload_when_needed[secondary_out_reload]
+               RELOAD_FOR_OPADDR_ADDR;
 
              /* If there's a tertiary reload we have to change it also.  */
              if (secondary_out_reload
@@ -3798,10 +3936,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                reload_when_needed[reload_secondary_out_reload[secondary_out_reload]] 
                  = RELOAD_FOR_OPADDR_ADDR;
            }
+
          reload_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
        }
 
-      if (reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
+      if ((reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
+          || reload_when_needed[i] == RELOAD_FOR_INPADDR_ADDRESS)
          && operand_reloadnum[reload_opnum[i]] >= 0
          && (reload_when_needed[operand_reloadnum[reload_opnum[i]]] 
              == RELOAD_OTHER))
@@ -3811,6 +3951,35 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        reload_opnum[i] = goal_alternative_matches[reload_opnum[i]];
     }
 
+  /* Scan all the reloads, and check for RELOAD_FOR_OPERAND_ADDRESS reloads.
+     If we have more than one, then convert all RELOAD_FOR_OPADDR_ADDR
+     reloads to RELOAD_FOR_OPERAND_ADDRESS reloads.
+
+     choose_reload_regs assumes that RELOAD_FOR_OPADDR_ADDR reloads never
+     conflict with RELOAD_FOR_OPERAND_ADDRESS reloads.  This is true for a
+     single pair of RELOAD_FOR_OPADDR_ADDR/RELOAD_FOR_OPERAND_ADDRESS reloads.
+     However, if there is more than one RELOAD_FOR_OPERAND_ADDRESS reload,
+     then a RELOAD_FOR_OPADDR_ADDR reload conflicts with all
+     RELOAD_FOR_OPERAND_ADDRESS reloads other than the one that uses it.
+     This is complicated by the fact that a single operand can have more
+     than one RELOAD_FOR_OPERAND_ADDRESS reload.  It is very difficult to fix
+     choose_reload_regs without affecting code quality, and cases that
+     actually fail are extremely rare, so it turns out to be better to fix
+     the problem here by not generating cases that choose_reload_regs will
+     fail for.  */
+   
+  {
+    int op_addr_reloads = 0;
+    for (i = 0; i < n_reloads; i++)
+      if (reload_when_needed[i] == RELOAD_FOR_OPERAND_ADDRESS)
+       op_addr_reloads++;
+
+    if (op_addr_reloads > 1)
+      for (i = 0; i < n_reloads; i++)
+       if (reload_when_needed[i] == RELOAD_FOR_OPADDR_ADDR)
+         reload_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
+  }
+
   /* See if we have any reloads that are now allowed to be merged
      because we've changed when the reload is needed to
      RELOAD_FOR_OPERAND_ADDRESS or RELOAD_FOR_OTHER_ADDRESS.  Only
@@ -3819,6 +3988,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
   for (i = 0; i < n_reloads; i++)
     if (reload_in[i] != 0 && reload_out[i] == 0
        && (reload_when_needed[i] == RELOAD_FOR_OPERAND_ADDRESS
+           || reload_when_needed[i] == RELOAD_FOR_OPADDR_ADDR
            || reload_when_needed[i] == RELOAD_FOR_OTHER_ADDRESS))
       for (j = 0; j < n_reloads; j++)
        if (i != j && reload_in[j] != 0 && reload_out[j] == 0
@@ -3833,6 +4003,67 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
            reload_in[j] = 0;
          }
 
+  /* Set which reloads must use registers not used in any group.  Start
+     with those that conflict with a group and then include ones that
+     conflict with ones that are already known to conflict with a group.  */
+
+  changed = 0;
+  for (i = 0; i < n_reloads; i++)
+    {
+      enum machine_mode mode = reload_inmode[i];
+      enum reg_class class = reload_reg_class[i];
+      int size;
+
+      if (GET_MODE_SIZE (reload_outmode[i]) > GET_MODE_SIZE (mode))
+       mode = reload_outmode[i];
+      size = CLASS_MAX_NREGS (class, mode);
+
+      if (size == 1)
+       for (j = 0; j < n_reloads; j++)
+         if ((CLASS_MAX_NREGS (reload_reg_class[j],
+                               (GET_MODE_SIZE (reload_outmode[j])
+                                > GET_MODE_SIZE (reload_inmode[j]))
+                               ? reload_outmode[j] : reload_inmode[j])
+              > 1)
+             && !reload_optional[j]
+             && (reload_in[j] != 0 || reload_out[j] != 0
+                 || reload_secondary_p[j])
+             && reloads_conflict (i, j)
+             && reg_classes_intersect_p (class, reload_reg_class[j]))
+           {
+             reload_nongroup[i] = 1;
+             changed = 1;
+             break;
+           }
+    }
+
+  while (changed)
+    {
+      changed = 0;
+
+      for (i = 0; i < n_reloads; i++)
+       {
+         enum machine_mode mode = reload_inmode[i];
+         enum reg_class class = reload_reg_class[i];
+         int size;
+
+         if (GET_MODE_SIZE (reload_outmode[i]) > GET_MODE_SIZE (mode))
+           mode = reload_outmode[i];
+         size = CLASS_MAX_NREGS (class, mode);
+
+         if (! reload_nongroup[i] && size == 1)
+           for (j = 0; j < n_reloads; j++)
+             if (reload_nongroup[j]
+                 && reloads_conflict (i, j)
+                 && reg_classes_intersect_p (class, reload_reg_class[j]))
+               {
+                 reload_nongroup[i] = 1;
+                 changed = 1;
+                 break;
+               }
+       }
+    }
+
 #else /* no REGISTER_CONSTRAINTS */
   int noperands;
   int insn_code_number;
@@ -3902,7 +4133,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        if (insn_operand_address_p[insn_code_number][i])
          find_reloads_address (VOIDmode, NULL_PTR,
                                recog_operand[i], recog_operand_loc[i],
-                               i, RELOAD_FOR_INPUT, ind_levels);
+                               i, RELOAD_FOR_INPUT, ind_levels, insn);
 
       /* In these cases, we can't tell if the operand is an input
         or an output, so be conservative.  In practice it won't be
@@ -3913,7 +4144,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                              recog_operand_loc[i],
                              XEXP (recog_operand[i], 0),
                              &XEXP (recog_operand[i], 0),
-                             i, RELOAD_OTHER, ind_levels);
+                             i, RELOAD_OTHER, ind_levels, insn);
       if (code == SUBREG)
        recog_operand[i] = *recog_operand_loc[i]
          = find_reloads_toplev (recog_operand[i], i, RELOAD_OTHER,
@@ -4015,11 +4246,11 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
          if (rtx_varies_p (addr))
            addr = copy_rtx (addr);
 
-         x = gen_rtx (MEM, GET_MODE (x), addr);
+         x = gen_rtx_MEM (GET_MODE (x), addr);
          RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
          find_reloads_address (GET_MODE (x), NULL_PTR,
                                XEXP (x, 0),
-                               &XEXP (x, 0), opnum, type, ind_levels);
+                               &XEXP (x, 0), opnum, type, ind_levels, 0);
        }
       return x;
     }
@@ -4027,7 +4258,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
     {
       rtx tem = x;
       find_reloads_address (GET_MODE (x), &tem, XEXP (x, 0), &XEXP (x, 0),
-                           opnum, type, ind_levels);
+                           opnum, type, ind_levels, 0);
       return tem;
     }
 
@@ -4060,6 +4291,29 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
                                     GET_MODE (SUBREG_REG (x)))) != 0)
        return tem;
 
+      /* If the SUBREG is wider than a word, the above test will fail.
+        For example, we might have a SImode SUBREG of a DImode SUBREG_REG
+        for a 16 bit target, or a DImode SUBREG of a TImode SUBREG_REG for
+        a 32 bit target.  We still can - and have to - handle this
+        for non-paradoxical subregs of CONST_INTs.  */
+      if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
+         && reg_equiv_constant[regno] != 0
+         && GET_CODE (reg_equiv_constant[regno]) == CONST_INT
+         && (GET_MODE_SIZE (GET_MODE (x))
+             < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
+         {
+           int shift = SUBREG_WORD (x) * BITS_PER_WORD;
+           if (WORDS_BIG_ENDIAN)
+             shift = (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
+                      - GET_MODE_BITSIZE (GET_MODE (x))
+                      - shift);
+           /* Here we use the knowledge that CONST_INTs have a
+              HOST_WIDE_INT field.  */
+           if (shift >= HOST_BITS_PER_WIDE_INT)
+             shift = HOST_BITS_PER_WIDE_INT - 1;
+           return GEN_INT (INTVAL (reg_equiv_constant[regno]) >> shift);
+         }
+
       if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
          && reg_equiv_constant[regno] != 0
          && GET_MODE (reg_equiv_constant[regno]) == VOIDmode)
@@ -4104,11 +4358,11 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
              offset -= MIN (size, UNITS_PER_WORD);
            }
          addr = plus_constant (addr, offset);
-         x = gen_rtx (MEM, GET_MODE (x), addr);
+         x = gen_rtx_MEM (GET_MODE (x), addr);
          RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
          find_reloads_address (GET_MODE (x), NULL_PTR,
                                XEXP (x, 0),
-                               &XEXP (x, 0), opnum, type, ind_levels);
+                               &XEXP (x, 0), opnum, type, ind_levels, 0);
        }
 
     }
@@ -4130,11 +4384,12 @@ make_memloc (ad, regno)
      rtx ad;
      int regno;
 {
+#if 0
   register int i;
+#endif
   /* 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);
+  rtx tem = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0, NULL_RTX), 0);
 
 #if 0 /* We cannot safely reuse a memloc made here;
         if the pseudo appears twice, and its mem needs a reload,
@@ -4151,7 +4406,7 @@ make_memloc (ad, regno)
   if (rtx_varies_p (tem))
     tem = copy_rtx (tem);
 
-  tem = gen_rtx (MEM, GET_MODE (ad), tem);
+  tem = gen_rtx_MEM (GET_MODE (ad), tem);
   RTX_UNCHANGING_P (tem) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
   memlocs[n_memlocs++] = tem;
   return tem;
@@ -4168,6 +4423,9 @@ make_memloc (ad, regno)
    IND_LEVELS says how many levels of indirect addressing this machine
    supports.
 
+   INSN, if nonzero, is the insn in which we do the reload.  It is used
+   to determine if we may generate output reloads.
+
    Value is nonzero if this address is reloaded or replaced as a whole.
    This is interesting to the caller if the address is an autoincrement.
 
@@ -4178,7 +4436,7 @@ make_memloc (ad, regno)
    to a hard register, and frame pointer elimination.  */
 
 static int
-find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
+find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
      enum machine_mode mode;
      rtx *memrefloc;
      rtx ad;
@@ -4186,6 +4444,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
      int opnum;
      enum reload_type type;
      int ind_levels;
+     rtx insn;
 {
   register int regno;
   rtx tem;
@@ -4209,8 +4468,10 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
        {
          tem = make_memloc (ad, regno);
          find_reloads_address (GET_MODE (tem), NULL_PTR, XEXP (tem, 0),
-                               &XEXP (tem, 0), opnum, type, ind_levels);
-         push_reload (tem, NULL_RTX, loc, NULL_PTR, BASE_REG_CLASS,
+                               &XEXP (tem, 0), opnum, ADDR_TYPE (type),
+                               ind_levels, insn);
+         push_reload (tem, NULL_RTX, loc, NULL_PTR,
+                      reload_address_base_reg_class,
                       GET_MODE (ad), VOIDmode, 0, 0,
                       opnum, type);
          return 1;
@@ -4233,12 +4494,13 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
         hard register that is valid as a base register and which is not the
         subject of a CLOBBER in this insn.  */
 
-      else if (regno < FIRST_PSEUDO_REGISTER && REGNO_OK_FOR_BASE_P (regno)
+      else if (regno < FIRST_PSEUDO_REGISTER
+              && REGNO_MODE_OK_FOR_BASE_P (regno, mode)
               && ! regno_clobbered_p (regno, this_insn))
        return 0;
 
       /* If we do not have one of the cases above, we must do the reload.  */
-      push_reload (ad, NULL_RTX, loc, NULL_PTR, BASE_REG_CLASS,
+      push_reload (ad, NULL_RTX, loc, NULL_PTR, reload_address_base_reg_class,
                   GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
       return 1;
     }
@@ -4270,6 +4532,24 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
        return 0;
     }
 
+#ifdef LEGITIMIZE_RELOAD_ADDRESS
+  do
+    {
+      if (memrefloc)
+       {
+         LEGITIMIZE_RELOAD_ADDRESS (ad, GET_MODE (*memrefloc), opnum, type,
+                                    ind_levels, win);
+       }
+      break;
+    win:
+      *memrefloc = copy_rtx (*memrefloc);
+      XEXP (*memrefloc, 0) = ad;
+      move_replacements (&ad, &XEXP (*memrefloc, 0));
+      return 1;
+    }
+  while (0);
+#endif
+
   /* The address is not valid.  We have to figure out why.  One possibility
      is that it is itself a MEM.  This can happen when the frame pointer is
      being eliminated, a pseudo is not allocated to a hard register, and the
@@ -4282,7 +4562,8 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
         indirect addresses are valid, reload the MEM into a register.  */
       tem = ad;
       find_reloads_address (GET_MODE (ad), &tem, XEXP (ad, 0), &XEXP (ad, 0),
-                           opnum, type, ind_levels == 0 ? 0 : ind_levels - 1);
+                           opnum, ADDR_TYPE (type),
+                           ind_levels == 0 ? 0 : ind_levels - 1, insn);
 
       /* If tem was changed, then we must create a new memory reference to
         hold it and store it back into memrefloc.  */
@@ -4308,7 +4589,8 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
          /* Must use TEM here, not AD, since it is the one that will
             have any subexpressions reloaded, if needed.  */
          push_reload (tem, NULL_RTX, loc, NULL_PTR,
-                      BASE_REG_CLASS, GET_MODE (tem), VOIDmode, 0,
+                      reload_address_base_reg_class, GET_MODE (tem),
+                      VOIDmode, 0,
                       0, opnum, type);
          return 1;
        }
@@ -4324,7 +4606,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
   else if (GET_CODE (ad) == PLUS
           && GET_CODE (XEXP (ad, 0)) == REG
           && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
-          && REG_OK_FOR_BASE_P (XEXP (ad, 0))
+          && REG_MODE_OK_FOR_BASE_P (XEXP (ad, 0), mode)
           && GET_CODE (XEXP (ad, 1)) == CONST_INT)
     {
       /* Unshare the MEM rtx so we can safely alter it.  */
@@ -4340,16 +4622,16 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
          /* Reload the displacement into an index reg.
             We assume the frame pointer or arg pointer is a base reg.  */
          find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
-                                    INDEX_REG_CLASS, GET_MODE (ad), opnum,
-                                    type, ind_levels);
+                                    reload_address_index_reg_class,
+                                    GET_MODE (ad), opnum, type, ind_levels);
        }
       else
        {
          /* If the sum of two regs is not necessarily valid,
             reload the sum into a base reg.
             That will at least work.  */
-         find_reloads_address_part (ad, loc, BASE_REG_CLASS, Pmode,
-                                    opnum, type, ind_levels);
+         find_reloads_address_part (ad, loc, reload_address_base_reg_class,
+                                    Pmode, opnum, type, ind_levels);
        }
       return 1;
     }
@@ -4395,13 +4677,15 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
               || XEXP (XEXP (ad, 0), 0) == stack_pointer_rtx)
           && ! memory_address_p (mode, ad))
     {
-      *loc = ad = gen_rtx (PLUS, GET_MODE (ad),
-                          plus_constant (XEXP (XEXP (ad, 0), 0),
-                                         INTVAL (XEXP (ad, 1))),
+      *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
+                               plus_constant (XEXP (XEXP (ad, 0), 0),
+                                              INTVAL (XEXP (ad, 1))),
                           XEXP (XEXP (ad, 0), 1));
-      find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0), BASE_REG_CLASS,
+      find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0),
+                                reload_address_base_reg_class,
                                 GET_MODE (ad), opnum, type, ind_levels);
-      find_reloads_address_1 (XEXP (ad, 1), 1, &XEXP (ad, 1), opnum, type, 0);
+      find_reloads_address_1 (mode, XEXP (ad, 1), 1, &XEXP (ad, 1), opnum,
+                             type, 0, insn);
 
       return 1;
     }
@@ -4418,13 +4702,15 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
               || XEXP (XEXP (ad, 0), 1) == stack_pointer_rtx)
           && ! memory_address_p (mode, ad))
     {
-      *loc = ad = gen_rtx (PLUS, GET_MODE (ad),
-                          XEXP (XEXP (ad, 0), 0),
-                          plus_constant (XEXP (XEXP (ad, 0), 1),
-                                         INTVAL (XEXP (ad, 1))));
-      find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1), BASE_REG_CLASS,
+      *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
+                               XEXP (XEXP (ad, 0), 0),
+                               plus_constant (XEXP (XEXP (ad, 0), 1),
+                                              INTVAL (XEXP (ad, 1))));
+      find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
+                                reload_address_base_reg_class,
                                 GET_MODE (ad), opnum, type, ind_levels);
-      find_reloads_address_1 (XEXP (ad, 0), 1, &XEXP (ad, 0), opnum, type, 0);
+      find_reloads_address_1 (mode, XEXP (ad, 0), 1, &XEXP (ad, 0), opnum,
+                             type, 0, insn);
 
       return 1;
     }
@@ -4465,12 +4751,14 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
          loc = &XEXP (*memrefloc, 0);
        }
 
-      find_reloads_address_part (ad, loc, BASE_REG_CLASS, Pmode, opnum, type,
+      find_reloads_address_part (ad, loc, reload_address_base_reg_class,
+                                Pmode, opnum, type,
                                 ind_levels);
       return 1;
     }
 
-  return find_reloads_address_1 (ad, 0, loc, opnum, type, ind_levels);
+  return find_reloads_address_1 (mode, ad, 0, loc, opnum, type, ind_levels,
+                                insn);
 }
 \f
 /* Find all pseudo regs appearing in AD
@@ -4514,6 +4802,10 @@ subst_reg_equivs (ad)
       if (XEXP (ad, 0) == frame_pointer_rtx
          && GET_CODE (XEXP (ad, 1)) == CONST_INT)
        return ad;
+      break;
+      
+    default:
+      break;
     }
 
   fmt = GET_RTX_FORMAT (code);
@@ -4567,10 +4859,10 @@ form_sum (x, y)
       if (GET_CODE (y) == CONST)
        y = XEXP (y, 0);
 
-      return gen_rtx (CONST, VOIDmode, gen_rtx (PLUS, mode, x, y));
+      return gen_rtx_CONST (VOIDmode, gen_rtx_PLUS (mode, x, y));
     }
 
-  return gen_rtx (PLUS, mode, x, y);
+  return gen_rtx_PLUS (mode, x, y);
 }
 \f
 /* If ADDR is a sum containing a pseudo register that should be
@@ -4633,9 +4925,11 @@ subst_indexed_address (addr)
   return addr;
 }
 \f
-/* Record the pseudo registers we must reload into hard registers
-   in a subexpression of a would-be memory address, X.
-   (This function is not called if the address we find is strictly valid.)
+/* Record the pseudo registers we must reload into hard registers in a
+   subexpression of a would-be memory address, X referring to a value
+   in mode MODE.  (This function is not called if the address we find
+   is strictly valid.)
+
    CONTEXT = 1 means we are considering regs as index regs,
    = 0 means we are considering them as base regs.
 
@@ -4644,6 +4938,9 @@ subst_indexed_address (addr)
    IND_LEVELS says how many levels of indirect addressing are
    supported at this point in the address.
 
+   INSN, if nonzero, is the insn in which we do the reload.  It is used
+   to determine if we may generate output reloads.
+
    We return nonzero if X, as a whole, is reloaded or replaced.  */
 
 /* Note that we take shortcuts assuming that no multi-reg machine mode
@@ -4653,13 +4950,15 @@ subst_indexed_address (addr)
    could have addressing modes that this does not handle right.  */
 
 static int
-find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
+find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
+     enum machine_mode mode;
      rtx x;
      int context;
      rtx *loc;
      int opnum;
      enum reload_type type;
      int ind_levels;
+     rtx insn;
 {
   register RTX_CODE code = GET_CODE (x);
 
@@ -4679,8 +4978,8 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
            op0 = SUBREG_REG (op0);
            code0 = GET_CODE (op0);
            if (code0 == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER)
-             op0 = gen_rtx (REG, word_mode,
-                            REGNO (op0) + SUBREG_WORD (orig_op0));
+             op0 = gen_rtx_REG (word_mode,
+                                REGNO (op0) + SUBREG_WORD (orig_op0));
          }
 
        if (GET_CODE (op1) == SUBREG)
@@ -4688,81 +4987,81 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
            op1 = SUBREG_REG (op1);
            code1 = GET_CODE (op1);
            if (code1 == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER)
-             op1 = gen_rtx (REG, GET_MODE (op1),
-                            REGNO (op1) + SUBREG_WORD (orig_op1));
+             op1 = gen_rtx_REG (GET_MODE (op1),
+                                REGNO (op1) + SUBREG_WORD (orig_op1));
          }
 
        if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE 
            || code0 == ZERO_EXTEND || code1 == MEM)
          {
-           find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type,
-                                   ind_levels);
-           find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
-                                   ind_levels);
+           find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
+                                   type, ind_levels, insn);
+           find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
+                                   type, ind_levels, insn);
          }
 
        else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
                 || code1 == ZERO_EXTEND || code0 == MEM)
          {
-           find_reloads_address_1 (orig_op0, 0, &XEXP (x, 0), opnum, type,
-                                   ind_levels);
-           find_reloads_address_1 (orig_op1, 1, &XEXP (x, 1), opnum, type,
-                                   ind_levels);
+           find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
+                                   type, ind_levels, insn);
+           find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
+                                   type, ind_levels, insn);
          }
 
        else if (code0 == CONST_INT || code0 == CONST
                 || code0 == SYMBOL_REF || code0 == LABEL_REF)
-         find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
-                                 ind_levels);
+         find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
+                                 type, ind_levels, insn);
 
        else if (code1 == CONST_INT || code1 == CONST
                 || code1 == SYMBOL_REF || code1 == LABEL_REF)
-         find_reloads_address_1 (orig_op0, 0, &XEXP (x, 0), opnum, type,
-                                 ind_levels);
+         find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
+                                 type, ind_levels, insn);
 
        else if (code0 == REG && code1 == REG)
          {
            if (REG_OK_FOR_INDEX_P (op0)
-               && REG_OK_FOR_BASE_P (op1))
+               && REG_MODE_OK_FOR_BASE_P (op1, mode))
              return 0;
            else if (REG_OK_FOR_INDEX_P (op1)
-                    && REG_OK_FOR_BASE_P (op0))
+                    && REG_MODE_OK_FOR_BASE_P (op0, mode))
              return 0;
-           else if (REG_OK_FOR_BASE_P (op1))
-             find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type, 
-                                     ind_levels);
-           else if (REG_OK_FOR_BASE_P (op0))
-             find_reloads_address_1 (orig_op1, 1, &XEXP (x, 1), opnum, type,
-                                     ind_levels);
+           else if (REG_MODE_OK_FOR_BASE_P (op1, mode))
+             find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
+                                     type, ind_levels, insn);
+           else if (REG_MODE_OK_FOR_BASE_P (op0, mode))
+             find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
+                                     type, ind_levels, insn);
            else if (REG_OK_FOR_INDEX_P (op1))
-             find_reloads_address_1 (orig_op0, 0, &XEXP (x, 0), opnum, type,
-                                     ind_levels);
+             find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
+                                     type, ind_levels, insn);
            else if (REG_OK_FOR_INDEX_P (op0))
-           find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
-                                   ind_levels);
+             find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
+                                     type, ind_levels, insn);
            else
              {
-               find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type,
-                                       ind_levels);
-               find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
-                                       ind_levels);
+               find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
+                                       type, ind_levels, insn);
+               find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
+                                       type, ind_levels, insn);
              }
          }
 
        else if (code0 == REG)
          {
-           find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type,
-                                   ind_levels);
-           find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
-                                   ind_levels);
+           find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
+                                   type, ind_levels, insn);
+           find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
+                                   type, ind_levels, insn);
          }
 
        else if (code1 == REG)
          {
-           find_reloads_address_1 (orig_op1, 1, &XEXP (x, 1), opnum, type,
-                                   ind_levels);
-           find_reloads_address_1 (orig_op0, 0, &XEXP (x, 0), opnum, type,
-                                   ind_levels);
+           find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
+                                   type, ind_levels, insn);
+           find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
+                                   type, ind_levels, insn);
          }
       }
 
@@ -4788,11 +5087,15 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
          if (reg_equiv_address[regno] != 0)
            {
              rtx tem = make_memloc (XEXP (x, 0), regno);
-             /* First reload the memory location's address.  */
+             /* First reload the memory location's address.
+                We can't use ADDR_TYPE (type) here, because we need to
+                write back the value after reading it, hence we actually
+                need two registers.  */
              find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
-                                   &XEXP (tem, 0), opnum, type, ind_levels);
+                                   &XEXP (tem, 0), opnum, type,
+                                   ind_levels, insn);
              /* Put this inside a new increment-expression.  */
-             x = gen_rtx (GET_CODE (x), GET_MODE (x), tem);
+             x = gen_rtx_fmt_e (GET_CODE (x), GET_MODE (x), tem);
              /* Proceed to reload that, as if it contained a register.  */
            }
 
@@ -4811,19 +5114,55 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
            regno = reg_renumber[regno];
          if ((regno >= FIRST_PSEUDO_REGISTER
               || !(context ? REGNO_OK_FOR_INDEX_P (regno)
-                   : REGNO_OK_FOR_BASE_P (regno))))
+                   : REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
            {
+#ifdef AUTO_INC_DEC
              register rtx link;
-
-             int reloadnum
-               = push_reload (x, NULL_RTX, loc, NULL_PTR,
-                              context ? INDEX_REG_CLASS : BASE_REG_CLASS,
-                              GET_MODE (x), GET_MODE (x), VOIDmode, 0,
-                              opnum, type);
-             reload_inc[reloadnum]
-               = find_inc_amount (PATTERN (this_insn), XEXP (x_orig, 0));
-
-             value = 1;
+#endif
+             int reloadnum;
+
+             /* If we can output the register afterwards, do so, this
+                saves the extra update.
+                We can do so if we have an INSN - i.e. no JUMP_INSN nor
+                CALL_INSN - and it does not set CC0.
+                But don't do this if we cannot directly address the
+                memory location, since this will make it harder to
+                reuse address reloads, and increases register pressure.
+                Also don't do this if we can probably update x directly.  */
+             rtx equiv = reg_equiv_mem[regno];
+             int icode = (int) add_optab->handlers[(int) Pmode].insn_code;
+             if (insn && GET_CODE (insn) == INSN && equiv
+#ifdef HAVE_cc0
+                 && ! sets_cc0_p (PATTERN (insn))
+#endif
+                 && ! (icode != CODE_FOR_nothing
+                       && (*insn_operand_predicate[icode][0]) (equiv, Pmode)
+                       && (*insn_operand_predicate[icode][1]) (equiv, Pmode)))
+               {
+                 loc = &XEXP (x, 0);
+                 x = XEXP (x, 0);
+                 reloadnum
+                   = push_reload (x, x, loc, loc,
+                                  (context
+                                   ? reload_address_index_reg_class
+                                   : reload_address_base_reg_class),
+                                   GET_MODE (x), GET_MODE (x), 0, 0,
+                                   opnum, RELOAD_OTHER);
+               }
+             else
+               {
+                 reloadnum
+                   = push_reload (x, NULL_RTX, loc, NULL_PTR,
+                                  (context
+                                   ? reload_address_index_reg_class
+                                   : reload_address_base_reg_class),
+                                  GET_MODE (x), GET_MODE (x), 0, 0,
+                                  opnum, type);
+                 reload_inc[reloadnum]
+                   = find_inc_amount (PATTERN (this_insn), XEXP (x_orig, 0));
+    
+                 value = 1;
+               }
 
 #ifdef AUTO_INC_DEC
              /* Update the REG_INC notes.  */
@@ -4854,12 +5193,17 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
             Note that this is actually conservative:  it would be slightly
             more efficient to use the value of SPILL_INDIRECT_LEVELS from
             reload1.c here.  */
+         /* We can't use ADDR_TYPE (type) here, because we need to
+            write back the value after reading it, hence we actually
+            need two registers.  */
          find_reloads_address (GET_MODE (x), &XEXP (x, 0),
                                XEXP (XEXP (x, 0), 0), &XEXP (XEXP (x, 0), 0),
-                               opnum, type, ind_levels);
+                               opnum, type, ind_levels, insn);
 
          reloadnum = push_reload (x, NULL_RTX, loc, NULL_PTR,
-                                  context ? INDEX_REG_CLASS : BASE_REG_CLASS,
+                                  (context
+                                   ? reload_address_index_reg_class
+                                   : reload_address_base_reg_class),
                                   GET_MODE (x), VOIDmode, 0, 0, opnum, type);
          reload_inc[reloadnum]
            = find_inc_amount (PATTERN (this_insn), XEXP (x, 0));
@@ -4886,9 +5230,10 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
         reload1.c here.  */
 
       find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
-                           opnum, type, ind_levels);
+                           opnum, ADDR_TYPE (type), ind_levels, insn);
       push_reload (*loc, NULL_RTX, loc, NULL_PTR,
-                  context ? INDEX_REG_CLASS : BASE_REG_CLASS,
+                  (context ? reload_address_index_reg_class
+                   : reload_address_base_reg_class),
                   GET_MODE (x), VOIDmode, 0, 0, opnum, type);
       return 1;
 
@@ -4899,8 +5244,9 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
        if (reg_equiv_constant[regno] != 0)
          {
            find_reloads_address_part (reg_equiv_constant[regno], loc, 
-                                      (context ? INDEX_REG_CLASS
-                                       : BASE_REG_CLASS),
+                                      (context
+                                       ? reload_address_index_reg_class
+                                       : reload_address_base_reg_class),
                                       GET_MODE (x), opnum, type, ind_levels);
            return 1;
          }
@@ -4910,7 +5256,9 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
        if (reg_equiv_mem[regno] != 0)
          {
            push_reload (reg_equiv_mem[regno], NULL_RTX, loc, NULL_PTR,
-                        context ? INDEX_REG_CLASS : BASE_REG_CLASS,
+                        (context
+                         ? reload_address_index_reg_class
+                         : reload_address_base_reg_class),
                         GET_MODE (x), VOIDmode, 0, 0, opnum, type);
            return 1;
          }
@@ -4920,7 +5268,7 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
          {
            x = make_memloc (x, regno);
            find_reloads_address (GET_MODE (x), 0, XEXP (x, 0), &XEXP (x, 0),
-                                 opnum, type, ind_levels);
+                                 opnum, ADDR_TYPE (type), ind_levels, insn);
          }
 
        if (reg_renumber[regno] >= 0)
@@ -4928,10 +5276,12 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
 
        if ((regno >= FIRST_PSEUDO_REGISTER
             || !(context ? REGNO_OK_FOR_INDEX_P (regno)
-                 : REGNO_OK_FOR_BASE_P (regno))))
+                 : REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
          {
            push_reload (x, NULL_RTX, loc, NULL_PTR,
-                        context ? INDEX_REG_CLASS : BASE_REG_CLASS,
+                        (context
+                         ? reload_address_index_reg_class
+                         : reload_address_base_reg_class),
                         GET_MODE (x), VOIDmode, 0, 0, opnum, type);
            return 1;
          }
@@ -4943,7 +5293,9 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
        if (regno_clobbered_p (regno, this_insn))
          {
            push_reload (x, NULL_RTX, loc, NULL_PTR,
-                        context ? INDEX_REG_CLASS : BASE_REG_CLASS,
+                        (context
+                         ? reload_address_index_reg_class
+                         : reload_address_base_reg_class),
                         GET_MODE (x), VOIDmode, 0, 0, opnum, type);
            return 1;
          }
@@ -4961,10 +5313,12 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
              int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
 
              if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
-                    : REGNO_OK_FOR_BASE_P (regno)))
+                    : REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
                {
                  push_reload (x, NULL_RTX, loc, NULL_PTR,
-                              context ? INDEX_REG_CLASS : BASE_REG_CLASS,
+                              (context
+                               ? reload_address_index_reg_class
+                               : reload_address_base_reg_class),
                               GET_MODE (x), VOIDmode, 0, 0, opnum, type);
                  return 1;
                }
@@ -4974,7 +5328,8 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
          else
            {
              enum reg_class class = (context
-                                     ? INDEX_REG_CLASS : BASE_REG_CLASS);
+                                     ? reload_address_index_reg_class
+                                     : reload_address_base_reg_class);
              if (CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
                  > reg_class_size[class])
                {
@@ -4985,6 +5340,9 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
            }
        }
       break;
+      
+    default:
+      break;
     }
 
   {
@@ -4994,8 +5352,8 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
     for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
       {
        if (fmt[i] == 'e')
-         find_reloads_address_1 (XEXP (x, i), context, &XEXP (x, i),
-                                 opnum, type, ind_levels);
+         find_reloads_address_1 (mode, XEXP (x, i), context, &XEXP (x, i),
+                                 opnum, type, ind_levels, insn);
       }
   }
 
@@ -5033,7 +5391,7 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels)
     {
       rtx tem = x = force_const_mem (mode, x);
       find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
-                           opnum, type, ind_levels);
+                           opnum, type, ind_levels, 0);
     }
 
   else if (GET_CODE (x) == PLUS
@@ -5043,9 +5401,9 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels)
     {
       rtx tem = force_const_mem (GET_MODE (x), XEXP (x, 1));
 
-      x = gen_rtx (PLUS, GET_MODE (x), XEXP (x, 0), tem);
+      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);
+                           opnum, type, ind_levels, 0);
     }
 
   push_reload (x, NULL_RTX, loc, NULL_PTR, class,
@@ -5075,7 +5433,7 @@ subst_reloads ()
             do the wrong thing if RELOADREG is multi-word.  RELOADREG
             will always be a REG here.  */
          if (GET_MODE (reloadreg) != r->mode && r->mode != VOIDmode)
-           reloadreg = gen_rtx (REG, r->mode, REGNO (reloadreg));
+           reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg));
 
          /* If we are putting this into a SUBREG and RELOADREG is a
             SUBREG, we would be making nested SUBREGs, so we have to fix
@@ -5142,6 +5500,25 @@ copy_replacements (x, y)
            }
        }
 }
+
+/* Change any replacements being done to *X to be done to *Y */
+
+void
+move_replacements (x, y)
+     rtx *x;
+     rtx *y;
+{
+  int i;
+
+  for (i = 0; i < n_replacements; i++)
+    if (replacements[i].subreg_loc == x)
+      replacements[i].subreg_loc = y;
+    else if (replacements[i].where == x)
+      {
+       replacements[i].where = y;
+       replacements[i].subreg_loc = 0;
+      }
+}
 \f
 /* If LOC was scheduled to be replaced by something, return the replacement.
    Otherwise, return *LOC.  */
@@ -5159,7 +5536,7 @@ find_replacement (loc)
       if (reloadreg && r->where == loc)
        {
          if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
-           reloadreg = gen_rtx (REG, r->mode, REGNO (reloadreg));
+           reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg));
 
          return reloadreg;
        }
@@ -5170,16 +5547,28 @@ find_replacement (loc)
             ??? Is it actually still ever a SUBREG?  If so, why?  */
 
          if (GET_CODE (reloadreg) == REG)
-           return gen_rtx (REG, GET_MODE (*loc),
-                           REGNO (reloadreg) + SUBREG_WORD (*loc));
+           return gen_rtx_REG (GET_MODE (*loc),
+                               REGNO (reloadreg) + SUBREG_WORD (*loc));
          else if (GET_MODE (reloadreg) == GET_MODE (*loc))
            return reloadreg;
          else
-           return gen_rtx (SUBREG, GET_MODE (*loc), SUBREG_REG (reloadreg),
-                           SUBREG_WORD (reloadreg) + SUBREG_WORD (*loc));
+           return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg),
+                                  SUBREG_WORD (reloadreg) + SUBREG_WORD (*loc));
        }
     }
 
+  /* If *LOC is a PLUS, MINUS, or MULT, see if a replacement is scheduled for
+     what's inside and make a new rtl if so.  */
+  if (GET_CODE (*loc) == PLUS || GET_CODE (*loc) == MINUS
+      || GET_CODE (*loc) == MULT)
+    {
+      rtx x = find_replacement (&XEXP (*loc, 0));
+      rtx y = find_replacement (&XEXP (*loc, 1));
+
+      if (x != XEXP (*loc, 0) || y != XEXP (*loc, 1))
+       return gen_rtx_fmt_ee (GET_CODE (*loc), GET_MODE (*loc), x, y);
+    }
+
   return *loc;
 }
 \f
@@ -5274,6 +5663,9 @@ refers_to_regno_for_reload_p (regno, endregno, x, loc)
        return 0;
       x = SET_SRC (x);
       goto repeat;
+      
+    default:
+      break;
     }
 
   /* X does not match, so try its subexpressions.  */
@@ -5454,6 +5846,8 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
        case POST_DEC:
        case PRE_DEC:
          return 0;
+       default:
+         break;
        }
       goal_mem = 1;
     }
@@ -5463,6 +5857,10 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
           && XEXP (goal, 0) == stack_pointer_rtx
           && CONSTANT_P (XEXP (goal, 1)))
     goal_const = need_stable_sp = 1;
+  else if (GET_CODE (goal) == PLUS
+          && XEXP (goal, 0) == frame_pointer_rtx
+          && CONSTANT_P (XEXP (goal, 1)))
+    goal_const = 1;
   else
     return 0;
 
@@ -5759,6 +6157,9 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
                      else if (goal_mem && GET_CODE (dest) == MEM
                               && ! push_operand (dest, GET_MODE (dest)))
                        return 0;
+                     else if (GET_CODE (dest) == MEM && regno >= FIRST_PSEUDO_REGISTER
+                              && reg_equiv_memory_loc[regno] != 0)
+                       return 0;
                      else if (need_stable_sp
                               && push_operand (dest, GET_MODE (dest)))
                        return 0;
@@ -5918,8 +6319,10 @@ static char *reload_when_needed_name[] =
   "RELOAD_FOR_INPUT", 
   "RELOAD_FOR_OUTPUT", 
   "RELOAD_FOR_INSN",
-  "RELOAD_FOR_INPUT_ADDRESS", 
+  "RELOAD_FOR_INPUT_ADDRESS",
+  "RELOAD_FOR_INPADDR_ADDRESS",
   "RELOAD_FOR_OUTPUT_ADDRESS",
+  "RELOAD_FOR_OUTADDR_ADDRESS",
   "RELOAD_FOR_OPERAND_ADDRESS", 
   "RELOAD_FOR_OPADDR_ADDR",
   "RELOAD_OTHER", 
@@ -5928,97 +6331,100 @@ static char *reload_when_needed_name[] =
 
 static char *reg_class_names[] = REG_CLASS_NAMES;
 
-/* This function is used to print the variables set by 'find_reloads' */
+/* These functions are used to print the variables set by 'find_reloads' */
 
 void
-debug_reload()
+debug_reload_to_stream (f)
+     FILE *f;
 {
   int r;
+  char *prefix;
 
-  fprintf (stderr, "\nn_reloads = %d\n", n_reloads);
-
+  if (! f)
+    f = stderr;
   for (r = 0; r < n_reloads; r++)
     {
-      fprintf (stderr, "\nRELOAD %d\n", r);
+      fprintf (f, "Reload %d: ", r);
 
-      if (reload_in[r])
+      if (reload_in[r] != 0)
        {
-         fprintf (stderr, "\nreload_in (%s) = ",
+         fprintf (f, "reload_in (%s) = ",
                   GET_MODE_NAME (reload_inmode[r]));
-         debug_rtx (reload_in[r]);
+         print_inline_rtx (f, reload_in[r], 24);
+         fprintf (f, "\n\t");
        }
 
-      if (reload_out[r])
+      if (reload_out[r] != 0)
        {
-         fprintf (stderr, "\nreload_out (%s) = ",
+         fprintf (f, "reload_out (%s) = ",
                   GET_MODE_NAME (reload_outmode[r]));
-         debug_rtx (reload_out[r]);
+         print_inline_rtx (f, reload_out[r], 24);
+         fprintf (f, "\n\t");
        }
 
-      fprintf (stderr, "%s, ", reg_class_names[(int) reload_reg_class[r]]);
+      fprintf (f, "%s, ", reg_class_names[(int) reload_reg_class[r]]);
 
-      fprintf (stderr, "%s (opnum = %d)",
-              reload_when_needed_name[(int)reload_when_needed[r]],
+      fprintf (f, "%s (opnum = %d)",
+              reload_when_needed_name[(int) reload_when_needed[r]],
               reload_opnum[r]);
 
       if (reload_optional[r])
-       fprintf (stderr, ", optional");
+       fprintf (f, ", optional");
+
+      if (reload_nongroup[r])
+       fprintf (stderr, ", nongroup");
 
-      if (reload_in[r])
-       fprintf (stderr, ", inc by %d\n", reload_inc[r]);
+      if (reload_inc[r] != 0)
+       fprintf (f, ", inc by %d", reload_inc[r]);
 
       if (reload_nocombine[r])
-       fprintf (stderr, ", can't combine", reload_nocombine[r]);
+       fprintf (f, ", can't combine");
 
       if (reload_secondary_p[r])
-       fprintf (stderr, ", secondary_reload_p");
+       fprintf (f, ", secondary_reload_p");
 
-      if (reload_in_reg[r])
+      if (reload_in_reg[r] != 0)
        {
-         fprintf (stderr, "\nreload_in_reg:\t\t\t");
-         debug_rtx (reload_in_reg[r]);
+         fprintf (f, "\n\treload_in_reg: ");
+         print_inline_rtx (f, reload_in_reg[r], 24);
        }
 
-      if (reload_reg_rtx[r])
+      if (reload_reg_rtx[r] != 0)
        {
-         fprintf (stderr, "\nreload_reg_rtx:\t\t\t");
-         debug_rtx (reload_reg_rtx[r]);
+         fprintf (f, "\n\treload_reg_rtx: ");
+         print_inline_rtx (f, reload_reg_rtx[r], 24);
        }
 
+      prefix = "\n\t";
       if (reload_secondary_in_reload[r] != -1)
        {
-         fprintf (stderr, "\nsecondary_in_reload = ");
-         fprintf (stderr, "%d ", reload_secondary_in_reload[r]);
+         fprintf (f, "%ssecondary_in_reload = %d",
+                  prefix, reload_secondary_in_reload[r]);
+         prefix = ", ";
        }
 
       if (reload_secondary_out_reload[r] != -1)
-       {
-         if (reload_secondary_in_reload[r] != -1)
-           fprintf (stderr, ", secondary_out_reload = ");
-         else
-           fprintf (stderr, "\nsecondary_out_reload = ");
-
-         fprintf (stderr, "%d", reload_secondary_out_reload[r]);
-       }
-
+       fprintf (f, "%ssecondary_out_reload = %d\n",
+                prefix, reload_secondary_out_reload[r]);
 
+      prefix = "\n\t";
       if (reload_secondary_in_icode[r] != CODE_FOR_nothing)
        {
-         fprintf (stderr, "\nsecondary_in_icode = ");
-         fprintf (stderr, "%s", insn_name[r]);
+         fprintf (stderr, "%ssecondary_in_icode = %s", prefix,
+                  insn_name[reload_secondary_in_icode[r]]);
+         prefix = ", ";
        }
 
       if (reload_secondary_out_icode[r] != CODE_FOR_nothing)
-       {
-         if (reload_secondary_in_icode[r] != CODE_FOR_nothing)
-           fprintf (stderr, ", secondary_out_icode = ");
-         else
-           fprintf (stderr, "\nsecondary_out_icode = ");
+       fprintf (stderr, "%ssecondary_out_icode = %s", prefix,
+                insn_name[reload_secondary_out_icode[r]]);
 
-         fprintf (stderr, "%s ", insn_name[r]);
-       }
-      fprintf (stderr, "\n");
+      fprintf (f, "\n");
     }
+}
 
-  fprintf (stderr, "\n");
+void
+debug_reload ()
+{
+  debug_reload_to_stream (stderr);
 }