OSDN Git Service

* lex.c (lang_init_options): New function.
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index 983060a..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.
 
@@ -88,7 +88,7 @@ a register with any other reload.  */
 #define REG_OK_STRICT
 
 #include "config.h"
-#include <stdio.h>
+#include "system.h"
 #include "rtl.h"
 #include "insn-config.h"
 #include "insn-codes.h"
@@ -100,6 +100,7 @@ a register with any other reload.  */
 #include "real.h"
 #include "output.h"
 #include "expr.h"
+#include "toplev.h"
 
 #ifndef REGISTER_MOVE_COST
 #define REGISTER_MOVE_COST(x, y) 2
@@ -128,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).
@@ -175,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];
@@ -306,9 +310,11 @@ static int output_reloadnum;
       ? 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,
@@ -366,7 +372,6 @@ 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
@@ -526,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;
@@ -594,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;
@@ -886,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
@@ -923,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.  */
@@ -987,9 +1001,11 @@ push_reload (in, out, inloc, outloc, class,
              && ((GET_MODE_SIZE (outmode)
                   > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
 #ifdef WORD_REGISTER_OPERATIONS
-                 || ((GET_MODE_SIZE (outmode) - 1) / UNITS_PER_WORD ==
-                     ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - 1)
-                      / UNITS_PER_WORD))
+                 || ((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
@@ -1025,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 ();
@@ -1261,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;
@@ -1489,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.
@@ -2305,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);
@@ -2451,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;
@@ -2567,11 +2600,29 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
          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
@@ -2590,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)
@@ -2611,16 +2670,13 @@ 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);
@@ -2660,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;
@@ -2715,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
@@ -2727,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
@@ -2745,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])
@@ -2763,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.  */
@@ -2814,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 '#':
@@ -3150,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
@@ -3171,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;
@@ -3193,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
@@ -3205,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++;
            }
 
@@ -3245,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]);
                }
            }
        }
@@ -3352,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,
@@ -3513,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]
@@ -3857,11 +3936,8 @@ 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;
            }
-         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_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
        }
 
       if ((reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
@@ -3927,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;
@@ -4154,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)
@@ -4224,7 +4384,9 @@ 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);
@@ -4370,6 +4532,24 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
        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
@@ -4936,7 +5116,9 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
               || !(context ? REGNO_OK_FOR_INDEX_P (regno)
                    : REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
            {
+#ifdef AUTO_INC_DEC
              register rtx link;
+#endif
              int reloadnum;
 
              /* If we can output the register afterwards, do so, this
@@ -5318,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.  */
@@ -5656,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;
 
@@ -6166,6 +6371,9 @@ debug_reload_to_stream (f)
       if (reload_optional[r])
        fprintf (f, ", optional");
 
+      if (reload_nongroup[r])
+       fprintf (stderr, ", nongroup");
+
       if (reload_inc[r] != 0)
        fprintf (f, ", inc by %d", reload_inc[r]);
 
@@ -6202,12 +6410,14 @@ debug_reload_to_stream (f)
       prefix = "\n\t";
       if (reload_secondary_in_icode[r] != CODE_FOR_nothing)
        {
-         fprintf (f, "%ssecondary_in_icode = %s", prefix, 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)
-       fprintf (f, "%ssecondary_out_icode = %s", prefix, insn_name[r]);
+       fprintf (stderr, "%ssecondary_out_icode = %s", prefix,
+                insn_name[reload_secondary_out_icode[r]]);
 
       fprintf (f, "\n");
     }