OSDN Git Service

H
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index c9ebee9..831436c 100644 (file)
@@ -21,6 +21,9 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+
+#include "machmode.h"
+#include "hard-reg-set.h"
 #include "rtl.h"
 #include "obstack.h"
 #include "insn-config.h"
@@ -29,12 +32,12 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "expr.h"
 #include "regs.h"
-#include "hard-reg-set.h"
+#include "basic-block.h"
 #include "reload.h"
 #include "recog.h"
-#include "basic-block.h"
 #include "output.h"
 #include "real.h"
+#include "toplev.h"
 
 /* This file contains the reload pass of the compiler, which is
    run after register allocation has been done.  It checks that
@@ -51,9 +54,10 @@ Boston, MA 02111-1307, USA.  */
    called ``reload regs'', and for each place where a pseudo reg
    must be in a hard reg, copy it temporarily into one of the reload regs.
 
-   All the pseudos that were formerly allocated to the hard regs that
-   are now in use as reload regs must be ``spilled''.  This means
-   that they go to other hard regs, or to stack slots if no other
+   Reload regs are allocated locally for every instruction that needs
+   reloads.  When there are pseudos which are allocated to a register that
+   has been chosen as a reload reg, such pseudos must be ``spilled''.
+   This means that they go to other hard regs, or to stack slots if no other
    available hard regs can be found.  Spilling can invalidate more
    insns, requiring additional need for reloads, so we must keep checking
    until the process stabilizes.
@@ -114,8 +118,11 @@ static int *reg_max_ref_width;
    constant or memory slot.  */
 static rtx *reg_equiv_init;
 
+/* Vector to remember old contents of reg_renumber before spilling.  */
+static short *reg_old_renumber;
+
 /* During reload_as_needed, element N contains the last pseudo regno reloaded
-  into hard register N.  If that pseudo reg occupied more than one register,
+   into hard register N.  If that pseudo reg occupied more than one register,
    reg_reloaded_contents points to that pseudo for each spill register in
    use; all of these must remain set for an inheritance to occur.  */
 static int reg_reloaded_contents[FIRST_PSEUDO_REGISTER];
@@ -145,41 +152,61 @@ static rtx spill_reg_rtx[FIRST_PSEUDO_REGISTER];
    The precise value is the insn generated to do the store.  */
 static rtx spill_reg_store[FIRST_PSEUDO_REGISTER];
 
+/* This is the register that was stored with spill_reg_store.  This is a
+   copy of reload_out / reload_out_reg when the value was stored; if
+   reload_out is a MEM, spill_reg_stored_to will be set to reload_out_reg.  */
+static rtx spill_reg_stored_to[FIRST_PSEUDO_REGISTER];
+
 /* This table is the inverse mapping of spill_regs:
    indexed by hard reg number,
    it contains the position of that reg in spill_regs,
-   or -1 for something that is not in spill_regs.  */
-static short spill_reg_order[FIRST_PSEUDO_REGISTER];
+   or -1 for something that is not in spill_regs. 
 
-/* This reg set indicates registers that may not be used for retrying global
-   allocation.  The registers that may not be used include all spill registers
-   and the frame pointer (if we are using one).  */
-HARD_REG_SET forbidden_regs;
-
-/* This reg set indicates registers that are not good for spill registers.
-   They will not be used to complete groups of spill registers.  This includes
-   all fixed registers, registers that may be eliminated, and, if
-   SMALL_REGISTER_CLASSES is zero, registers explicitly used in the rtl.
+   ?!?  This is no longer accurate.  */
+static short spill_reg_order[FIRST_PSEUDO_REGISTER];
 
-   (spill_reg_order prevents these registers from being used to start a
-   group.)  */
+/* This reg set indicates registers that can't be used as spill registers for
+   the currently processed insn.  These are the hard registers which are live
+   during the insn, but not allocated to pseudos, as well as fixed
+   registers.  */
 static HARD_REG_SET bad_spill_regs;
 
+/* These are the hard registers that can't be used as spill register for any
+   insn.  This includes registers used for user variables and registers that
+   we can't eliminate.  A register that appears in this set also can't be used
+   to retry register allocation.  */
+static HARD_REG_SET bad_spill_regs_global;
+
 /* Describes order of use of registers for reloading
-   of spilled pseudo-registers.  `spills' is the number of
-   elements that are actually valid; new ones are added at the end.  */
+   of spilled pseudo-registers.  `n_spills' is the number of
+   elements that are actually valid; new ones are added at the end.
+
+   Both spill_regs and spill_reg_order are used on two occasions:
+   once during find_reload_regs, where they keep track of the spill registers
+   for a single insn, but also during reload_as_needed where they show all
+   the registers ever used by reload.  For the latter case, the information
+   is calculated during finish_spills.  */
 static short spill_regs[FIRST_PSEUDO_REGISTER];
 
-/* This reg set indicates those registers that have been used a spill
-   registers.  This information is used in reorg.c, to help figure out
-   what registers are live at any point.  It is assumed that all spill_regs
-   are dead at every CODE_LABEL.  */
+/* This vector of reg sets indicates, for each pseudo, which hard registers
+   may not be used for retrying global allocation because the register was
+   formerly spilled from one of them.  If we allowed reallocating a pseudo to
+   a register that it was already allocated to, reload might not
+   terminate.  */
+static HARD_REG_SET *pseudo_previous_regs;
 
-HARD_REG_SET used_spill_regs;
+/* This vector of reg sets indicates, for each pseudo, which hard
+   registers may not be used for retrying global allocation because they
+   are used as spill registers during one of the insns in which the
+   pseudo is live.  */
+static HARD_REG_SET *pseudo_forbidden_regs;
+
+/* All hard regs that have been used as spill registers for any insn are
+   marked in this set.  */
+static HARD_REG_SET used_spill_regs;
 
 /* Index of last register assigned as a spill register.  We allocate in
    a round-robin fashion.  */
-
 static int last_spill_reg;
 
 /* Describes order of preference for putting regs into spill_regs.
@@ -189,54 +216,30 @@ static int last_spill_reg;
    Empty elements at the end contain -1.  */
 static short potential_reload_regs[FIRST_PSEUDO_REGISTER];
 
-/* 1 for a hard register that appears explicitly in the rtl
-   (for example, function value registers, special registers
-   used by insns, structure value pointer registers).  */
-static char regs_explicitly_used[FIRST_PSEUDO_REGISTER];
-
-/* Indicates if a register was counted against the need for
-   groups.  0 means it can count against max_nongroup instead.  */
-static HARD_REG_SET counted_for_groups;
-
-/* Indicates if a register was counted against the need for
-   non-groups.  0 means it can become part of a new group.
-   During choose_reload_regs, 1 here means don't use this reg
-   as part of a group, even if it seems to be otherwise ok.  */
-static HARD_REG_SET counted_for_nongroups;
-
 /* Nonzero if indirect addressing is supported on the machine; this means
    that spilling (REG n) does not require reloading it into a register in
    order to do (MEM (REG n)) or (MEM (PLUS (REG n) (CONST_INT c))).  The
    value indicates the level of indirect addressing supported, e.g., two
    means that (MEM (MEM (REG n))) is also valid if (REG n) does not get
    a hard register.  */
-
 static char spill_indirect_levels;
 
 /* Nonzero if indirect addressing is supported when the innermost MEM is
    of the form (MEM (SYMBOL_REF sym)).  It is assumed that the level to
    which these are valid is the same as spill_indirect_levels, above.   */
-
 char indirect_symref_ok;
 
 /* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid.  */
-
 char double_reg_address_ok;
 
 /* Record the stack slot for each spilled hard register.  */
-
 static rtx spill_stack_slot[FIRST_PSEUDO_REGISTER];
 
 /* Width allocated so far for that stack slot.  */
-
 static int spill_stack_slot_width[FIRST_PSEUDO_REGISTER];
 
-/* Indexed by register class and basic block number, nonzero if there is
-   any need for a spill register of that class in that basic block.
-   The pointer is 0 if we did stupid allocation and don't know
-   the structure of basic blocks.  */
-
-char *basic_block_needs[N_REG_CLASSES];
+/* Record which pseudos needed to be spilled.  */
+static regset spilled_pseudos;
 
 /* First uid used by insns created by reload in this function.
    Used in find_equiv_reg.  */
@@ -244,38 +247,29 @@ int reload_first_uid;
 
 /* Flag set by local-alloc or global-alloc if anything is live in
    a call-clobbered reg across calls.  */
-
 int caller_save_needed;
 
-/* The register class to use for a base register when reloading an
-   address.  This is normally BASE_REG_CLASS, but it may be different
-   when using SMALL_REGISTER_CLASSES and passing parameters in
-   registers.  */
-enum reg_class reload_address_base_reg_class;
-
-/* The register class to use for an index register when reloading an
-   address.  This is normally INDEX_REG_CLASS, but it may be different
-   when using SMALL_REGISTER_CLASSES and passing parameters in
-   registers.  */
-enum reg_class reload_address_index_reg_class;
-
 /* Set to 1 while reload_as_needed is operating.
    Required by some machines to handle any generated moves differently.  */
-
 int reload_in_progress = 0;
 
 /* These arrays record the insn_code of insns that may be needed to
    perform input and output reloads of special objects.  They provide a
    place to pass a scratch register.  */
-
 enum insn_code reload_in_optab[NUM_MACHINE_MODES];
 enum insn_code reload_out_optab[NUM_MACHINE_MODES];
 
 /* This obstack is used for allocation of rtl during register elimination.
    The allocated storage can be freed once find_reloads has processed the
    insn.  */
-
 struct obstack reload_obstack;
+
+/* Points to the beginning of the reload_obstack.  All insn_chain structures
+   are allocated first.  */
+char *reload_startobj;
+
+/* The point after all insn_chain structures.  Used to quickly deallocate
+   memory used while processing one insn.  */
 char *reload_firstobj;
 
 #define obstack_chunk_alloc xmalloc
@@ -284,8 +278,12 @@ char *reload_firstobj;
 /* List of labels that must never be deleted.  */
 extern rtx forced_labels;
 
-/* Allocation number table from global register allocation.  */
-extern int *reg_allocno;
+/* List of insn_chain instructions, one for every insn that reload needs to
+   examine.  */
+struct insn_chain *reload_insn_chain;
+
+/* List of all insns needing reloads.  */
+static struct insn_chain *insns_need_reload;
 \f
 /* This structure is used to record information about register eliminations.
    Each array entry describes one possible way of eliminating a register
@@ -301,7 +299,6 @@ static struct elim_table
   int can_eliminate_previous;  /* Value of CAN_ELIMINATE in previous scan over
                                   insns made by reload.  */
   int offset;                  /* Current offset between the two regs.  */
-  int max_offset;              /* Maximum offset between the two regs.  */
   int previous_offset;         /* Offset at end of previous insn.  */
   int ref_outside_mem;         /* "to" has been referenced outside a MEM.  */
   rtx from_rtx;                        /* REG rtx for the register to be eliminated.
@@ -327,7 +324,7 @@ static struct elim_table
 /* Record the number of pending eliminations that have an offset not equal
    to their initial offset.  If non-zero, we use a new copy of each
    replacement result in any insns encountered.  */
-static int num_not_at_initial_offset;
+int num_not_at_initial_offset;
 
 /* Count the number of registers that we may be able to eliminate.  */
 static int num_eliminable;
@@ -346,29 +343,52 @@ static int (*offsets_at)[NUM_ELIMINABLE_REGS];
 
 static int num_labels;
 
-struct hard_reg_n_uses { int regno; int uses; };
+struct hard_reg_n_uses
+{
+  int regno;
+  unsigned int uses;
+};
 \f
-static int possible_group_p            PROTO((int, int *));
-static void count_possible_groups      PROTO((int *, enum machine_mode *,
-                                              int *, int));
+static void maybe_fix_stack_asms       PROTO((void));
+static void calculate_needs_all_insns  PROTO((int));
+static void calculate_needs            PROTO((struct insn_chain *));
+static void find_reload_regs           PROTO((struct insn_chain *chain,
+                                              FILE *));
+static void find_tworeg_group          PROTO((struct insn_chain *, int,
+                                              FILE *));
+static void find_group                 PROTO((struct insn_chain *, int,
+                                              FILE *));
+static int possible_group_p            PROTO((struct insn_chain *, int));
+static void count_possible_groups      PROTO((struct insn_chain *, int));
 static int modes_equiv_for_class_p     PROTO((enum machine_mode,
                                               enum machine_mode,
                                               enum reg_class));
+static void delete_caller_save_insns   PROTO((void));
+
 static void spill_failure              PROTO((rtx));
-static int new_spill_reg               PROTO((int, int, int *, int *, int,
-                                              FILE *));
+static void new_spill_reg              PROTO((struct insn_chain *, int, int,
+                                              int, FILE *));
+static void maybe_mark_pseudo_spilled  PROTO((int));
 static void delete_dead_insn           PROTO((rtx));
 static void alter_reg                          PROTO((int, int));
-static void mark_scratch_live          PROTO((rtx));
 static void set_label_offsets          PROTO((rtx, rtx, int));
 static int eliminate_regs_in_insn      PROTO((rtx, int));
+static void update_eliminable_offsets  PROTO((void));
 static void mark_not_eliminable                PROTO((rtx, rtx));
-static int spill_hard_reg              PROTO((int, int, FILE *, int));
+static void set_initial_elim_offsets   PROTO((void));
+static void verify_initial_elim_offsets        PROTO((void));
+static void set_initial_label_offsets  PROTO((void));
+static void set_offsets_for_label      PROTO((rtx));
+static void init_elim_table            PROTO((void));
+static void update_eliminables         PROTO((HARD_REG_SET *));
+static void spill_hard_reg             PROTO((int, FILE *, int));
+static int finish_spills               PROTO((int, FILE *));
+static void ior_hard_reg_set           PROTO((HARD_REG_SET *, HARD_REG_SET *));
 static void scan_paradoxical_subregs   PROTO((rtx));
 static int hard_reg_use_compare                PROTO((const GENERIC_PTR, const GENERIC_PTR));
-static void order_regs_for_reload      PROTO((int));
-static int compare_spill_regs          PROTO((const GENERIC_PTR, const GENERIC_PTR));
-static void reload_as_needed           PROTO((rtx, int));
+static void count_pseudo               PROTO((struct hard_reg_n_uses *, int));
+static void order_regs_for_reload      PROTO((struct insn_chain *));
+static void reload_as_needed           PROTO((int));
 static void forget_old_reloads_1       PROTO((rtx, rtx));
 static int reload_reg_class_lower      PROTO((const GENERIC_PTR, const GENERIC_PTR));
 static void mark_reload_reg_in_use     PROTO((int, int, enum reload_type,
@@ -376,15 +396,20 @@ static void mark_reload_reg_in_use        PROTO((int, int, enum reload_type,
 static void clear_reload_reg_in_use    PROTO((int, int, enum reload_type,
                                               enum machine_mode));
 static int reload_reg_free_p           PROTO((int, int, enum reload_type));
-static int reload_reg_free_before_p    PROTO((int, int, enum reload_type));
+static int reload_reg_free_before_p    PROTO((int, int, enum reload_type, int));
+static int reload_reg_free_for_value_p PROTO((int, int, enum reload_type, rtx, rtx, int));
 static int reload_reg_reaches_end_p    PROTO((int, int, enum reload_type));
-static int allocate_reload_reg         PROTO((int, rtx, int, int));
-static void choose_reload_regs         PROTO((rtx, rtx));
+static int allocate_reload_reg         PROTO((struct insn_chain *, int, int,
+                                              int));
+static void choose_reload_regs         PROTO((struct insn_chain *));
 static void merge_assigned_reloads     PROTO((rtx));
-static void emit_reload_insns          PROTO((rtx));
-static void delete_output_reload       PROTO((rtx, int, rtx));
-static void inc_for_reload             PROTO((rtx, rtx, int));
+static void emit_reload_insns          PROTO((struct insn_chain *));
+static void delete_output_reload       PROTO((rtx, int, int));
+static void delete_address_reloads     PROTO((rtx, rtx));
+static void delete_address_reloads_1   PROTO((rtx, rtx, rtx));
+static rtx inc_for_reload              PROTO((rtx, rtx, rtx, int));
 static int constraint_accepts_reg_p    PROTO((char *, rtx));
+static void reload_cse_regs_1          PROTO((rtx));
 static void reload_cse_invalidate_regno        PROTO((int, enum machine_mode, int));
 static int reload_cse_mem_conflict_p   PROTO((rtx, rtx));
 static void reload_cse_invalidate_mem  PROTO((rtx));
@@ -395,8 +420,11 @@ static int reload_cse_simplify_set PROTO((rtx, rtx));
 static int reload_cse_simplify_operands        PROTO((rtx));
 static void reload_cse_check_clobber   PROTO((rtx, rtx));
 static void reload_cse_record_set      PROTO((rtx, rtx));
-static void reload_cse_delete_death_notes      PROTO((rtx));
-static void reload_cse_no_longer_dead  PROTO((int, enum machine_mode));
+static void reload_combine PROTO((void));
+static void reload_combine_note_use PROTO((rtx *, rtx));
+static void reload_combine_note_store PROTO((rtx, rtx));
+static void reload_cse_move2add PROTO((rtx));
+static void move2add_note_store PROTO((rtx, rtx));
 \f
 /* Initialize the reload pass once per compilation.  */
 
@@ -446,67 +474,67 @@ init_reload ()
 
   /* Initialize obstack for our rtl allocation.  */
   gcc_obstack_init (&reload_obstack);
-  reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+  reload_startobj = (char *) obstack_alloc (&reload_obstack, 0);
+}
 
-  /* Decide which register class should be used when reloading
-     addresses.  If we are using SMALL_REGISTER_CLASSES, and any
-     parameters are passed in registers, then we do not want to use
-     those registers when reloading an address.  Otherwise, if a
-     function argument needs a reload, we may wind up clobbering
-     another argument to the function which was already computed.  If
-     we find a subset class which simply avoids those registers, we
-     use it instead.  ??? It would be better to only use the
-     restricted class when we actually are loading function arguments,
-     but that is hard to determine.  */
-  reload_address_base_reg_class = BASE_REG_CLASS;
-  reload_address_index_reg_class = INDEX_REG_CLASS;
-  if (SMALL_REGISTER_CLASSES)
-    {
-      int regno;
-      HARD_REG_SET base, index;
-      enum reg_class *p;
+/* List of insn chains that are currently unused.  */
+static struct insn_chain *unused_insn_chains = 0;
 
-      COPY_HARD_REG_SET (base, reg_class_contents[BASE_REG_CLASS]);
-      COPY_HARD_REG_SET (index, reg_class_contents[INDEX_REG_CLASS]);
-      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-       {
-         if (FUNCTION_ARG_REGNO_P (regno))
-           {
-             CLEAR_HARD_REG_BIT (base, regno);
-             CLEAR_HARD_REG_BIT (index, regno);
-           }
-       }
-      
-      GO_IF_HARD_REG_EQUAL (base, reg_class_contents[BASE_REG_CLASS],
-                           baseok);
-      for (p = reg_class_subclasses[BASE_REG_CLASS];
-          *p != LIM_REG_CLASSES;
-          p++)
-       {
-         GO_IF_HARD_REG_EQUAL (base, reg_class_contents[*p], usebase);
-         continue;
-       usebase:
-         reload_address_base_reg_class = *p;
-         break;
-       }
-    baseok:;
+/* Allocate an empty insn_chain structure.  */
+struct insn_chain *
+new_insn_chain ()
+{
+  struct insn_chain *c;
 
-      GO_IF_HARD_REG_EQUAL (index, reg_class_contents[INDEX_REG_CLASS],
-                           indexok);
-      for (p = reg_class_subclasses[INDEX_REG_CLASS];
-          *p != LIM_REG_CLASSES;
-          p++)
-       {
-         GO_IF_HARD_REG_EQUAL (index, reg_class_contents[*p], useindex);
-         continue;
-       useindex:
-         reload_address_index_reg_class = *p;
-         break;
-       }
-    indexok:;
+  if (unused_insn_chains == 0)
+    {
+      c = obstack_alloc (&reload_obstack, sizeof (struct insn_chain));
+      c->live_before = OBSTACK_ALLOC_REG_SET (&reload_obstack);
+      c->live_after = OBSTACK_ALLOC_REG_SET (&reload_obstack);
+    }
+  else
+    {
+      c = unused_insn_chains;
+      unused_insn_chains = c->next;
     }
+  c->is_caller_save_insn = 0;
+  c->need_operand_change = 0;
+  c->need_reload = 0;
+  c->need_elim = 0;
+  return c;
 }
 
+/* Small utility function to set all regs in hard reg set TO which are
+   allocated to pseudos in regset FROM.  */
+void
+compute_use_by_pseudos (to, from)
+     HARD_REG_SET *to;
+     regset from;
+{
+  int regno;
+  EXECUTE_IF_SET_IN_REG_SET
+    (from, FIRST_PSEUDO_REGISTER, regno,
+     {
+       int r = reg_renumber[regno];
+       int nregs;
+       if (r < 0)
+        abort ();
+       nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (regno));
+       while (nregs-- > 0)
+        SET_HARD_REG_BIT (*to, r + nregs);
+     });
+}
+\f
+/* Global variables used by reload and its subroutines.  */
+
+/* Set during calculate_needs if an insn needs register elimination.  */
+static int something_needs_elimination;
+/* Set during calculate_needs if an insn needs an operand changed.  */
+int something_needs_operands_changed;
+
+/* Nonzero means we couldn't get enough spill regs.  */
+static int failure;
+
 /* Main entry point for the reload pass.
 
    FIRST is the first insn of the function being compiled.
@@ -531,8 +559,7 @@ reload (first, global, dumpfile)
      int global;
      FILE *dumpfile;
 {
-  register int class;
-  register int i, j, k;
+  register int i;
   register rtx insn;
   register struct elim_table *ep;
 
@@ -541,38 +568,25 @@ reload (first, global, dumpfile)
   char *real_known_ptr = NULL_PTR;
   int (*real_at_ptr)[NUM_ELIMINABLE_REGS];
 
-  int something_changed;
-  int something_needs_reloads;
-  int something_needs_elimination;
-  int new_basic_block_needs;
-  enum reg_class caller_save_spill_class = NO_REGS;
-  int caller_save_group_size = 1;
+  /* Make sure even insns with volatile mem refs are recognizable.  */
+  init_recog ();
 
-  /* Nonzero means we couldn't get enough spill regs.  */
-  int failure = 0;
+  failure = 0;
 
-  /* The basic block number currently being processed for INSN.  */
-  int this_block;
+  reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
 
-  /* Make sure even insns with volatile mem refs are recognizable.  */
-  init_recog ();
+  /* Make sure that the last insn in the chain
+     is not something that needs reloading.  */
+  emit_note (NULL_PTR, NOTE_INSN_DELETED);
 
   /* Enable find_equiv_reg to distinguish insns made by reload.  */
   reload_first_uid = get_max_uid ();
 
-  for (i = 0; i < N_REG_CLASSES; i++)
-    basic_block_needs[i] = 0;
-
 #ifdef SECONDARY_MEMORY_NEEDED
   /* Initialize the secondary memory table.  */
   clear_secondary_mem ();
 #endif
 
-  /* Remember which hard regs appear explicitly
-     before we merge into `regs_ever_live' the ones in which
-     pseudo regs have been allocated.  */
-  bcopy (regs_ever_live, regs_explicitly_used, sizeof regs_ever_live);
-
   /* We don't have a stack slot for any spill reg yet.  */
   bzero ((char *) spill_stack_slot, sizeof spill_stack_slot);
   bzero ((char *) spill_stack_slot_width, sizeof spill_stack_slot_width);
@@ -597,14 +611,6 @@ reload (first, global, dumpfile)
          regs_ever_live[i] = 1;
       }
 
-  for (i = 0; i < scratch_list_length; i++)
-    if (scratch_list[i])
-      mark_scratch_live (scratch_list[i]);
-
-  /* Make sure that the last insn in the chain
-     is not something that needs reloading.  */
-  emit_note (NULL_PTR, NOTE_INSN_DELETED);
-
   /* Find all the pseudo registers that didn't get hard regs
      but do have known equivalent constants or memory slots.
      These include parameters (known equivalent to parameter slots)
@@ -615,21 +621,27 @@ reload (first, global, dumpfile)
      Record memory equivalents in reg_mem_equiv so they can
      be substituted eventually by altering the REG-rtx's.  */
 
-  reg_equiv_constant = (rtx *) alloca (max_regno * sizeof (rtx));
+  reg_equiv_constant = (rtx *) xmalloc (max_regno * sizeof (rtx));
   bzero ((char *) reg_equiv_constant, max_regno * sizeof (rtx));
-  reg_equiv_memory_loc = (rtx *) alloca (max_regno * sizeof (rtx));
+  reg_equiv_memory_loc = (rtx *) xmalloc (max_regno * sizeof (rtx));
   bzero ((char *) reg_equiv_memory_loc, max_regno * sizeof (rtx));
-  reg_equiv_mem = (rtx *) alloca (max_regno * sizeof (rtx));
+  reg_equiv_mem = (rtx *) xmalloc (max_regno * sizeof (rtx));
   bzero ((char *) reg_equiv_mem, max_regno * sizeof (rtx));
-  reg_equiv_init = (rtx *) alloca (max_regno * sizeof (rtx));
+  reg_equiv_init = (rtx *) xmalloc (max_regno * sizeof (rtx));
   bzero ((char *) reg_equiv_init, max_regno * sizeof (rtx));
-  reg_equiv_address = (rtx *) alloca (max_regno * sizeof (rtx));
+  reg_equiv_address = (rtx *) xmalloc (max_regno * sizeof (rtx));
   bzero ((char *) reg_equiv_address, max_regno * sizeof (rtx));
-  reg_max_ref_width = (int *) alloca (max_regno * sizeof (int));
+  reg_max_ref_width = (int *) xmalloc (max_regno * sizeof (int));
   bzero ((char *) reg_max_ref_width, max_regno * sizeof (int));
+  reg_old_renumber = (short *) xmalloc (max_regno * sizeof (short));
+  bcopy (reg_renumber, reg_old_renumber, max_regno * sizeof (short));
+  pseudo_forbidden_regs
+    = (HARD_REG_SET *) xmalloc (max_regno * sizeof (HARD_REG_SET));
+  pseudo_previous_regs
+    = (HARD_REG_SET *) xmalloc (max_regno * sizeof (HARD_REG_SET));
 
-  if (SMALL_REGISTER_CLASSES)
-    CLEAR_HARD_REG_SET (forbidden_regs);
+  CLEAR_HARD_REG_SET (bad_spill_regs_global);
+  bzero ((char *) pseudo_previous_regs, max_regno * sizeof (HARD_REG_SET));
 
   /* Look for REG_EQUIV notes; record what each pseudo is equivalent to.
      Also find all paradoxical subregs and find largest such for each pseudo.
@@ -706,46 +718,7 @@ reload (first, global, dumpfile)
        scan_paradoxical_subregs (PATTERN (insn));
     }
 
-  /* Does this function require a frame pointer?  */
-
-  frame_pointer_needed = (! flag_omit_frame_pointer
-#ifdef EXIT_IGNORE_STACK
-                         /* ?? If EXIT_IGNORE_STACK is set, we will not save
-                            and restore sp for alloca.  So we can't eliminate
-                            the frame pointer in that case.  At some point,
-                            we should improve this by emitting the
-                            sp-adjusting insns for this case.  */
-                         || (current_function_calls_alloca
-                             && EXIT_IGNORE_STACK)
-#endif
-                         || FRAME_POINTER_REQUIRED);
-
-  num_eliminable = 0;
-
-  /* Initialize the table of registers to eliminate.  The way we do this
-     depends on how the eliminable registers were defined.  */
-#ifdef ELIMINABLE_REGS
-  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-    {
-      ep->can_eliminate = ep->can_eliminate_previous
-       = (CAN_ELIMINATE (ep->from, ep->to)
-          && ! (ep->to == STACK_POINTER_REGNUM && frame_pointer_needed));
-    }
-#else
-  reg_eliminate[0].can_eliminate = reg_eliminate[0].can_eliminate_previous
-    = ! frame_pointer_needed;
-#endif
-
-  /* Count the number of eliminable registers and build the FROM and TO
-     REG rtx's.  Note that code in gen_rtx will cause, e.g.,
-     gen_rtx (REG, Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx.
-     We depend on this.  */
-  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-    {
-      num_eliminable += ep->can_eliminate;
-      ep->from_rtx = gen_rtx_REG (Pmode, ep->from);
-      ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
-    }
+  init_elim_table ();
 
   num_labels = max_label_num () - get_first_label_num ();
 
@@ -795,114 +768,53 @@ reload (first, global, dumpfile)
     {
       free (real_known_ptr);
       free (real_at_ptr);
-      return;
+      free (reg_equiv_constant);
+      free (reg_equiv_memory_loc);
+      free (reg_equiv_mem);
+      free (reg_equiv_init);
+      free (reg_equiv_address);
+      free (reg_max_ref_width);
+      free (reg_old_renumber);
+      free (pseudo_previous_regs);
+      free (pseudo_forbidden_regs);
+      return 0;
     }
 #endif
 
-  /* Compute the order of preference for hard registers to spill.
-     Store them by decreasing preference in potential_reload_regs.  */
-
-  order_regs_for_reload (global);
-
-  /* So far, no hard regs have been spilled.  */
-  n_spills = 0;
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    spill_reg_order[i] = -1;
+  maybe_fix_stack_asms ();
 
+  insns_need_reload = 0;
+  something_needs_elimination = 0;
+  
   /* Initialize to -1, which means take the first spill register.  */
   last_spill_reg = -1;
 
-  /* On most machines, we can't use any register explicitly used in the
-     rtl as a spill register.  But on some, we have to.  Those will have
-     taken care to keep the life of hard regs as short as possible.  */
-
-  if (! SMALL_REGISTER_CLASSES)
-    COPY_HARD_REG_SET (forbidden_regs, bad_spill_regs);
+  spilled_pseudos = ALLOCA_REG_SET ();
 
   /* Spill any hard regs that we know we can't eliminate.  */
+  CLEAR_HARD_REG_SET (used_spill_regs);
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     if (! ep->can_eliminate)
-      spill_hard_reg (ep->from, global, dumpfile, 1);
+      spill_hard_reg (ep->from, dumpfile, 1);
 
 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
   if (frame_pointer_needed)
-    spill_hard_reg (HARD_FRAME_POINTER_REGNUM, global, dumpfile, 1);
+    spill_hard_reg (HARD_FRAME_POINTER_REGNUM, dumpfile, 1);
 #endif
-
-  if (global)
-    for (i = 0; i < N_REG_CLASSES; i++)
-      {
-       basic_block_needs[i] = (char *) alloca (n_basic_blocks);
-       bzero (basic_block_needs[i], n_basic_blocks);
-      }
+  finish_spills (global, dumpfile);
 
   /* From now on, we need to emit any moves without making new pseudos.  */
   reload_in_progress = 1;
 
   /* This loop scans the entire function each go-round
      and repeats until one repetition spills no additional hard regs.  */
-
-  /* This flag is set when a pseudo reg is spilled,
-     to require another pass.  Note that getting an additional reload
-     reg does not necessarily imply any pseudo reg was spilled;
-     sometimes we find a reload reg that no pseudo reg was allocated in.  */
-  something_changed = 1;
-  /* This flag is set if there are any insns that require reloading.  */
-  something_needs_reloads = 0;
-  /* This flag is set if there are any insns that require register
-     eliminations.  */
-  something_needs_elimination = 0;
-  while (something_changed)
+  for (;;)
     {
-      rtx after_call = 0;
-
-      /* For each class, number of reload regs needed in that class.
-        This is the maximum over all insns of the needs in that class
-        of the individual insn.  */
-      int max_needs[N_REG_CLASSES];
-      /* For each class, size of group of consecutive regs
-        that is needed for the reloads of this class.  */
-      int group_size[N_REG_CLASSES];
-      /* For each class, max number of consecutive groups needed.
-        (Each group contains group_size[CLASS] consecutive registers.)  */
-      int max_groups[N_REG_CLASSES];
-      /* For each class, max number needed of regs that don't belong
-        to any of the groups.  */
-      int max_nongroups[N_REG_CLASSES];
-      /* For each class, the machine mode which requires consecutive
-        groups of regs of that class.
-        If two different modes ever require groups of one class,
-        they must be the same size and equally restrictive for that class,
-        otherwise we can't handle the complexity.  */
-      enum machine_mode group_mode[N_REG_CLASSES];
-      /* Record the insn where each maximum need is first found.  */
-      rtx max_needs_insn[N_REG_CLASSES];
-      rtx max_groups_insn[N_REG_CLASSES];
-      rtx max_nongroups_insn[N_REG_CLASSES];
-      rtx x;
-      HOST_WIDE_INT starting_frame_size;
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
-      int previous_frame_pointer_needed = frame_pointer_needed;
-#endif
-      static char *reg_class_names[] = REG_CLASS_NAMES;
+      int something_changed;
+      int did_spill;
+      struct insn_chain *chain;
 
-      something_changed = 0;
-      bzero ((char *) max_needs, sizeof max_needs);
-      bzero ((char *) max_groups, sizeof max_groups);
-      bzero ((char *) max_nongroups, sizeof max_nongroups);
-      bzero ((char *) max_needs_insn, sizeof max_needs_insn);
-      bzero ((char *) max_groups_insn, sizeof max_groups_insn);
-      bzero ((char *) max_nongroups_insn, sizeof max_nongroups_insn);
-      bzero ((char *) group_size, sizeof group_size);
-      for (i = 0; i < N_REG_CLASSES; i++)
-       group_mode[i] = VOIDmode;
-
-      /* Keep track of which basic blocks are needing the reloads.  */
-      this_block = 0;
-
-      /* Remember whether any element of basic_block_needs
-        changes from 0 to 1 in this pass.  */
-      new_basic_block_needs = 0;
+      HOST_WIDE_INT starting_frame_size;
 
       /* Round size of stack frame to BIGGEST_ALIGNMENT.  This must be done
         here because the stack size may be a part of the offset computation
@@ -912,38 +824,8 @@ reload (first, global, dumpfile)
 
       starting_frame_size = get_frame_size ();
 
-      /* Reset all offsets on eliminable registers to their initial values.  */
-#ifdef ELIMINABLE_REGS
-      for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-       {
-         INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->initial_offset);
-         ep->previous_offset = ep->offset
-           = ep->max_offset = ep->initial_offset;
-       }
-#else
-#ifdef INITIAL_FRAME_POINTER_OFFSET
-      INITIAL_FRAME_POINTER_OFFSET (reg_eliminate[0].initial_offset);
-#else
-      if (!FRAME_POINTER_REQUIRED)
-       abort ();
-      reg_eliminate[0].initial_offset = 0;
-#endif
-      reg_eliminate[0].previous_offset = reg_eliminate[0].max_offset
-       = reg_eliminate[0].offset = reg_eliminate[0].initial_offset;
-#endif
-
-      num_not_at_initial_offset = 0;
-
-      bzero ((char *) &offsets_known_at[get_first_label_num ()], num_labels);
-
-      /* Set a known offset for each forced label to be at the initial offset
-        of each elimination.  We do this because we assume that all
-        computed jumps occur from a location where each elimination is
-        at its initial offset.  */
-
-      for (x = forced_labels; x; x = XEXP (x, 1))
-       if (XEXP (x, 0))
-         set_label_offsets (XEXP (x, 0), NULL_RTX, 1);
+      set_initial_elim_offsets ();
+      set_initial_label_offsets ();
 
       /* For each pseudo register that has an equivalent location defined,
         try to eliminate any eliminable registers (such as the frame pointer)
@@ -997,1188 +879,1119 @@ reload (first, global, dumpfile)
                reg_equiv_memory_loc[i] = 0;
                reg_equiv_init[i] = 0;
                alter_reg (i, -1);
-               something_changed = 1;
              }
          }
 
-      /* If we allocated another pseudo to the stack, redo elimination
-        bookkeeping.  */
-      if (something_changed)
-       continue;
+      if (caller_save_needed)
+       setup_save_areas ();
 
-      /* If caller-saves needs a group, initialize the group to include
-        the size and mode required for caller-saves.  */
+      /* If we allocated another stack slot, redo elimination bookkeeping.  */
+      if (starting_frame_size != get_frame_size ())
+       continue;
 
-      if (caller_save_group_size > 1)
+      if (caller_save_needed)
        {
-         group_mode[(int) caller_save_spill_class] = Pmode;
-         group_size[(int) caller_save_spill_class] = caller_save_group_size;
+         save_call_clobbered_regs ();
+         /* That might have allocated new insn_chain structures.  */
+         reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
        }
 
-      /* Compute the most additional registers needed by any instruction.
-        Collect information separately for each class of regs.  */
+      calculate_needs_all_insns (global);
 
-      for (insn = first; insn; insn = NEXT_INSN (insn))
-       {
-         if (global && this_block + 1 < n_basic_blocks
-             && insn == basic_block_head[this_block+1])
-           ++this_block;
+      CLEAR_REG_SET (spilled_pseudos);
+      did_spill = 0;
 
-         /* If this is a label, a JUMP_INSN, or has REG_NOTES (which
-            might include REG_LABEL), we need to see what effects this
-            has on the known offsets at labels.  */
+      something_changed = 0;
 
-         if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN
-             || (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
-                 && REG_NOTES (insn) != 0))
-           set_label_offsets (insn, insn, 0);
+      /* If we allocated any new memory locations, make another pass
+        since it might have changed elimination offsets.  */
+      if (starting_frame_size != get_frame_size ())
+       something_changed = 1;
 
-         if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+      {
+       HARD_REG_SET to_spill;
+       CLEAR_HARD_REG_SET (to_spill);
+       update_eliminables (&to_spill);
+       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+         if (TEST_HARD_REG_BIT (to_spill, i))
            {
-             /* Nonzero means don't use a reload reg that overlaps
-                the place where a function value can be returned.  */
-             rtx avoid_return_reg = 0;
-
-             rtx old_body = PATTERN (insn);
-             int old_code = INSN_CODE (insn);
-             rtx old_notes = REG_NOTES (insn);
-             int did_elimination = 0;
-
-             /* To compute the number of reload registers of each class 
-                needed for an insn, we must simulate what choose_reload_regs
-                can do.  We do this by splitting an insn into an "input" and
-                an "output" part.  RELOAD_OTHER reloads are used in both. 
-                The input part uses those reloads, RELOAD_FOR_INPUT reloads,
-                which must be live over the entire input section of reloads,
-                and the maximum of all the RELOAD_FOR_INPUT_ADDRESS and
-                RELOAD_FOR_OPERAND_ADDRESS reloads, which conflict with the
-                inputs.
-
-                The registers needed for output are RELOAD_OTHER and
-                RELOAD_FOR_OUTPUT, which are live for the entire output
-                portion, and the maximum of all the RELOAD_FOR_OUTPUT_ADDRESS
-                reloads for each operand.
-
-                The total number of registers needed is the maximum of the
-                inputs and outputs.  */
-
-             struct needs
-               {
-                 /* [0] is normal, [1] is nongroup.  */
-                 int regs[2][N_REG_CLASSES];
-                 int groups[N_REG_CLASSES];
-               };
-
-             /* Each `struct needs' corresponds to one RELOAD_... type.  */
-             struct {
-               struct needs other;
-               struct needs input;
-               struct needs output;
-               struct needs insn;
-               struct needs other_addr;
-               struct needs op_addr;
-               struct needs op_addr_reload;
-               struct needs in_addr[MAX_RECOG_OPERANDS];
-               struct needs in_addr_addr[MAX_RECOG_OPERANDS];
-               struct needs out_addr[MAX_RECOG_OPERANDS];
-               struct needs out_addr_addr[MAX_RECOG_OPERANDS];
-             } insn_needs;
-
-             /* If needed, eliminate any eliminable registers.  */
-             if (num_eliminable)
-               did_elimination = eliminate_regs_in_insn (insn, 0);
-
-             /* Set avoid_return_reg if this is an insn
-                that might use the value of a function call.  */
-             if (SMALL_REGISTER_CLASSES && GET_CODE (insn) == CALL_INSN)
-               {
-                 if (GET_CODE (PATTERN (insn)) == SET)
-                   after_call = SET_DEST (PATTERN (insn));
-                 else if (GET_CODE (PATTERN (insn)) == PARALLEL
-                          && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
-                   after_call = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
-                 else
-                   after_call = 0;
-               }
-             else if (SMALL_REGISTER_CLASSES && after_call != 0
-                      && !(GET_CODE (PATTERN (insn)) == SET
-                           && SET_DEST (PATTERN (insn)) == stack_pointer_rtx)
-                      && GET_CODE (PATTERN (insn)) != USE)
-               {
-                 if (reg_referenced_p (after_call, PATTERN (insn)))
-                   avoid_return_reg = after_call;
-                 after_call = 0;
-               }
+             spill_hard_reg (i, dumpfile, 1);
+             did_spill = 1;
+           }
+      }
 
-             /* Analyze the instruction.  */
-             find_reloads (insn, 0, spill_indirect_levels, global,
-                           spill_reg_order);
+      CLEAR_HARD_REG_SET (used_spill_regs);
+      /* Try to satisfy the needs for each insn.  */
+      for (chain = insns_need_reload; chain != 0;
+          chain = chain->next_need_reload)
+       find_reload_regs (chain, dumpfile);
 
-             /* Remember for later shortcuts which insns had any reloads or
-                register eliminations.
+      if (failure)
+       goto failed;
 
-                One might think that it would be worthwhile to mark insns
-                that need register replacements but not reloads, but this is
-                not safe because find_reloads may do some manipulation of
-                the insn (such as swapping commutative operands), which would
-                be lost when we restore the old pattern after register
-                replacement.  So the actions of find_reloads must be redone in
-                subsequent passes or in reload_as_needed.
+      if (insns_need_reload != 0 || did_spill)
+       something_changed |= finish_spills (global, dumpfile);
 
-                However, it is safe to mark insns that need reloads
-                but not register replacement.  */
+      if (! something_changed)
+       break;
 
-             PUT_MODE (insn, (did_elimination ? QImode
-                              : n_reloads ? HImode
-                              : GET_MODE (insn) == DImode ? DImode
-                              : VOIDmode));
+      if (caller_save_needed)
+       delete_caller_save_insns ();
+    }
 
-             /* Discard any register replacements done.  */
-             if (did_elimination)
-               {
-                 obstack_free (&reload_obstack, reload_firstobj);
-                 PATTERN (insn) = old_body;
-                 INSN_CODE (insn) = old_code;
-                 REG_NOTES (insn) = old_notes;
-                 something_needs_elimination = 1;
-               }
+  /* If global-alloc was run, notify it of any register eliminations we have
+     done.  */
+  if (global)
+    for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+      if (ep->can_eliminate)
+       mark_elimination (ep->from, ep->to);
 
-             /* If this insn has no reloads, we need not do anything except
-                in the case of a CALL_INSN when we have caller-saves and
-                caller-save needs reloads.  */
+  /* If a pseudo has no hard reg, delete the insns that made the equivalence.
+     If that insn didn't set the register (i.e., it copied the register to
+     memory), just delete that insn instead of the equivalencing insn plus
+     anything now dead.  If we call delete_dead_insn on that insn, we may
+     delete the insn that actually sets the register if the register die
+     there and that is incorrect.  */
 
-             if (n_reloads == 0
-                 && ! (GET_CODE (insn) == CALL_INSN
-                       && caller_save_spill_class != NO_REGS))
-               continue;
+  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+    if (reg_renumber[i] < 0 && reg_equiv_init[i] != 0
+       && GET_CODE (reg_equiv_init[i]) != NOTE)
+      {
+       if (reg_set_p (regno_reg_rtx[i], PATTERN (reg_equiv_init[i])))
+         delete_dead_insn (reg_equiv_init[i]);
+       else
+         {
+           PUT_CODE (reg_equiv_init[i], NOTE);
+           NOTE_SOURCE_FILE (reg_equiv_init[i]) = 0;
+           NOTE_LINE_NUMBER (reg_equiv_init[i]) = NOTE_INSN_DELETED;
+         }
+      }
 
-             something_needs_reloads = 1;
-             bzero ((char *) &insn_needs, sizeof insn_needs);
+  /* Use the reload registers where necessary
+     by generating move instructions to move the must-be-register
+     values into or out of the reload registers.  */
 
-             /* Count each reload once in every class
-                containing the reload's own class.  */
+  if (insns_need_reload != 0 || something_needs_elimination
+      || something_needs_operands_changed)
+    {
+      int old_frame_size = get_frame_size ();
 
-             for (i = 0; i < n_reloads; i++)
-               {
-                 register enum reg_class *p;
-                 enum reg_class class = reload_reg_class[i];
-                 int size;
-                 enum machine_mode mode;
-                 struct needs *this_needs;
-
-                 /* Don't count the dummy reloads, for which one of the
-                    regs mentioned in the insn can be used for reloading.
-                    Don't count optional reloads.
-                    Don't count reloads that got combined with others.  */
-                 if (reload_reg_rtx[i] != 0
-                     || reload_optional[i] != 0
-                     || (reload_out[i] == 0 && reload_in[i] == 0
-                         && ! reload_secondary_p[i]))
-                   continue;
-
-                 /* Show that a reload register of this class is needed
-                    in this basic block.  We do not use insn_needs and
-                    insn_groups because they are overly conservative for
-                    this purpose.  */
-                 if (global && ! basic_block_needs[(int) class][this_block])
-                   {
-                     basic_block_needs[(int) class][this_block] = 1;
-                     new_basic_block_needs = 1;
-                   }
+      reload_as_needed (global);
 
-                 mode = reload_inmode[i];
-                 if (GET_MODE_SIZE (reload_outmode[i]) > GET_MODE_SIZE (mode))
-                   mode = reload_outmode[i];
-                 size = CLASS_MAX_NREGS (class, mode);
+      if (old_frame_size != get_frame_size ())
+       abort ();
 
-                 /* Decide which time-of-use to count this reload for.  */
-                 switch (reload_when_needed[i])
-                   {
-                   case RELOAD_OTHER:
-                     this_needs = &insn_needs.other;
-                     break;
-                   case RELOAD_FOR_INPUT:
-                     this_needs = &insn_needs.input;
-                     break;
-                   case RELOAD_FOR_OUTPUT:
-                     this_needs = &insn_needs.output;
-                     break;
-                   case RELOAD_FOR_INSN:
-                     this_needs = &insn_needs.insn;
-                     break;
-                   case RELOAD_FOR_OTHER_ADDRESS:
-                     this_needs = &insn_needs.other_addr;
-                     break;
-                   case RELOAD_FOR_INPUT_ADDRESS:
-                     this_needs = &insn_needs.in_addr[reload_opnum[i]];
-                     break;
-                   case RELOAD_FOR_INPADDR_ADDRESS:
-                     this_needs = &insn_needs.in_addr_addr[reload_opnum[i]];
-                     break;
-                   case RELOAD_FOR_OUTPUT_ADDRESS:
-                     this_needs = &insn_needs.out_addr[reload_opnum[i]];
-                     break;
-                   case RELOAD_FOR_OUTADDR_ADDRESS:
-                     this_needs = &insn_needs.out_addr_addr[reload_opnum[i]];
-                     break;
-                   case RELOAD_FOR_OPERAND_ADDRESS:
-                     this_needs = &insn_needs.op_addr;
-                     break;
-                   case RELOAD_FOR_OPADDR_ADDR:
-                     this_needs = &insn_needs.op_addr_reload;
-                     break;
-                   }
+      if (num_eliminable)
+       verify_initial_elim_offsets ();
+    }
 
-                 if (size > 1)
-                   {
-                     enum machine_mode other_mode, allocate_mode;
-
-                     /* Count number of groups needed separately from
-                        number of individual regs needed.  */
-                     this_needs->groups[(int) class]++;
-                     p = reg_class_superclasses[(int) class];
-                     while (*p != LIM_REG_CLASSES)
-                       this_needs->groups[(int) *p++]++;
-
-                     /* Record size and mode of a group of this class.  */
-                     /* If more than one size group is needed,
-                        make all groups the largest needed size.  */
-                     if (group_size[(int) class] < size)
-                       {
-                         other_mode = group_mode[(int) class];
-                         allocate_mode = mode;
+  /* If we were able to eliminate the frame pointer, show that it is no
+     longer live at the start of any basic block.  If it ls live by
+     virtue of being in a pseudo, that pseudo will be marked live
+     and hence the frame pointer will be known to be live via that
+     pseudo.  */
 
-                         group_size[(int) class] = size;
-                         group_mode[(int) class] = mode;
-                       }
-                     else
-                       {
-                         other_mode = mode;
-                         allocate_mode = group_mode[(int) class];
-                       }
+  if (! frame_pointer_needed)
+    for (i = 0; i < n_basic_blocks; i++)
+      CLEAR_REGNO_REG_SET (basic_block_live_at_start[i],
+                          HARD_FRAME_POINTER_REGNUM);
 
-                     /* Crash if two dissimilar machine modes both need
-                        groups of consecutive regs of the same class.  */
+  /* Come here (with failure set nonzero) if we can't get enough spill regs
+     and we decide not to abort about it.  */
+ failed:
 
-                     if (other_mode != VOIDmode && other_mode != allocate_mode
-                         && ! modes_equiv_for_class_p (allocate_mode,
-                                                       other_mode, class))
-                       fatal_insn ("Two dissimilar machine modes both need groups of consecutive regs of the same class",
-                                   insn);
-                   }
-                 else if (size == 1)
-                   {
-                     this_needs->regs[reload_nongroup[i]][(int) class] += 1;
-                     p = reg_class_superclasses[(int) class];
-                     while (*p != LIM_REG_CLASSES)
-                       this_needs->regs[reload_nongroup[i]][(int) *p++] += 1;
-                   }
-                 else
-                   abort ();
-               }
+  reload_in_progress = 0;
 
-             /* All reloads have been counted for this insn;
-                now merge the various times of use.
-                This sets insn_needs, etc., to the maximum total number
-                of registers needed at any point in this insn.  */
+  /* Now eliminate all pseudo regs by modifying them into
+     their equivalent memory references.
+     The REG-rtx's for the pseudos are modified in place,
+     so all insns that used to refer to them now refer to memory.
 
-             for (i = 0; i < N_REG_CLASSES; i++)
-               {
-                 int in_max, out_max;
+     For a reg that has a reg_equiv_address, all those insns
+     were changed by reloading so that no insns refer to it any longer;
+     but the DECL_RTL of a variable decl may refer to it,
+     and if so this causes the debugging info to mention the variable.  */
 
-                 /* Compute normal and nongroup needs.  */
-                 for (j = 0; j <= 1; j++)
-                   {
-                     for (in_max = 0, out_max = 0, k = 0;
-                          k < reload_n_operands; k++)
-                       {
-                         in_max
-                           = MAX (in_max,
-                                  (insn_needs.in_addr[k].regs[j][i]
-                                   + insn_needs.in_addr_addr[k].regs[j][i]));
-                         out_max
-                           = MAX (out_max, insn_needs.out_addr[k].regs[j][i]);
-                         out_max
-                           = MAX (out_max,
-                                  insn_needs.out_addr_addr[k].regs[j][i]);
-                       }
+  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+    {
+      rtx addr = 0;
+      int in_struct = 0;
+      int is_readonly = 0;
 
-                     /* RELOAD_FOR_INSN reloads conflict with inputs, outputs,
-                        and operand addresses but not things used to reload
-                        them.  Similarly, RELOAD_FOR_OPERAND_ADDRESS reloads
-                        don't conflict with things needed to reload inputs or
-                        outputs.  */
+      if (reg_equiv_memory_loc[i])
+       {
+         in_struct = MEM_IN_STRUCT_P (reg_equiv_memory_loc[i]);
+         is_readonly = RTX_UNCHANGING_P (reg_equiv_memory_loc[i]);
+       }
 
-                     in_max = MAX (MAX (insn_needs.op_addr.regs[j][i],
-                                        insn_needs.op_addr_reload.regs[j][i]),
-                                   in_max);
+      if (reg_equiv_mem[i])
+       addr = XEXP (reg_equiv_mem[i], 0);
 
-                     out_max = MAX (out_max, insn_needs.insn.regs[j][i]);
+      if (reg_equiv_address[i])
+       addr = reg_equiv_address[i];
 
-                     insn_needs.input.regs[j][i]
-                       = MAX (insn_needs.input.regs[j][i]
-                              + insn_needs.op_addr.regs[j][i]
-                              + insn_needs.insn.regs[j][i],
-                              in_max + insn_needs.input.regs[j][i]);
+      if (addr)
+       {
+         if (reg_renumber[i] < 0)
+           {
+             rtx reg = regno_reg_rtx[i];
+             XEXP (reg, 0) = addr;
+             REG_USERVAR_P (reg) = 0;
+             RTX_UNCHANGING_P (reg) = is_readonly;
+             MEM_IN_STRUCT_P (reg) = in_struct;
+             /* We have no alias information about this newly created
+                MEM.  */
+             MEM_ALIAS_SET (reg) = 0;
+             PUT_CODE (reg, MEM);
+           }
+         else if (reg_equiv_mem[i])
+           XEXP (reg_equiv_mem[i], 0) = addr;
+       }
+    }
 
-                     insn_needs.output.regs[j][i] += out_max;
-                     insn_needs.other.regs[j][i]
-                       += MAX (MAX (insn_needs.input.regs[j][i],
-                                    insn_needs.output.regs[j][i]),
-                               insn_needs.other_addr.regs[j][i]);
+  /* Make a pass over all the insns and delete all USEs which we inserted
+     only to tag a REG_EQUAL note on them.  Remove all REG_DEAD and REG_UNUSED
+     notes.  Delete all CLOBBER insns and simplify (subreg (reg)) operands.  */
 
-                   }
+  for (insn = first; insn; insn = NEXT_INSN (insn))
+    if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+      {
+       rtx *pnote;
 
-                 /* Now compute group needs.  */
-                 for (in_max = 0, out_max = 0, j = 0;
-                      j < reload_n_operands; j++)
-                   {
-                     in_max = MAX (in_max, insn_needs.in_addr[j].groups[i]);
-                     in_max = MAX (in_max,
-                                    insn_needs.in_addr_addr[j].groups[i]);
-                     out_max
-                       = MAX (out_max, insn_needs.out_addr[j].groups[i]);
-                     out_max
-                       = MAX (out_max, insn_needs.out_addr_addr[j].groups[i]);
-                   }
+       if ((GET_CODE (PATTERN (insn)) == USE
+            && find_reg_note (insn, REG_EQUAL, NULL_RTX))
+           || GET_CODE (PATTERN (insn)) == CLOBBER)
+         {
+           PUT_CODE (insn, NOTE);
+           NOTE_SOURCE_FILE (insn) = 0;
+           NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+           continue;
+         }
 
-                 in_max = MAX (MAX (insn_needs.op_addr.groups[i],
-                                    insn_needs.op_addr_reload.groups[i]),
-                               in_max);
-                 out_max = MAX (out_max, insn_needs.insn.groups[i]);
-
-                 insn_needs.input.groups[i]
-                   = MAX (insn_needs.input.groups[i]
-                          + insn_needs.op_addr.groups[i]
-                          + insn_needs.insn.groups[i],
-                          in_max + insn_needs.input.groups[i]);
-
-                 insn_needs.output.groups[i] += out_max;
-                 insn_needs.other.groups[i]
-                   += MAX (MAX (insn_needs.input.groups[i],
-                                insn_needs.output.groups[i]),
-                           insn_needs.other_addr.groups[i]);
-               }
+       pnote = &REG_NOTES (insn);
+       while (*pnote != 0)
+         {
+           if (REG_NOTE_KIND (*pnote) == REG_DEAD
+               || REG_NOTE_KIND (*pnote) == REG_UNUSED)
+             *pnote = XEXP (*pnote, 1);
+           else
+             pnote = &XEXP (*pnote, 1);
+         }
 
-             /* If this is a CALL_INSN and caller-saves will need
-                a spill register, act as if the spill register is
-                needed for this insn.   However, the spill register
-                can be used by any reload of this insn, so we only
-                need do something if no need for that class has
-                been recorded.
+       /* And simplify (subreg (reg)) if it appears as an operand.  */
+       cleanup_subreg_operands (insn);
+      }
 
-                The assumption that every CALL_INSN will trigger a
-                caller-save is highly conservative, however, the number
-                of cases where caller-saves will need a spill register but
-                a block containing a CALL_INSN won't need a spill register
-                of that class should be quite rare.
+  /* If we are doing stack checking, give a warning if this function's
+     frame size is larger than we expect.  */
+  if (flag_stack_check && ! STACK_CHECK_BUILTIN)
+    {
+      HOST_WIDE_INT size = get_frame_size () + STACK_CHECK_FIXED_FRAME_SIZE;
 
-                If a group is needed, the size and mode of the group will
-                have been set up at the beginning of this loop.  */
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+       if (regs_ever_live[i] && ! fixed_regs[i] && call_used_regs[i])
+         size += UNITS_PER_WORD;
 
-             if (GET_CODE (insn) == CALL_INSN
-                 && caller_save_spill_class != NO_REGS)
-               {
-                 /* See if this register would conflict with any reload that
-                    needs a group or any reload that needs a nongroup.  */
-                 int nongroup_need = 0;
-                 int *caller_save_needs;
-
-                 for (j = 0; j < n_reloads; j++)
-                   if (reg_classes_intersect_p (caller_save_spill_class,
-                                                reload_reg_class[j])
-                       && ((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_nongroup[j]))
-                     {
-                       nongroup_need = 1;
-                       break;
-                     }
+      if (size > STACK_CHECK_MAX_FRAME_SIZE)
+       warning ("frame size too large for reliable stack checking");
+    }
 
-                 caller_save_needs 
-                   = (caller_save_group_size > 1
-                      ? insn_needs.other.groups
-                      : insn_needs.other.regs[nongroup_need]); 
+  /* Indicate that we no longer have known memory locations or constants.  */
+  if (reg_equiv_constant)
+    free (reg_equiv_constant);
+  reg_equiv_constant = 0;
+  if (reg_equiv_memory_loc)
+    free (reg_equiv_memory_loc);
+  reg_equiv_memory_loc = 0;
 
-                 if (caller_save_needs[(int) caller_save_spill_class] == 0)
-                   {
-                     register enum reg_class *p
-                       = reg_class_superclasses[(int) caller_save_spill_class];
+  if (real_known_ptr)
+    free (real_known_ptr);
+  if (real_at_ptr)
+    free (real_at_ptr);
 
-                     caller_save_needs[(int) caller_save_spill_class]++;
+  free (reg_equiv_mem);
+  free (reg_equiv_init);
+  free (reg_equiv_address);
+  free (reg_max_ref_width);
+  free (reg_old_renumber);
+  free (pseudo_previous_regs);
+  free (pseudo_forbidden_regs);
 
-                     while (*p != LIM_REG_CLASSES)
-                       caller_save_needs[(int) *p++] += 1;
-                   }
+  FREE_REG_SET (spilled_pseudos);
 
-                 /* Show that this basic block will need a register of
-                   this class.  */
+  CLEAR_HARD_REG_SET (used_spill_regs);
+  for (i = 0; i < n_spills; i++)
+    SET_HARD_REG_BIT (used_spill_regs, spill_regs[i]);
 
-                 if (global
-                     && ! (basic_block_needs[(int) caller_save_spill_class]
-                           [this_block]))
-                   {
-                     basic_block_needs[(int) caller_save_spill_class]
-                       [this_block] = 1;
-                     new_basic_block_needs = 1;
-                   }
-               }
+  /* Free all the insn_chain structures at once.  */
+  obstack_free (&reload_obstack, reload_startobj);
+  unused_insn_chains = 0;
 
-             /* If this insn stores the value of a function call,
-                and that value is in a register that has been spilled,
-                and if the insn needs a reload in a class
-                that might use that register as the reload register,
-                then add add an extra need in that class.
-                This makes sure we have a register available that does
-                not overlap the return value.  */
+  return failure;
+}
 
-             if (SMALL_REGISTER_CLASSES && avoid_return_reg)
-               {
-                 int regno = REGNO (avoid_return_reg);
-                 int nregs
-                   = HARD_REGNO_NREGS (regno, GET_MODE (avoid_return_reg));
-                 int r;
-                 int basic_needs[N_REG_CLASSES], basic_groups[N_REG_CLASSES];
-
-                 /* First compute the "basic needs", which counts a
-                    need only in the smallest class in which it
-                    is required.  */
-
-                 bcopy ((char *) insn_needs.other.regs[0],
-                        (char *) basic_needs, sizeof basic_needs);
-                 bcopy ((char *) insn_needs.other.groups,
-                        (char *) basic_groups, sizeof basic_groups);
-
-                 for (i = 0; i < N_REG_CLASSES; i++)
-                   {
-                     enum reg_class *p;
+/* Yet another special case.  Unfortunately, reg-stack forces people to
+   write incorrect clobbers in asm statements.  These clobbers must not
+   cause the register to appear in bad_spill_regs, otherwise we'll call
+   fatal_insn later.  We clear the corresponding regnos in the live
+   register sets to avoid this.
+   The whole thing is rather sick, I'm afraid.  */
+static void
+maybe_fix_stack_asms ()
+{
+#ifdef STACK_REGS
+  char *constraints[MAX_RECOG_OPERANDS];
+  enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
+  struct insn_chain *chain;
 
-                     if (basic_needs[i] >= 0)
-                       for (p = reg_class_superclasses[i];
-                            *p != LIM_REG_CLASSES; p++)
-                         basic_needs[(int) *p] -= basic_needs[i];
+  for (chain = reload_insn_chain; chain != 0; chain = chain->next)
+    {
+      int i, noperands;
+      HARD_REG_SET clobbered, allowed;
+      rtx pat;
 
-                     if (basic_groups[i] >= 0)
-                       for (p = reg_class_superclasses[i];
-                            *p != LIM_REG_CLASSES; p++)
-                         basic_groups[(int) *p] -= basic_groups[i];
-                   }
+      if (GET_RTX_CLASS (GET_CODE (chain->insn)) != 'i'
+         || (noperands = asm_noperands (PATTERN (chain->insn))) < 0)
+       continue;
+      pat = PATTERN (chain->insn);
+      if (GET_CODE (pat) != PARALLEL)
+       continue;
 
-                 /* Now count extra regs if there might be a conflict with
-                    the return value register.  */
+      CLEAR_HARD_REG_SET (clobbered);
+      CLEAR_HARD_REG_SET (allowed);
 
-                 for (r = regno; r < regno + nregs; r++)
-                   if (spill_reg_order[r] >= 0)
-                     for (i = 0; i < N_REG_CLASSES; i++)
-                       if (TEST_HARD_REG_BIT (reg_class_contents[i], r))
-                         {
-                           if (basic_needs[i] > 0)
-                             {
-                               enum reg_class *p;
+      /* First, make a mask of all stack regs that are clobbered.  */
+      for (i = 0; i < XVECLEN (pat, 0); i++)
+       {
+         rtx t = XVECEXP (pat, 0, i);
+         if (GET_CODE (t) == CLOBBER && STACK_REG_P (XEXP (t, 0)))
+           SET_HARD_REG_BIT (clobbered, REGNO (XEXP (t, 0)));
+       }
 
-                               insn_needs.other.regs[0][i]++;
-                               p = reg_class_superclasses[i];
-                               while (*p != LIM_REG_CLASSES)
-                                 insn_needs.other.regs[0][(int) *p++]++;
-                             }
-                           if (basic_groups[i] > 0)
-                             {
-                               enum reg_class *p;
+      /* Get the operand values and constraints out of the insn.  */
+      decode_asm_operands (pat, recog_operand, recog_operand_loc,
+                          constraints, operand_mode);
 
-                               insn_needs.other.groups[i]++;
-                               p = reg_class_superclasses[i];
-                               while (*p != LIM_REG_CLASSES)
-                                 insn_needs.other.groups[(int) *p++]++;
-                             }
-                         }
-               }
+      /* For every operand, see what registers are allowed.  */
+      for (i = 0; i < noperands; i++)
+       {
+         char *p = constraints[i];
+         /* For every alternative, we compute the class of registers allowed
+            for reloading in CLS, and merge its contents into the reg set
+            ALLOWED.  */
+         int cls = (int) NO_REGS;
 
-             /* For each class, collect maximum need of any insn.  */
+         for (;;)
+           {
+             char c = *p++;
 
-             for (i = 0; i < N_REG_CLASSES; i++)
+             if (c == '\0' || c == ',' || c == '#')
                {
-                 if (max_needs[i] < insn_needs.other.regs[0][i])
-                   {
-                     max_needs[i] = insn_needs.other.regs[0][i];
-                     max_needs_insn[i] = insn;
-                   }
-                 if (max_groups[i] < insn_needs.other.groups[i])
-                   {
-                     max_groups[i] = insn_needs.other.groups[i];
-                     max_groups_insn[i] = insn;
-                   }
-                 if (max_nongroups[i] < insn_needs.other.regs[1][i])
-                   {
-                     max_nongroups[i] = insn_needs.other.regs[1][i];
-                     max_nongroups_insn[i] = insn;
-                   }
+                 /* End of one alternative - mark the regs in the current
+                    class, and reset the class.  */
+                 IOR_HARD_REG_SET (allowed, reg_class_contents[cls]);
+                 cls = NO_REGS;
+                 if (c == '#')
+                   do {
+                     c = *p++;
+                   } while (c != '\0' && c != ',');
+                 if (c == '\0')
+                   break;
+                 continue;
                }
-           }
-         /* Note that there is a continue statement above.  */
-       }
 
-      /* If we allocated any new memory locations, make another pass
-        since it might have changed elimination offsets.  */
-      if (starting_frame_size != get_frame_size ())
-       something_changed = 1;
+             switch (c)
+               {
+               case '=': case '+': case '*': case '%': case '?': case '!':
+               case '0': case '1': case '2': case '3': case '4': case 'm':
+               case '<': case '>': case 'V': case 'o': case '&': case 'E':
+               case 'F': case 's': case 'i': case 'n': case 'X': case 'I':
+               case 'J': case 'K': case 'L': case 'M': case 'N': case 'O':
+               case 'P':
+#ifdef EXTRA_CONSTRAINT
+               case 'Q': case 'R': case 'S': case 'T': case 'U':
+#endif
+                 break;
 
-      if (dumpfile)
-       for (i = 0; i < N_REG_CLASSES; i++)
-         {
-           if (max_needs[i] > 0)
-             fprintf (dumpfile,
-                        ";; Need %d reg%s of class %s (for insn %d).\n",
-                      max_needs[i], max_needs[i] == 1 ? "" : "s",
-                      reg_class_names[i], INSN_UID (max_needs_insn[i]));
-           if (max_nongroups[i] > 0)
-             fprintf (dumpfile,
-                      ";; Need %d nongroup reg%s of class %s (for insn %d).\n",
-                      max_nongroups[i], max_nongroups[i] == 1 ? "" : "s",
-                      reg_class_names[i], INSN_UID (max_nongroups_insn[i]));
-           if (max_groups[i] > 0)
-             fprintf (dumpfile,
-                      ";; Need %d group%s (%smode) of class %s (for insn %d).\n",
-                      max_groups[i], max_groups[i] == 1 ? "" : "s",
-                      mode_name[(int) group_mode[i]],
-                      reg_class_names[i], INSN_UID (max_groups_insn[i]));
-         }
-                        
-      /* If we have caller-saves, set up the save areas and see if caller-save
-        will need a spill register.  */
+               case 'p':
+                 cls = (int) reg_class_subunion[cls][(int) BASE_REG_CLASS];
+                 break;
 
-      if (caller_save_needed)
-       {
-         /* Set the offsets for setup_save_areas.  */
-         for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
-              ep++)
-           ep->previous_offset = ep->max_offset;
+               case 'g':
+               case 'r':
+                 cls = (int) reg_class_subunion[cls][(int) GENERAL_REGS];
+                 break;
 
-         if ( ! setup_save_areas (&something_changed)
-             && caller_save_spill_class  == NO_REGS)
-           {
-             /* The class we will need depends on whether the machine
-                supports the sum of two registers for an address; see
-             find_address_reloads for details.  */
-
-             caller_save_spill_class
-               = double_reg_address_ok ? INDEX_REG_CLASS : BASE_REG_CLASS;
-             caller_save_group_size
-               = CLASS_MAX_NREGS (caller_save_spill_class, Pmode);
-             something_changed = 1;
+               default:
+                 cls = (int) reg_class_subunion[cls][(int) REG_CLASS_FROM_LETTER (c)];
+               
+               }
            }
        }
+      /* Those of the registers which are clobbered, but allowed by the
+        constraints, must be usable as reload registers.  So clear them
+        out of the life information.  */
+      AND_HARD_REG_SET (allowed, clobbered);
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+       if (TEST_HARD_REG_BIT (allowed, i))
+         {
+           CLEAR_REGNO_REG_SET (chain->live_before, i);
+           CLEAR_REGNO_REG_SET (chain->live_after, i);
+         }
+    }
 
-      /* See if anything that happened changes which eliminations are valid.
-        For example, on the Sparc, whether or not the frame pointer can
-        be eliminated can depend on what registers have been used.  We need
-        not check some conditions again (such as flag_omit_frame_pointer)
-        since they can't have changed.  */
-
-      for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-       if ((ep->from == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED)
-#ifdef ELIMINABLE_REGS
-           || ! CAN_ELIMINATE (ep->from, ep->to)
 #endif
-           )
-         ep->can_eliminate = 0;
+}
 
-      /* Look for the case where we have discovered that we can't replace
-        register A with register B and that means that we will now be
-        trying to replace register A with register C.  This means we can
-        no longer replace register C with register B and we need to disable
-        such an elimination, if it exists.  This occurs often with A == ap,
-        B == sp, and C == fp.  */
+\f
+/* Walk the chain of insns, and determine for each whether it needs reloads
+   and/or eliminations.  Build the corresponding insns_need_reload list, and
+   set something_needs_elimination as appropriate.  */
+static void
+calculate_needs_all_insns (global)
+     int global;
+{
+  struct insn_chain **pprev_reload = &insns_need_reload;
+  struct insn_chain **pchain;
 
-      for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+  something_needs_elimination = 0;
+
+  for (pchain = &reload_insn_chain; *pchain != 0; pchain = &(*pchain)->next)
+    {
+      rtx insn;
+      struct insn_chain *chain;
+
+      chain = *pchain;
+      insn = chain->insn;
+
+      /* If this is a label, a JUMP_INSN, or has REG_NOTES (which might
+        include REG_LABEL), we need to see what effects this has on the
+        known offsets at labels.  */
+
+      if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN
+         || (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+             && REG_NOTES (insn) != 0))
+       set_label_offsets (insn, insn, 0);
+
+      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
        {
-         struct elim_table *op;
-         register int new_to = -1;
+         rtx old_body = PATTERN (insn);
+         int old_code = INSN_CODE (insn);
+         rtx old_notes = REG_NOTES (insn);
+         int did_elimination = 0;
+         int operands_changed = 0;
+
+         /* If needed, eliminate any eliminable registers.  */
+         if (num_eliminable)
+           did_elimination = eliminate_regs_in_insn (insn, 0);
+
+         /* Analyze the instruction.  */
+         operands_changed = find_reloads (insn, 0, spill_indirect_levels,
+                                          global, spill_reg_order);
+
+         /* If a no-op set needs more than one reload, this is likely
+            to be something that needs input address reloads.  We
+            can't get rid of this cleanly later, and it is of no use
+            anyway, so discard it now.
+            We only do this when expensive_optimizations is enabled,
+            since this complements reload inheritance / output
+            reload deletion, and it can make debugging harder.  */
+         if (flag_expensive_optimizations && n_reloads > 1)
+           {
+             rtx set = single_set (insn);
+             if (set
+                 && SET_SRC (set) == SET_DEST (set)
+                 && GET_CODE (SET_SRC (set)) == REG
+                 && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER)
+               {
+                 PUT_CODE (insn, NOTE);
+                 NOTE_SOURCE_FILE (insn) = 0;
+                 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+                 continue;
+               }
+           }
+         if (num_eliminable)
+           update_eliminable_offsets ();
 
-         if (! ep->can_eliminate && ep->can_eliminate_previous)
+         /* Remember for later shortcuts which insns had any reloads or
+            register eliminations.  */
+         chain->need_elim = did_elimination;
+         chain->need_reload = n_reloads > 0;
+         chain->need_operand_change = operands_changed;
+
+         /* Discard any register replacements done.  */
+         if (did_elimination)
            {
-             /* Find the current elimination for ep->from, if there is a
-                new one.  */
-             for (op = reg_eliminate;
-                  op < &reg_eliminate[NUM_ELIMINABLE_REGS]; op++)
-               if (op->from == ep->from && op->can_eliminate)
-                 {
-                   new_to = op->to;
-                   break;
-                 }
+             obstack_free (&reload_obstack, reload_firstobj);
+             PATTERN (insn) = old_body;
+             INSN_CODE (insn) = old_code;
+             REG_NOTES (insn) = old_notes;
+             something_needs_elimination = 1;
+           }
+
+         something_needs_operands_changed |= operands_changed;
 
-             /* See if there is an elimination of NEW_TO -> EP->TO.  If so,
-                disable it.  */
-             for (op = reg_eliminate;
-                  op < &reg_eliminate[NUM_ELIMINABLE_REGS]; op++)
-               if (op->from == new_to && op->to == ep->to)
-                 op->can_eliminate = 0;
+         if (n_reloads != 0)
+           {
+             *pprev_reload = chain;
+             pprev_reload = &chain->next_need_reload;
+
+             calculate_needs (chain);
            }
        }
+    }
+  *pprev_reload = 0;
+}
 
-      /* See if any registers that we thought we could eliminate the previous
-        time are no longer eliminable.  If so, something has changed and we
-        must spill the register.  Also, recompute the number of eliminable
-        registers and see if the frame pointer is needed; it is if there is
-        no elimination of the frame pointer that we can perform.  */
+/* Compute the most additional registers needed by one instruction,
+   given by CHAIN.  Collect information separately for each class of regs.
 
-      frame_pointer_needed = 1;
-      for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+   To compute the number of reload registers of each class needed for an
+   insn, we must simulate what choose_reload_regs can do.  We do this by
+   splitting an insn into an "input" and an "output" part.  RELOAD_OTHER
+   reloads are used in both.  The input part uses those reloads,
+   RELOAD_FOR_INPUT reloads, which must be live over the entire input section
+   of reloads, and the maximum of all the RELOAD_FOR_INPUT_ADDRESS and
+   RELOAD_FOR_OPERAND_ADDRESS reloads, which conflict with the inputs.
+
+   The registers needed for output are RELOAD_OTHER and RELOAD_FOR_OUTPUT,
+   which are live for the entire output portion, and the maximum of all the
+   RELOAD_FOR_OUTPUT_ADDRESS reloads for each operand.
+
+   The total number of registers needed is the maximum of the
+   inputs and outputs.  */
+
+static void
+calculate_needs (chain)
+     struct insn_chain *chain;
+{
+  int i;
+
+  /* Each `struct needs' corresponds to one RELOAD_... type.  */
+  struct {
+    struct needs other;
+    struct needs input;
+    struct needs output;
+    struct needs insn;
+    struct needs other_addr;
+    struct needs op_addr;
+    struct needs op_addr_reload;
+    struct needs in_addr[MAX_RECOG_OPERANDS];
+    struct needs in_addr_addr[MAX_RECOG_OPERANDS];
+    struct needs out_addr[MAX_RECOG_OPERANDS];
+    struct needs out_addr_addr[MAX_RECOG_OPERANDS];
+  } insn_needs;
+
+  bzero ((char *) chain->group_size, sizeof chain->group_size);
+  for (i = 0; i < N_REG_CLASSES; i++)
+    chain->group_mode[i] = VOIDmode;
+  bzero ((char *) &insn_needs, sizeof insn_needs);
+
+  /* Count each reload once in every class
+     containing the reload's own class.  */
+
+  for (i = 0; i < n_reloads; i++)
+    {
+      register enum reg_class *p;
+      enum reg_class class = reload_reg_class[i];
+      int size;
+      enum machine_mode mode;
+      struct needs *this_needs;
+
+      /* Don't count the dummy reloads, for which one of the
+        regs mentioned in the insn can be used for reloading.
+        Don't count optional reloads.
+        Don't count reloads that got combined with others.  */
+      if (reload_reg_rtx[i] != 0
+         || reload_optional[i] != 0
+         || (reload_out[i] == 0 && reload_in[i] == 0
+             && ! reload_secondary_p[i]))
+       continue;
+
+      mode = reload_inmode[i];
+      if (GET_MODE_SIZE (reload_outmode[i]) > GET_MODE_SIZE (mode))
+       mode = reload_outmode[i];
+      size = CLASS_MAX_NREGS (class, mode);
+
+      /* Decide which time-of-use to count this reload for.  */
+      switch (reload_when_needed[i])
+       {
+       case RELOAD_OTHER:
+         this_needs = &insn_needs.other;
+         break;
+       case RELOAD_FOR_INPUT:
+         this_needs = &insn_needs.input;
+         break;
+       case RELOAD_FOR_OUTPUT:
+         this_needs = &insn_needs.output;
+         break;
+       case RELOAD_FOR_INSN:
+         this_needs = &insn_needs.insn;
+         break;
+       case RELOAD_FOR_OTHER_ADDRESS:
+         this_needs = &insn_needs.other_addr;
+         break;
+       case RELOAD_FOR_INPUT_ADDRESS:
+         this_needs = &insn_needs.in_addr[reload_opnum[i]];
+         break;
+       case RELOAD_FOR_INPADDR_ADDRESS:
+         this_needs = &insn_needs.in_addr_addr[reload_opnum[i]];
+         break;
+       case RELOAD_FOR_OUTPUT_ADDRESS:
+         this_needs = &insn_needs.out_addr[reload_opnum[i]];
+         break;
+       case RELOAD_FOR_OUTADDR_ADDRESS:
+         this_needs = &insn_needs.out_addr_addr[reload_opnum[i]];
+         break;
+       case RELOAD_FOR_OPERAND_ADDRESS:
+         this_needs = &insn_needs.op_addr;
+         break;
+       case RELOAD_FOR_OPADDR_ADDR:
+         this_needs = &insn_needs.op_addr_reload;
+         break;
+       }
+
+      if (size > 1)
        {
-         if (ep->can_eliminate && ep->from == FRAME_POINTER_REGNUM
-             && ep->to != HARD_FRAME_POINTER_REGNUM)
-           frame_pointer_needed = 0;
+         enum machine_mode other_mode, allocate_mode;
+
+         /* Count number of groups needed separately from
+            number of individual regs needed.  */
+         this_needs->groups[(int) class]++;
+         p = reg_class_superclasses[(int) class];
+         while (*p != LIM_REG_CLASSES)
+           this_needs->groups[(int) *p++]++;
+
+         /* Record size and mode of a group of this class.  */
+         /* If more than one size group is needed,
+            make all groups the largest needed size.  */
+         if (chain->group_size[(int) class] < size)
+           {
+             other_mode = chain->group_mode[(int) class];
+             allocate_mode = mode;
 
-         if (! ep->can_eliminate && ep->can_eliminate_previous)
+             chain->group_size[(int) class] = size;
+             chain->group_mode[(int) class] = mode;
+           }
+         else
            {
-             ep->can_eliminate_previous = 0;
-             spill_hard_reg (ep->from, global, dumpfile, 1);
-             something_changed = 1;
-             num_eliminable--;
+             other_mode = mode;
+             allocate_mode = chain->group_mode[(int) class];
            }
-       }
 
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
-      /* If we didn't need a frame pointer last time, but we do now, spill
-        the hard frame pointer.  */
-      if (frame_pointer_needed && ! previous_frame_pointer_needed)
+         /* Crash if two dissimilar machine modes both need
+            groups of consecutive regs of the same class.  */
+
+         if (other_mode != VOIDmode && other_mode != allocate_mode
+             && ! modes_equiv_for_class_p (allocate_mode,
+                                           other_mode, class))
+           fatal_insn ("Two dissimilar machine modes both need groups of consecutive regs of the same class",
+                       chain->insn);
+       }
+      else if (size == 1)
        {
-         spill_hard_reg (HARD_FRAME_POINTER_REGNUM, global, dumpfile, 1);
-         something_changed = 1;
+         this_needs->regs[(unsigned char)reload_nongroup[i]][(int) class] += 1;
+         p = reg_class_superclasses[(int) class];
+         while (*p != LIM_REG_CLASSES)
+           this_needs->regs[(unsigned char)reload_nongroup[i]][(int) *p++] += 1;
        }
-#endif
+      else
+       abort ();
+    }
 
-      /* If all needs are met, we win.  */
+  /* All reloads have been counted for this insn;
+     now merge the various times of use.
+     This sets insn_needs, etc., to the maximum total number
+     of registers needed at any point in this insn.  */
 
-      for (i = 0; i < N_REG_CLASSES; i++)
-       if (max_needs[i] > 0 || max_groups[i] > 0 || max_nongroups[i] > 0)
-         break;
-      if (i == N_REG_CLASSES && !new_basic_block_needs && ! something_changed)
-       break;
+  for (i = 0; i < N_REG_CLASSES; i++)
+    {
+      int j, in_max, out_max;
 
-      /* Not all needs are met; must spill some hard regs.  */
-
-      /* Put all registers spilled so far back in potential_reload_regs, but
-        put them at the front, since we've already spilled most of the
-        pseudos in them (we might have left some pseudos unspilled if they
-        were in a block that didn't need any spill registers of a conflicting
-        class.  We used to try to mark off the need for those registers,
-        but doing so properly is very complex and reallocating them is the
-        simpler approach.  First, "pack" potential_reload_regs by pushing 
-        any nonnegative entries towards the end.  That will leave room 
-        for the registers we already spilled.
-
-        Also, undo the marking of the spill registers from the last time
-        around in FORBIDDEN_REGS since we will be probably be allocating
-        them again below.
-
-        ??? It is theoretically possible that we might end up not using one
-        of our previously-spilled registers in this allocation, even though
-        they are at the head of the list.  It's not clear what to do about
-        this, but it was no better before, when we marked off the needs met
-        by the previously-spilled registers.  With the current code, globals
-        can be allocated into these registers, but locals cannot.  */
-
-      if (n_spills)
+      /* Compute normal and nongroup needs.  */
+      for (j = 0; j <= 1; j++)
        {
-         for (i = j = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
-           if (potential_reload_regs[i] != -1)
-             potential_reload_regs[j--] = potential_reload_regs[i];
-
-         for (i = 0; i < n_spills; i++)
+         int k;
+         for (in_max = 0, out_max = 0, k = 0; k < reload_n_operands; k++)
            {
-             potential_reload_regs[i] = spill_regs[i];
-             spill_reg_order[spill_regs[i]] = -1;
-             CLEAR_HARD_REG_BIT (forbidden_regs, spill_regs[i]);
+             in_max = MAX (in_max,
+                           (insn_needs.in_addr[k].regs[j][i]
+                            + insn_needs.in_addr_addr[k].regs[j][i]));
+             out_max = MAX (out_max, insn_needs.out_addr[k].regs[j][i]);
+             out_max = MAX (out_max,
+                            insn_needs.out_addr_addr[k].regs[j][i]);
            }
 
-         n_spills = 0;
-       }
-
-      /* Now find more reload regs to satisfy the remaining need
-        Do it by ascending class number, since otherwise a reg
-        might be spilled for a big class and might fail to count
-        for a smaller class even though it belongs to that class.
+         /* RELOAD_FOR_INSN reloads conflict with inputs, outputs,
+            and operand addresses but not things used to reload
+            them.  Similarly, RELOAD_FOR_OPERAND_ADDRESS reloads
+            don't conflict with things needed to reload inputs or
+            outputs.  */
 
-        Count spilled regs in `spills', and add entries to
-        `spill_regs' and `spill_reg_order'.
+         in_max = MAX (MAX (insn_needs.op_addr.regs[j][i],
+                            insn_needs.op_addr_reload.regs[j][i]),
+                       in_max);
 
-        ??? Note there is a problem here.
-        When there is a need for a group in a high-numbered class,
-        and also need for non-group regs that come from a lower class,
-        the non-group regs are chosen first.  If there aren't many regs,
-        they might leave no room for a group.
+         out_max = MAX (out_max, insn_needs.insn.regs[j][i]);
 
-        This was happening on the 386.  To fix it, we added the code
-        that calls possible_group_p, so that the lower class won't
-        break up the last possible group.
+         insn_needs.input.regs[j][i]
+           = MAX (insn_needs.input.regs[j][i]
+                  + insn_needs.op_addr.regs[j][i]
+                  + insn_needs.insn.regs[j][i],
+                  in_max + insn_needs.input.regs[j][i]);
 
-        Really fixing the problem would require changes above
-        in counting the regs already spilled, and in choose_reload_regs.
-        It might be hard to avoid introducing bugs there.  */
+         insn_needs.output.regs[j][i] += out_max;
+         insn_needs.other.regs[j][i]
+           += MAX (MAX (insn_needs.input.regs[j][i],
+                        insn_needs.output.regs[j][i]),
+                   insn_needs.other_addr.regs[j][i]);
 
-      CLEAR_HARD_REG_SET (counted_for_groups);
-      CLEAR_HARD_REG_SET (counted_for_nongroups);
+       }
 
-      for (class = 0; class < N_REG_CLASSES; class++)
+      /* Now compute group needs.  */
+      for (in_max = 0, out_max = 0, j = 0; j < reload_n_operands; j++)
        {
-         /* First get the groups of registers.
-            If we got single registers first, we might fragment
-            possible groups.  */
-         while (max_groups[class] > 0)
-           {
-             /* If any single spilled regs happen to form groups,
-                count them now.  Maybe we don't really need
-                to spill another group.  */
-             count_possible_groups (group_size, group_mode, max_groups,
-                                    class);
-
-             if (max_groups[class] <= 0)
-               break;
+         in_max = MAX (in_max, insn_needs.in_addr[j].groups[i]);
+         in_max = MAX (in_max, insn_needs.in_addr_addr[j].groups[i]);
+         out_max = MAX (out_max, insn_needs.out_addr[j].groups[i]);
+         out_max = MAX (out_max, insn_needs.out_addr_addr[j].groups[i]);
+       }
 
-             /* Groups of size 2 (the only groups used on most machines)
-                are treated specially.  */
-             if (group_size[class] == 2)
-               {
-                 /* First, look for a register that will complete a group.  */
-                 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-                   {
-                     int other;
-
-                     j = potential_reload_regs[i];
-                     if (j >= 0 && ! TEST_HARD_REG_BIT (bad_spill_regs, j)
-                         &&
-                         ((j > 0 && (other = j - 1, spill_reg_order[other] >= 0)
-                           && TEST_HARD_REG_BIT (reg_class_contents[class], j)
-                           && TEST_HARD_REG_BIT (reg_class_contents[class], other)
-                           && HARD_REGNO_MODE_OK (other, group_mode[class])
-                           && ! TEST_HARD_REG_BIT (counted_for_nongroups,
-                                                   other)
-                           /* We don't want one part of another group.
-                              We could get "two groups" that overlap!  */
-                           && ! TEST_HARD_REG_BIT (counted_for_groups, other))
-                          ||
-                          (j < FIRST_PSEUDO_REGISTER - 1
-                           && (other = j + 1, spill_reg_order[other] >= 0)
-                           && TEST_HARD_REG_BIT (reg_class_contents[class], j)
-                           && TEST_HARD_REG_BIT (reg_class_contents[class], other)
-                           && HARD_REGNO_MODE_OK (j, group_mode[class])
-                           && ! TEST_HARD_REG_BIT (counted_for_nongroups,
-                                                   other)
-                           && ! TEST_HARD_REG_BIT (counted_for_groups,
-                                                   other))))
-                       {
-                         register enum reg_class *p;
+      in_max = MAX (MAX (insn_needs.op_addr.groups[i],
+                        insn_needs.op_addr_reload.groups[i]),
+                   in_max);
+      out_max = MAX (out_max, insn_needs.insn.groups[i]);
+
+      insn_needs.input.groups[i]
+       = MAX (insn_needs.input.groups[i]
+              + insn_needs.op_addr.groups[i]
+              + insn_needs.insn.groups[i],
+              in_max + insn_needs.input.groups[i]);
+
+      insn_needs.output.groups[i] += out_max;
+      insn_needs.other.groups[i]
+       += MAX (MAX (insn_needs.input.groups[i],
+                    insn_needs.output.groups[i]),
+               insn_needs.other_addr.groups[i]);
+    }
 
-                         /* We have found one that will complete a group,
-                            so count off one group as provided.  */
-                         max_groups[class]--;
-                         p = reg_class_superclasses[class];
-                         while (*p != LIM_REG_CLASSES)
-                           {
-                             if (group_size [(int) *p] <= group_size [class])
-                               max_groups[(int) *p]--;
-                             p++;
-                           }
+  /* Record the needs for later.  */
+  chain->need = insn_needs.other;
+}
+\f
+/* Find a group of exactly 2 registers.
 
-                         /* Indicate both these regs are part of a group.  */
-                         SET_HARD_REG_BIT (counted_for_groups, j);
-                         SET_HARD_REG_BIT (counted_for_groups, other);
-                         break;
-                       }
-                   }
-                 /* We can't complete a group, so start one.  */
-                 /* Look for a pair neither of which is explicitly used.  */
-                 if (SMALL_REGISTER_CLASSES && i == FIRST_PSEUDO_REGISTER)
-                   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-                     {
-                       int k;
-                       j = potential_reload_regs[i];
-                       /* Verify that J+1 is a potential reload reg.  */
-                       for (k = 0; k < FIRST_PSEUDO_REGISTER; k++)
-                         if (potential_reload_regs[k] == j + 1)
-                           break;
-                       if (j >= 0 && j + 1 < FIRST_PSEUDO_REGISTER
-                           && k < FIRST_PSEUDO_REGISTER
-                           && spill_reg_order[j] < 0 && spill_reg_order[j + 1] < 0
-                           && TEST_HARD_REG_BIT (reg_class_contents[class], j)
-                           && TEST_HARD_REG_BIT (reg_class_contents[class], j + 1)
-                           && HARD_REGNO_MODE_OK (j, group_mode[class])
-                           && ! TEST_HARD_REG_BIT (counted_for_nongroups,
-                                                   j + 1)
-                           && ! TEST_HARD_REG_BIT (bad_spill_regs, j + 1)
-                           /* Reject J at this stage
-                              if J+1 was explicitly used.  */
-                           && ! regs_explicitly_used[j + 1])
-                         break;
-                     }
-                 /* Now try any group at all
-                    whose registers are not in bad_spill_regs.  */
-                 if (i == FIRST_PSEUDO_REGISTER)
-                   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-                     {
-                       int k;
-                       j = potential_reload_regs[i];
-                       /* Verify that J+1 is a potential reload reg.  */
-                       for (k = 0; k < FIRST_PSEUDO_REGISTER; k++)
-                         if (potential_reload_regs[k] == j + 1)
-                           break;
-                       if (j >= 0 && j + 1 < FIRST_PSEUDO_REGISTER
-                           && k < FIRST_PSEUDO_REGISTER
-                           && spill_reg_order[j] < 0 && spill_reg_order[j + 1] < 0
-                           && TEST_HARD_REG_BIT (reg_class_contents[class], j)
-                           && TEST_HARD_REG_BIT (reg_class_contents[class], j + 1)
-                           && HARD_REGNO_MODE_OK (j, group_mode[class])
-                           && ! TEST_HARD_REG_BIT (counted_for_nongroups,
-                                                   j + 1)
-                           && ! TEST_HARD_REG_BIT (bad_spill_regs, j + 1))
-                         break;
-                     }
+   First try to fill out the group by spilling a single register which
+   would allow completion of the group.
 
-                 /* I should be the index in potential_reload_regs
-                    of the new reload reg we have found.  */
+   Then try to create a new group from a pair of registers, neither of
+   which are explicitly used.
 
-                 if (i >= FIRST_PSEUDO_REGISTER)
-                   {
-                     /* There are no groups left to spill.  */
-                     spill_failure (max_groups_insn[class]);
-                     failure = 1;
-                     goto failed;
-                   }
-                 else
-                   something_changed
-                     |= new_spill_reg (i, class, max_needs, NULL_PTR,
-                                       global, dumpfile);
-               }
-             else
-               {
-                 /* For groups of more than 2 registers,
-                    look for a sufficient sequence of unspilled registers,
-                    and spill them all at once.  */
-                 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-                   {
-                     int k;
+   Then try to create a group from any pair of registers.  */
 
-                     j = potential_reload_regs[i];
-                     if (j >= 0
-                         && j + group_size[class] <= FIRST_PSEUDO_REGISTER
-                         && HARD_REGNO_MODE_OK (j, group_mode[class]))
-                       {
-                         /* Check each reg in the sequence.  */
-                         for (k = 0; k < group_size[class]; k++)
-                           if (! (spill_reg_order[j + k] < 0
-                                  && ! TEST_HARD_REG_BIT (bad_spill_regs, j + k)
-                                  && TEST_HARD_REG_BIT (reg_class_contents[class], j + k)))
-                             break;
-                         /* We got a full sequence, so spill them all.  */
-                         if (k == group_size[class])
-                           {
-                             register enum reg_class *p;
-                             for (k = 0; k < group_size[class]; k++)
-                               {
-                                 int idx;
-                                 SET_HARD_REG_BIT (counted_for_groups, j + k);
-                                 for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
-                                   if (potential_reload_regs[idx] == j + k)
-                                     break;
-                                 something_changed
-                                   |= new_spill_reg (idx, class,
-                                                     max_needs, NULL_PTR,
-                                                     global, dumpfile);
-                               }
+static void
+find_tworeg_group (chain, class, dumpfile)
+     struct insn_chain *chain;
+     int class;
+     FILE *dumpfile;
+{
+  int i;
+  /* First, look for a register that will complete a group.  */
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      int j, other;
+
+      j = potential_reload_regs[i];
+      if (j >= 0 && ! TEST_HARD_REG_BIT (bad_spill_regs, j)
+         && ((j > 0 && (other = j - 1, spill_reg_order[other] >= 0)
+              && TEST_HARD_REG_BIT (reg_class_contents[class], j)
+              && TEST_HARD_REG_BIT (reg_class_contents[class], other)
+              && HARD_REGNO_MODE_OK (other, chain->group_mode[class])
+              && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, other)
+              /* We don't want one part of another group.
+                 We could get "two groups" that overlap!  */
+              && ! TEST_HARD_REG_BIT (chain->counted_for_groups, other))
+             || (j < FIRST_PSEUDO_REGISTER - 1
+                 && (other = j + 1, spill_reg_order[other] >= 0)
+                 && TEST_HARD_REG_BIT (reg_class_contents[class], j)
+                 && TEST_HARD_REG_BIT (reg_class_contents[class], other)
+                 && HARD_REGNO_MODE_OK (j, chain->group_mode[class])
+                 && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, other)
+                 && ! TEST_HARD_REG_BIT (chain->counted_for_groups, other))))
+       {
+         register enum reg_class *p;
 
-                             /* We have found one that will complete a group,
-                                so count off one group as provided.  */
-                             max_groups[class]--;
-                             p = reg_class_superclasses[class];
-                             while (*p != LIM_REG_CLASSES)
-                               {
-                                 if (group_size [(int) *p]
-                                     <= group_size [class])
-                                   max_groups[(int) *p]--;
-                                 p++;
-                               }
-                             break;
-                           }
-                       }
-                   }
-                 /* We couldn't find any registers for this reload.
-                    Avoid going into an infinite loop.  */
-                 if (i >= FIRST_PSEUDO_REGISTER)
-                   {
-                     /* There are no groups left.  */
-                     spill_failure (max_groups_insn[class]);
-                     failure = 1;
-                     goto failed;
-                   }
-               }
+         /* We have found one that will complete a group,
+            so count off one group as provided.  */
+         chain->need.groups[class]--;
+         p = reg_class_superclasses[class];
+         while (*p != LIM_REG_CLASSES)
+           {
+             if (chain->group_size [(int) *p] <= chain->group_size [class])
+               chain->need.groups[(int) *p]--;
+             p++;
            }
 
-         /* Now similarly satisfy all need for single registers.  */
+         /* Indicate both these regs are part of a group.  */
+         SET_HARD_REG_BIT (chain->counted_for_groups, j);
+         SET_HARD_REG_BIT (chain->counted_for_groups, other);
+         break;
+       }
+    }
+  /* We can't complete a group, so start one.  */
+  if (i == FIRST_PSEUDO_REGISTER)
+    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+      {
+       int j, k;
+       j = potential_reload_regs[i];
+       /* Verify that J+1 is a potential reload reg.  */
+       for (k = 0; k < FIRST_PSEUDO_REGISTER; k++)
+         if (potential_reload_regs[k] == j + 1)
+           break;
+       if (j >= 0 && j + 1 < FIRST_PSEUDO_REGISTER
+           && k < FIRST_PSEUDO_REGISTER
+           && spill_reg_order[j] < 0 && spill_reg_order[j + 1] < 0
+           && TEST_HARD_REG_BIT (reg_class_contents[class], j)
+           && TEST_HARD_REG_BIT (reg_class_contents[class], j + 1)
+           && HARD_REGNO_MODE_OK (j, chain->group_mode[class])
+           && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, j + 1)
+           && ! TEST_HARD_REG_BIT (bad_spill_regs, j + 1))
+         break;
+      }
 
-         while (max_needs[class] > 0 || max_nongroups[class] > 0)
-           {
-             /* If we spilled enough regs, but they weren't counted
-                against the non-group need, see if we can count them now.
-                If so, we can avoid some actual spilling.  */
-             if (max_needs[class] <= 0 && max_nongroups[class] > 0)
-               for (i = 0; i < n_spills; i++)
-                 if (TEST_HARD_REG_BIT (reg_class_contents[class],
-                                        spill_regs[i])
-                     && !TEST_HARD_REG_BIT (counted_for_groups,
-                                            spill_regs[i])
-                     && !TEST_HARD_REG_BIT (counted_for_nongroups,
-                                            spill_regs[i])
-                     && max_nongroups[class] > 0)
-                   {
-                     register enum reg_class *p;
+  /* I should be the index in potential_reload_regs
+     of the new reload reg we have found.  */
 
-                     SET_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]);
-                     max_nongroups[class]--;
-                     p = reg_class_superclasses[class];
-                     while (*p != LIM_REG_CLASSES)
-                       max_nongroups[(int) *p++]--;
-                   }
-             if (max_needs[class] <= 0 && max_nongroups[class] <= 0)
-               break;
+  new_spill_reg (chain, i, class, 0, dumpfile);
+}
 
-             /* Consider the potential reload regs that aren't
-                yet in use as reload regs, in order of preference.
-                Find the most preferred one that's in this class.  */
-
-             for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-               if (potential_reload_regs[i] >= 0
-                   && TEST_HARD_REG_BIT (reg_class_contents[class],
-                                         potential_reload_regs[i])
-                   /* If this reg will not be available for groups,
-                      pick one that does not foreclose possible groups.
-                      This is a kludge, and not very general,
-                      but it should be sufficient to make the 386 work,
-                      and the problem should not occur on machines with
-                      more registers.  */
-                   && (max_nongroups[class] == 0
-                       || possible_group_p (potential_reload_regs[i], max_groups)))
-                 break;
+/* Find a group of more than 2 registers.
+   Look for a sufficient sequence of unspilled registers, and spill them all
+   at once.  */
 
-             /* If we couldn't get a register, try to get one even if we
-                might foreclose possible groups.  This may cause problems
-                later, but that's better than aborting now, since it is
-                possible that we will, in fact, be able to form the needed
-                group even with this allocation.  */
-
-             if (i >= FIRST_PSEUDO_REGISTER
-                 && (asm_noperands (max_needs[class] > 0
-                                    ? max_needs_insn[class]
-                                    : max_nongroups_insn[class])
-                     < 0))
-               for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-                 if (potential_reload_regs[i] >= 0
-                     && TEST_HARD_REG_BIT (reg_class_contents[class],
-                                           potential_reload_regs[i]))
-                   break;
+static void
+find_group (chain, class, dumpfile)
+     struct insn_chain *chain;
+     int class;
+     FILE *dumpfile;
+{
+  int i;
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      int j = potential_reload_regs[i];
 
-             /* I should be the index in potential_reload_regs
-                of the new reload reg we have found.  */
+      if (j >= 0
+         && j + chain->group_size[class] <= FIRST_PSEUDO_REGISTER
+         && HARD_REGNO_MODE_OK (j, chain->group_mode[class]))
+       {
+         int k;
+         /* Check each reg in the sequence.  */
+         for (k = 0; k < chain->group_size[class]; k++)
+           if (! (spill_reg_order[j + k] < 0
+                  && ! TEST_HARD_REG_BIT (bad_spill_regs, j + k)
+                  && TEST_HARD_REG_BIT (reg_class_contents[class], j + k)))
+             break;
+         /* We got a full sequence, so spill them all.  */
+         if (k == chain->group_size[class])
+           {
+             register enum reg_class *p;
+             for (k = 0; k < chain->group_size[class]; k++)
+               {
+                 int idx;
+                 SET_HARD_REG_BIT (chain->counted_for_groups, j + k);
+                 for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
+                   if (potential_reload_regs[idx] == j + k)
+                     break;
+                 new_spill_reg (chain, idx, class, 0, dumpfile);
+               }
 
-             if (i >= FIRST_PSEUDO_REGISTER)
+             /* We have found one that will complete a group,
+                so count off one group as provided.  */
+             chain->need.groups[class]--;
+             p = reg_class_superclasses[class];
+             while (*p != LIM_REG_CLASSES)
                {
-                 /* There are no possible registers left to spill.  */
-                 spill_failure (max_needs[class] > 0 ? max_needs_insn[class]
-                                : max_nongroups_insn[class]);
-                 failure = 1;
-                 goto failed;
+                 if (chain->group_size [(int) *p]
+                     <= chain->group_size [class])
+                   chain->need.groups[(int) *p]--;
+                 p++;
                }
-             else
-               something_changed
-                 |= new_spill_reg (i, class, max_needs, max_nongroups,
-                                   global, dumpfile);
+             return;
            }
        }
     }
+  /* There are no groups left.  */
+  spill_failure (chain->insn);
+  failure = 1;
+}
 
-  /* If global-alloc was run, notify it of any register eliminations we have
-     done.  */
-  if (global)
-    for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-      if (ep->can_eliminate)
-       mark_elimination (ep->from, ep->to);
+/* If pseudo REG conflicts with one of our reload registers, mark it as
+   spilled.  */
+static void
+maybe_mark_pseudo_spilled (reg)
+     int reg;
+{
+  int i;
+  int r = reg_renumber[reg];
+  int nregs;
 
-  /* Insert code to save and restore call-clobbered hard regs
-     around calls.  Tell if what mode to use so that we will process
-     those insns in reload_as_needed if we have to.  */
+  if (r < 0)
+    abort ();
+  nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg));
+  for (i = 0; i < n_spills; i++)
+    if (r <= spill_regs[i] && r + nregs > spill_regs[i])
+      {
+       SET_REGNO_REG_SET (spilled_pseudos, reg);
+       return;
+      }
+}
 
-  if (caller_save_needed)
-    save_call_clobbered_regs (num_eliminable ? QImode
-                             : caller_save_spill_class != NO_REGS ? HImode
-                             : VOIDmode);
+/* Find more reload regs to satisfy the remaining need of an insn, which
+   is given by CHAIN.
+   Do it by ascending class number, since otherwise a reg
+   might be spilled for a big class and might fail to count
+   for a smaller class even though it belongs to that class.
 
-  /* If a pseudo has no hard reg, delete the insns that made the equivalence.
-     If that insn didn't set the register (i.e., it copied the register to
-     memory), just delete that insn instead of the equivalencing insn plus
-     anything now dead.  If we call delete_dead_insn on that insn, we may
-     delete the insn that actually sets the register if the register die
-     there and that is incorrect.  */
+   Count spilled regs in `spills', and add entries to
+   `spill_regs' and `spill_reg_order'.
 
-  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-    if (reg_renumber[i] < 0 && reg_equiv_init[i] != 0
-       && GET_CODE (reg_equiv_init[i]) != NOTE)
-      {
-       if (reg_set_p (regno_reg_rtx[i], PATTERN (reg_equiv_init[i])))
-         delete_dead_insn (reg_equiv_init[i]);
-       else
-         {
-           PUT_CODE (reg_equiv_init[i], NOTE);
-           NOTE_SOURCE_FILE (reg_equiv_init[i]) = 0;
-           NOTE_LINE_NUMBER (reg_equiv_init[i]) = NOTE_INSN_DELETED;
-         }
-      }
+   ??? Note there is a problem here.
+   When there is a need for a group in a high-numbered class,
+   and also need for non-group regs that come from a lower class,
+   the non-group regs are chosen first.  If there aren't many regs,
+   they might leave no room for a group.
 
-  /* Use the reload registers where necessary
-     by generating move instructions to move the must-be-register
-     values into or out of the reload registers.  */
+   This was happening on the 386.  To fix it, we added the code
+   that calls possible_group_p, so that the lower class won't
+   break up the last possible group.
 
-  if (something_needs_reloads || something_needs_elimination
-      || (caller_save_needed && num_eliminable)
-      || caller_save_spill_class != NO_REGS)
-    reload_as_needed (first, global);
+   Really fixing the problem would require changes above
+   in counting the regs already spilled, and in choose_reload_regs.
+   It might be hard to avoid introducing bugs there.  */
 
-  /* If we were able to eliminate the frame pointer, show that it is no
-     longer live at the start of any basic block.  If it ls live by
-     virtue of being in a pseudo, that pseudo will be marked live
-     and hence the frame pointer will be known to be live via that
-     pseudo.  */
+static void
+find_reload_regs (chain, dumpfile)
+     struct insn_chain *chain;
+     FILE *dumpfile;
+{
+  int i, class;
+  short *group_needs = chain->need.groups;
+  short *simple_needs = chain->need.regs[0];
+  short *nongroup_needs = chain->need.regs[1];
 
-  if (! frame_pointer_needed)
-    for (i = 0; i < n_basic_blocks; i++)
-      CLEAR_REGNO_REG_SET (basic_block_live_at_start[i],
-                          HARD_FRAME_POINTER_REGNUM);
+  if (dumpfile)
+    fprintf (dumpfile, "Spilling for insn %d.\n", INSN_UID (chain->insn));
 
-  /* Come here (with failure set nonzero) if we can't get enough spill regs
-     and we decide not to abort about it.  */
- failed:
+  /* Compute the order of preference for hard registers to spill.
+     Store them by decreasing preference in potential_reload_regs.  */
 
-  reload_in_progress = 0;
+  order_regs_for_reload (chain);
 
-  /* Now eliminate all pseudo regs by modifying them into
-     their equivalent memory references.
-     The REG-rtx's for the pseudos are modified in place,
-     so all insns that used to refer to them now refer to memory.
+  /* So far, no hard regs have been spilled.  */
+  n_spills = 0;
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    spill_reg_order[i] = -1;
 
-     For a reg that has a reg_equiv_address, all those insns
-     were changed by reloading so that no insns refer to it any longer;
-     but the DECL_RTL of a variable decl may refer to it,
-     and if so this causes the debugging info to mention the variable.  */
+  CLEAR_HARD_REG_SET (chain->used_spill_regs);
+  CLEAR_HARD_REG_SET (chain->counted_for_groups);
+  CLEAR_HARD_REG_SET (chain->counted_for_nongroups);
 
-  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+  for (class = 0; class < N_REG_CLASSES; class++)
     {
-      rtx addr = 0;
-      int in_struct = 0;
-      if (reg_equiv_mem[i])
-       {
-         addr = XEXP (reg_equiv_mem[i], 0);
-         in_struct = MEM_IN_STRUCT_P (reg_equiv_mem[i]);
-       }
-      if (reg_equiv_address[i])
-       addr = reg_equiv_address[i];
-      if (addr)
+      /* First get the groups of registers.
+        If we got single registers first, we might fragment
+        possible groups.  */
+      while (group_needs[class] > 0)
        {
-         if (reg_renumber[i] < 0)
-           {
-             rtx reg = regno_reg_rtx[i];
-             XEXP (reg, 0) = addr;
-             REG_USERVAR_P (reg) = 0;
-             MEM_IN_STRUCT_P (reg) = in_struct;
-             PUT_CODE (reg, MEM);
-           }
-         else if (reg_equiv_mem[i])
-           XEXP (reg_equiv_mem[i], 0) = addr;
+         /* If any single spilled regs happen to form groups,
+            count them now.  Maybe we don't really need
+            to spill another group.  */
+         count_possible_groups (chain, class);
+
+         if (group_needs[class] <= 0)
+           break;
+
+         /* Groups of size 2, the only groups used on most machines,
+            are treated specially.  */
+         if (chain->group_size[class] == 2)
+           find_tworeg_group (chain, class, dumpfile);
+         else
+           find_group (chain, class, dumpfile);
+         if (failure)
+           return;
        }
-    }
 
-  /* Make a pass over all the insns and delete all USEs which we inserted
-     only to tag a REG_EQUAL note on them; if PRESERVE_DEATH_INFO_REGNO_P
-     is defined, also remove death notes for things that are no longer
-     registers or no longer die in the insn (e.g., an input and output
-     pseudo being tied).  */
+      /* Now similarly satisfy all need for single registers.  */
+
+      while (simple_needs[class] > 0 || nongroup_needs[class] > 0)
+       {
+         /* If we spilled enough regs, but they weren't counted
+            against the non-group need, see if we can count them now.
+            If so, we can avoid some actual spilling.  */
+         if (simple_needs[class] <= 0 && nongroup_needs[class] > 0)
+           for (i = 0; i < n_spills; i++)
+             {
+               int regno = spill_regs[i];
+               if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+                   && !TEST_HARD_REG_BIT (chain->counted_for_groups, regno)
+                   && !TEST_HARD_REG_BIT (chain->counted_for_nongroups, regno)
+                   && nongroup_needs[class] > 0)
+                 {
+                   register enum reg_class *p;
 
-  for (insn = first; insn; insn = NEXT_INSN (insn))
-    if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
-      {
-       rtx note, next;
+                   SET_HARD_REG_BIT (chain->counted_for_nongroups, regno);
+                   nongroup_needs[class]--;
+                   p = reg_class_superclasses[class];
+                   while (*p != LIM_REG_CLASSES)
+                     nongroup_needs[(int) *p++]--;
+                 }
+             }
 
-       if (GET_CODE (insn) == USE
-           && find_reg_note (insn, REG_EQUAL, NULL_RTX))
-         {
-           PUT_CODE (insn, NOTE);
-           NOTE_SOURCE_FILE (insn) = 0;
-           NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-           continue;
-         }
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-       for (note = REG_NOTES (insn); note; note = next)
-         {
-           next = XEXP (note, 1);
-           if (REG_NOTE_KIND (note) == REG_DEAD
-               && (GET_CODE (XEXP (note, 0)) != REG
-                   || reg_set_p (XEXP (note, 0), PATTERN (insn))))
-             remove_note (insn, note);
-         }
-#endif
-      }
+         if (simple_needs[class] <= 0 && nongroup_needs[class] <= 0)
+           break;
 
-  /* If we are doing stack checking, give a warning if this function's
-     frame size is larger than we expect.  */
-  if (flag_stack_check && ! STACK_CHECK_BUILTIN)
-    {
-      HOST_WIDE_INT size = get_frame_size () + STACK_CHECK_FIXED_FRAME_SIZE;
+         /* Consider the potential reload regs that aren't
+            yet in use as reload regs, in order of preference.
+            Find the most preferred one that's in this class.  */
 
-      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-       if (regs_ever_live[i] && ! fixed_regs[i] && call_used_regs[i])
-         size += UNITS_PER_WORD;
+         for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+           {
+             int regno = potential_reload_regs[i];
+             if (regno >= 0
+                 && TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+                 /* If this reg will not be available for groups,
+                    pick one that does not foreclose possible groups.
+                    This is a kludge, and not very general,
+                    but it should be sufficient to make the 386 work,
+                    and the problem should not occur on machines with
+                    more registers.  */
+                 && (nongroup_needs[class] == 0
+                     || possible_group_p (chain, regno)))
+               break;
+           }
 
-      if (size > STACK_CHECK_MAX_FRAME_SIZE)
-       warning ("frame size too large for reliable stack checking");
-    }
-       
-  /* Indicate that we no longer have known memory locations or constants.  */
-  reg_equiv_constant = 0;
-  reg_equiv_memory_loc = 0;
+         /* If we couldn't get a register, try to get one even if we
+            might foreclose possible groups.  This may cause problems
+            later, but that's better than aborting now, since it is
+            possible that we will, in fact, be able to form the needed
+            group even with this allocation.  */
+
+         if (i >= FIRST_PSEUDO_REGISTER
+             && asm_noperands (chain->insn) < 0)
+           for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+             if (potential_reload_regs[i] >= 0
+                 && TEST_HARD_REG_BIT (reg_class_contents[class],
+                                       potential_reload_regs[i]))
+               break;
 
-  if (real_known_ptr)
-    free (real_known_ptr);
-  if (real_at_ptr)
-    free (real_at_ptr);
+         /* I should be the index in potential_reload_regs
+            of the new reload reg we have found.  */
+
+         new_spill_reg (chain, i, class, 1, dumpfile);
+         if (failure)
+           return;
+       }
+    }
+  
+  /* We know which hard regs to use, now mark the pseudos that live in them
+     as needing to be kicked out.  */
+  EXECUTE_IF_SET_IN_REG_SET
+    (chain->live_before, FIRST_PSEUDO_REGISTER, i,
+     {
+       maybe_mark_pseudo_spilled (i);
+     });
+  EXECUTE_IF_SET_IN_REG_SET
+    (chain->live_after, FIRST_PSEUDO_REGISTER, i,
+     {
+       maybe_mark_pseudo_spilled (i);
+     });
+
+  IOR_HARD_REG_SET (used_spill_regs, chain->used_spill_regs);
+}
 
-  if (scratch_list)
-    free (scratch_list);
-  scratch_list = 0;
-  if (scratch_block)
-    free (scratch_block);
-  scratch_block = 0;
+void
+dump_needs (chain, dumpfile)
+     struct insn_chain *chain;
+     FILE *dumpfile;
+{
+  static char *reg_class_names[] = REG_CLASS_NAMES;
+  int i;
+  struct needs *n = &chain->need;
 
-  CLEAR_HARD_REG_SET (used_spill_regs);
-  for (i = 0; i < n_spills; i++)
-    SET_HARD_REG_BIT (used_spill_regs, spill_regs[i]);
+  for (i = 0; i < N_REG_CLASSES; i++)
+    {
+      if (n->regs[i][0] > 0)
+       fprintf (dumpfile,
+                ";; Need %d reg%s of class %s.\n",
+                n->regs[i][0], n->regs[i][0] == 1 ? "" : "s",
+                reg_class_names[i]);
+      if (n->regs[i][1] > 0)
+       fprintf (dumpfile,
+                ";; Need %d nongroup reg%s of class %s.\n",
+                n->regs[i][1], n->regs[i][1] == 1 ? "" : "s",
+                reg_class_names[i]);
+      if (n->groups[i] > 0)
+       fprintf (dumpfile,
+                ";; Need %d group%s (%smode) of class %s.\n",
+                n->groups[i], n->groups[i] == 1 ? "" : "s",
+                mode_name[(int) chain->group_mode[i]],
+                reg_class_names[i]);
+    }
+}
+\f
+/* Delete all insns that were inserted by emit_caller_save_insns during
+   this iteration.  */
+static void
+delete_caller_save_insns ()
+{
+  struct insn_chain *c = reload_insn_chain;
 
-  return failure;
+  while (c != 0)
+    {
+      while (c != 0 && c->is_caller_save_insn)
+       {
+         struct insn_chain *next = c->next;
+         rtx insn = c->insn;
+
+         if (insn == basic_block_head[c->block])
+           basic_block_head[c->block] = NEXT_INSN (insn);
+         if (insn == basic_block_end[c->block])
+           basic_block_end[c->block] = PREV_INSN (insn);
+         if (c == reload_insn_chain)
+           reload_insn_chain = next;
+
+         if (NEXT_INSN (insn) != 0)
+           PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
+         if (PREV_INSN (insn) != 0)
+           NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
+
+         if (next)
+           next->prev = c->prev;
+         if (c->prev)
+           c->prev->next = next;
+         c->next = unused_insn_chains;
+         unused_insn_chains = c;
+         c = next;
+       }
+      if (c != 0)
+       c = c->next;
+    }
 }
 \f
 /* Nonzero if, after spilling reg REGNO for non-groups,
    it will still be possible to find a group if we still need one.  */
 
 static int
-possible_group_p (regno, max_groups)
+possible_group_p (chain, regno)
+     struct insn_chain *chain;
      int regno;
-     int *max_groups;
 {
   int i;
   int class = (int) NO_REGS;
 
   for (i = 0; i < (int) N_REG_CLASSES; i++)
-    if (max_groups[i] > 0)
+    if (chain->need.groups[i] > 0)
       {
        class = i;
        break;
@@ -2213,28 +2026,26 @@ possible_group_p (regno, max_groups)
       if (spill_reg_order[i] < 0
          && ! TEST_HARD_REG_BIT (bad_spill_regs, i)
          && spill_reg_order[i + 1] >= 0
-         && ! TEST_HARD_REG_BIT (counted_for_groups, i + 1)
-         && ! TEST_HARD_REG_BIT (counted_for_nongroups, i + 1))
+         && ! TEST_HARD_REG_BIT (chain->counted_for_groups, i + 1)
+         && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, i + 1))
        return 1;
       if (spill_reg_order[i + 1] < 0
          && ! TEST_HARD_REG_BIT (bad_spill_regs, i + 1)
          && spill_reg_order[i] >= 0
-         && ! TEST_HARD_REG_BIT (counted_for_groups, i)
-         && ! TEST_HARD_REG_BIT (counted_for_nongroups, i))
+         && ! TEST_HARD_REG_BIT (chain->counted_for_groups, i)
+         && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, i))
        return 1;
     }
 
   return 0;
 }
-\f
+
 /* Count any groups of CLASS that can be formed from the registers recently
    spilled.  */
 
 static void
-count_possible_groups (group_size, group_mode, max_groups, class)
-     int *group_size;
-     enum machine_mode *group_mode;
-     int *max_groups;
+count_possible_groups (chain, class)
+     struct insn_chain *chain;
      int class;
 {
   HARD_REG_SET new;
@@ -2244,46 +2055,50 @@ count_possible_groups (group_size, group_mode, max_groups, class)
      and mark each group off against the need for such groups.
      But don't count them against ordinary need, yet.  */
 
-  if (group_size[class] == 0)
+  if (chain->group_size[class] == 0)
     return;
 
   CLEAR_HARD_REG_SET (new);
 
   /* Make a mask of all the regs that are spill regs in class I.  */
   for (i = 0; i < n_spills; i++)
-    if (TEST_HARD_REG_BIT (reg_class_contents[class], spill_regs[i])
-       && ! TEST_HARD_REG_BIT (counted_for_groups, spill_regs[i])
-       && ! TEST_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]))
-      SET_HARD_REG_BIT (new, spill_regs[i]);
+    {
+      int regno = spill_regs[i];
+
+      if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+         && ! TEST_HARD_REG_BIT (chain->counted_for_groups, regno)
+         && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, regno))
+       SET_HARD_REG_BIT (new, regno);
+    }
 
   /* Find each consecutive group of them.  */
-  for (i = 0; i < FIRST_PSEUDO_REGISTER && max_groups[class] > 0; i++)
+  for (i = 0; i < FIRST_PSEUDO_REGISTER && chain->need.groups[class] > 0; i++)
     if (TEST_HARD_REG_BIT (new, i)
-       && i + group_size[class] <= FIRST_PSEUDO_REGISTER
-       && HARD_REGNO_MODE_OK (i, group_mode[class]))
+       && i + chain->group_size[class] <= FIRST_PSEUDO_REGISTER
+       && HARD_REGNO_MODE_OK (i, chain->group_mode[class]))
       {
-       for (j = 1; j < group_size[class]; j++)
+       for (j = 1; j < chain->group_size[class]; j++)
          if (! TEST_HARD_REG_BIT (new, i + j))
            break;
 
-       if (j == group_size[class])
+       if (j == chain->group_size[class])
          {
            /* We found a group.  Mark it off against this class's need for
               groups, and against each superclass too.  */
            register enum reg_class *p;
 
-           max_groups[class]--;
+           chain->need.groups[class]--;
            p = reg_class_superclasses[class];
            while (*p != LIM_REG_CLASSES)
              {
-               if (group_size [(int) *p] <= group_size [class])
-                 max_groups[(int) *p]--;
+               if (chain->group_size [(int) *p] <= chain->group_size [class])
+                 chain->need.groups[(int) *p]--;
                p++;
              }
 
            /* Don't count these registers again.  */
-           for (j = 0; j < group_size[class]; j++)
-             SET_HARD_REG_BIT (counted_for_groups, i + j);
+           for (j = 0; j < chain->group_size[class]; j++)
+             SET_HARD_REG_BIT (chain->counted_for_groups, i + j);
          }
 
        /* Skip to the last reg in this group.  When i is incremented above,
@@ -2319,7 +2134,7 @@ modes_equiv_for_class_p (allocate_mode, other_mode, class)
     }
   return 1;
 }
-
+\f
 /* Handle the failure to find a register to spill.
    INSN should be one of the insns which needed this particular spill reg.  */
 
@@ -2333,37 +2148,53 @@ spill_failure (insn)
     fatal_insn ("Unable to find a register to spill.", insn);
 }
 
-/* Add a new register to the tables of available spill-registers
-    (as well as spilling all pseudos allocated to the register).
+/* Add a new register to the tables of available spill-registers.
+   CHAIN is the insn for which the register will be used; we decrease the
+   needs of that insn.
    I is the index of this register in potential_reload_regs.
    CLASS is the regclass whose need is being satisfied.
-   MAX_NEEDS and MAX_NONGROUPS are the vectors of needs,
-    so that this register can count off against them.
-    MAX_NONGROUPS is 0 if this register is part of a group.
-   GLOBAL and DUMPFILE are the same as the args that `reload' got.  */
+   NONGROUP is 0 if this register is part of a group.
+   DUMPFILE is the same as the one that `reload' got.  */
 
-static int
-new_spill_reg (i, class, max_needs, max_nongroups, global, dumpfile)
+static void
+new_spill_reg (chain, i, class, nongroup, dumpfile)
+     struct insn_chain *chain;
      int i;
      int class;
-     int *max_needs;
-     int *max_nongroups;
-     int global;
+     int nongroup;
      FILE *dumpfile;
 {
   register enum reg_class *p;
-  int val;
   int regno = potential_reload_regs[i];
 
   if (i >= FIRST_PSEUDO_REGISTER)
-    abort ();  /* Caller failed to find any register.  */
+    {
+      spill_failure (chain->insn);
+      failure = 1;
+      return;
+    }
 
-  if (fixed_regs[regno] || TEST_HARD_REG_BIT (forbidden_regs, regno))
+  if (TEST_HARD_REG_BIT (bad_spill_regs, regno))
     {
       static char *reg_class_names[] = REG_CLASS_NAMES;
-      fatal ("fixed or forbidden register %d (%s) was spilled for class %s.\n\
-This may be due to a compiler bug or to impossible asm\n\
-statements or clauses.", regno, reg_names[regno], reg_class_names[class]);
+
+      if (asm_noperands (PATTERN (chain->insn)) < 0)
+       {
+       /* The error message is still correct - we know only that it wasn't
+          an asm statement that caused the problem, but one of the global
+          registers declared by the users might have screwed us.  */
+         error ("fixed or forbidden register %d (%s) was spilled for class %s.",
+                regno, reg_names[regno], reg_class_names[class]);
+         error ("This may be due to a compiler bug or to impossible asm");
+         error ("statements or clauses.");
+         fatal_insn ("This is the instruction:", chain->insn);
+       }
+      error_for_asm (chain->insn, "Invalid `asm' statement:");
+      error_for_asm (chain->insn,
+                    "fixed or forbidden register %d (%s) was spilled for class %s.",
+                    regno, reg_names[regno], reg_class_names[class]);
+      failure = 1;
+      return;
     }
 
   /* Make reg REGNO an additional reload reg.  */
@@ -2372,49 +2203,26 @@ statements or clauses.", regno, reg_names[regno], reg_class_names[class]);
   spill_regs[n_spills] = regno;
   spill_reg_order[regno] = n_spills;
   if (dumpfile)
-    fprintf (dumpfile, "Spilling reg %d.\n", spill_regs[n_spills]);
+    fprintf (dumpfile, "Spilling reg %d.\n", regno);
+  SET_HARD_REG_BIT (chain->used_spill_regs, regno);
 
   /* Clear off the needs we just satisfied.  */
 
-  max_needs[class]--;
+  chain->need.regs[0][class]--;
   p = reg_class_superclasses[class];
   while (*p != LIM_REG_CLASSES)
-    max_needs[(int) *p++]--;
+    chain->need.regs[0][(int) *p++]--;
 
-  if (max_nongroups && max_nongroups[class] > 0)
+  if (nongroup && chain->need.regs[1][class] > 0)
     {
-      SET_HARD_REG_BIT (counted_for_nongroups, regno);
-      max_nongroups[class]--;
+      SET_HARD_REG_BIT (chain->counted_for_nongroups, regno);
+      chain->need.regs[1][class]--;
       p = reg_class_superclasses[class];
       while (*p != LIM_REG_CLASSES)
-       max_nongroups[(int) *p++]--;
+       chain->need.regs[1][(int) *p++]--;
     }
 
-  /* Spill every pseudo reg that was allocated to this reg
-     or to something that overlaps this reg.  */
-
-  val = spill_hard_reg (spill_regs[n_spills], global, dumpfile, 0);
-
-  /* If there are some registers still to eliminate and this register
-     wasn't ever used before, additional stack space may have to be
-     allocated to store this register.  Thus, we may have changed the offset
-     between the stack and frame pointers, so mark that something has changed.
-     (If new pseudos were spilled, thus requiring more space, VAL would have
-     been set non-zero by the call to spill_hard_reg above since additional
-     reloads may be needed in that case.
-
-     One might think that we need only set VAL to 1 if this is a call-used
-     register.  However, the set of registers that must be saved by the
-     prologue is not identical to the call-used set.  For example, the
-     register used by the call insn for the return PC is a call-used register,
-     but must be saved by the prologue.  */
-  if (num_eliminable && ! regs_ever_live[spill_regs[n_spills]])
-    val = 1;
-
-  regs_ever_live[spill_regs[n_spills]] = 1;
   n_spills++;
-
-  return val;
 }
 \f
 /* Delete an unneeded INSN and any previous insns who sole purpose is loading
@@ -2432,7 +2240,8 @@ delete_dead_insn (insn)
   if (prev && GET_CODE (PATTERN (prev)) == SET
       && (prev_dest = SET_DEST (PATTERN (prev)), GET_CODE (prev_dest) == REG)
       && reg_mentioned_p (prev_dest, PATTERN (insn))
-      && find_regno_note (insn, REG_DEAD, REGNO (prev_dest)))
+      && find_regno_note (insn, REG_DEAD, REGNO (prev_dest))
+      && ! side_effects_p (SET_SRC (PATTERN (prev))))
     delete_dead_insn (prev);
 
   PUT_CODE (insn, NOTE);
@@ -2556,7 +2365,14 @@ alter_reg (i, from_reg)
        {
          x = gen_rtx_MEM (GET_MODE (regno_reg_rtx[i]),
                       plus_constant (XEXP (x, 0), adjust));
-         RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]);
+
+         /* If this was shared among registers, must ensure we never
+            set it readonly since that can cause scheduling
+            problems.  Note we would only have in this adjustment
+            case in any event, since the code above doesn't set it.  */
+
+         if (from_reg == -1)
+           RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]);
        }
 
       /* Save the stack slot for later.   */
@@ -2579,20 +2395,6 @@ mark_home_live (regno)
   while (i < lim)
     regs_ever_live[i++] = 1;
 }
-
-/* Mark the registers used in SCRATCH as being live.  */
-
-static void
-mark_scratch_live (scratch)
-     rtx scratch;
-{
-  register int i;
-  int regno = REGNO (scratch);
-  int lim = regno + HARD_REGNO_NREGS (regno, GET_MODE (scratch));
-
-  for (i = regno; i < lim; i++)
-    regs_ever_live[i] = 1;
-}
 \f
 /* This function handles the tracking of elimination offsets around branches.
 
@@ -2612,7 +2414,7 @@ set_label_offsets (x, insn, initial_p)
 {
   enum rtx_code code = GET_CODE (x);
   rtx tem;
-  int i;
+  unsigned int i;
   struct elim_table *p;
 
   switch (code)
@@ -2649,19 +2451,7 @@ set_label_offsets (x, insn, initial_p)
       else if (x == insn
               && (tem = prev_nonnote_insn (insn)) != 0
               && GET_CODE (tem) == BARRIER)
-       {
-         num_not_at_initial_offset = 0;
-         for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
-           {
-             reg_eliminate[i].offset = reg_eliminate[i].previous_offset
-               = offsets_at[CODE_LABEL_NUMBER (x)][i];
-             if (reg_eliminate[i].can_eliminate
-                 && (reg_eliminate[i].offset
-                     != reg_eliminate[i].initial_offset))
-               num_not_at_initial_offset++;
-           }
-       }
-
+       set_offsets_for_label (insn);
       else
        /* If neither of the above cases is true, compare each offset
           with those previously recorded and suppress any eliminations
@@ -2692,10 +2482,10 @@ set_label_offsets (x, insn, initial_p)
     case ADDR_VEC:
     case ADDR_DIFF_VEC:
       /* Each of the labels in the address vector must be at their initial
-        offsets.  We want the first first for ADDR_VEC and the second
+        offsets.  We want the first field for ADDR_VEC and the second
         field for ADDR_DIFF_VEC.  */
 
-      for (i = 0; i < XVECLEN (x, code == ADDR_DIFF_VEC); i++)
+      for (i = 0; i < (unsigned) XVECLEN (x, code == ADDR_DIFF_VEC); i++)
        set_label_offsets (XVECEXP (x, code == ADDR_DIFF_VEC, i),
                           insn, initial_p);
       return;
@@ -2773,7 +2563,7 @@ static struct rtvec_def *old_asm_operands_vec, *new_asm_operands_vec;
    If INSN is an insn, it is the insn containing X.  If we replace a REG
    in a SET_DEST with an equivalent MEM and INSN is non-zero, write a
    CLOBBER of the pseudo after INSN so find_equiv_regs will know that
-   that the REG is being modified.
+   the REG is being modified.
 
    Alternatively, INSN may be a note (an EXPR_LIST or INSN_LIST).
    That's used when we eliminate in expressions stored in notes.
@@ -2847,27 +2637,6 @@ eliminate_regs (x, mem_mode, insn)
              }
 
        }
-      else if (reg_equiv_memory_loc && reg_equiv_memory_loc[regno]
-              && (reg_equiv_address[regno] || num_not_at_initial_offset))
-       {
-         /* In this case, find_reloads would attempt to either use an
-            incorrect address (if something is not at its initial offset)
-            or substitute an replaced address into an insn (which loses
-            if the offset is changed by some later action).  So we simply
-            return the replaced stack slot (assuming it is changed by
-            elimination) and ignore the fact that this is actually a
-            reference to the pseudo.  Ensure we make a copy of the
-            address in case it is shared.  */
-         new = eliminate_regs (reg_equiv_memory_loc[regno], mem_mode, insn);
-         if (new != reg_equiv_memory_loc[regno])
-           {
-             if (insn != 0 && GET_CODE (insn) != EXPR_LIST
-                 && GET_CODE (insn) != INSN_LIST)
-               REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode, x), insn))
-                 = gen_rtx_EXPR_LIST (REG_EQUAL, new, NULL_RTX);
-             return copy_rtx (new);
-           }
-       }
       return x;
 
     case PLUS:
@@ -3075,6 +2844,7 @@ eliminate_regs (x, mem_mode, insn)
          && reg_equiv_memory_loc != 0
          && reg_equiv_memory_loc[REGNO (SUBREG_REG (x))] != 0)
        {
+#if 0
          new = eliminate_regs (reg_equiv_memory_loc[REGNO (SUBREG_REG (x))],
                                mem_mode, insn);
 
@@ -3095,6 +2865,9 @@ eliminate_regs (x, mem_mode, insn)
              /* Ensure NEW isn't shared in case we have to reload it.  */
              new = copy_rtx (new);
            }
+#else
+         new = SUBREG_REG (x);
+#endif
        }
       else
        new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
@@ -3391,8 +3164,13 @@ eliminate_regs_in_insn (insn, replace)
                if (src == ep->to_rtx)
                  offset = 0, ok = 1;
                else if (GET_CODE (src) == PLUS
-                        && GET_CODE (XEXP (src, 0)) == CONST_INT)
+                        && GET_CODE (XEXP (src, 0)) == CONST_INT
+                        && XEXP (src, 1) == ep->to_rtx)
                  offset = INTVAL (XEXP (src, 0)), ok = 1;
+               else if (GET_CODE (src) == PLUS
+                        && GET_CODE (XEXP (src, 1)) == CONST_INT
+                        && XEXP (src, 0) == ep->to_rtx)
+                 offset = INTVAL (XEXP (src, 1)), ok = 1;
                else if ((prev_insn = prev_nonnote_insn (insn)) != 0
                         && (prev_set = single_set (prev_insn)) != 0
                         && rtx_equal_p (SET_DEST (prev_set), src))
@@ -3452,7 +3230,7 @@ eliminate_regs_in_insn (insn, replace)
         in the insn is the negative of the offset in FROM.  Substitute
         (set (reg) (reg to)) for the insn and change its code.
 
-        We have to do this here, rather than in eliminate_regs, do that we can
+        We have to do this here, rather than in eliminate_regs, so that we can
         change the insn code.  */
 
       if (GET_CODE (SET_SRC (old_set)) == PLUS
@@ -3539,11 +3317,7 @@ eliminate_regs_in_insn (insn, replace)
       val = 1;
     }
 
-  /* Loop through all elimination pairs.  See if any have changed and
-     recalculate the number not at initial offset.
-
-     Compute the maximum offset (minimum offset if the stack does not
-     grow downward) for each elimination pair.
+  /* Loop through all elimination pairs.  See if any have changed.
 
      We also detect a cases where register elimination cannot be done,
      namely, if a register would be both changed and referenced outside a MEM
@@ -3554,7 +3328,6 @@ eliminate_regs_in_insn (insn, replace)
 
      If anything changes, return nonzero.  */
 
-  num_not_at_initial_offset = 0;
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     {
       if (ep->previous_offset != ep->offset && ep->ref_outside_mem)
@@ -3564,78 +3337,300 @@ eliminate_regs_in_insn (insn, replace)
 
       if (ep->previous_offset != ep->offset)
        val = 1;
+    }
+
+ done:
+  /* If we changed something, perform elimination in REG_NOTES.  This is
+     needed even when REPLACE is zero because a REG_DEAD note might refer
+     to a register that we eliminate and could cause a different number
+     of spill registers to be needed in the final reload pass than in
+     the pre-passes.  */
+  if (val && REG_NOTES (insn) != 0)
+    REG_NOTES (insn) = eliminate_regs (REG_NOTES (insn), 0, REG_NOTES (insn));
+
+  if (! replace)
+    pop_obstacks ();
 
+  return val;
+}
+
+/* Loop through all elimination pairs.
+   Recalculate the number not at initial offset.
+
+   Compute the maximum offset (minimum offset if the stack does not
+   grow downward) for each elimination pair.  */
+
+static void
+update_eliminable_offsets ()
+{
+  struct elim_table *ep;
+
+  num_not_at_initial_offset = 0;
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    {
       ep->previous_offset = ep->offset;
       if (ep->can_eliminate && ep->offset != ep->initial_offset)
        num_not_at_initial_offset++;
+    }
+}
+
+/* Given X, a SET or CLOBBER of DEST, if DEST is the target of a register
+   replacement we currently believe is valid, mark it as not eliminable if X
+   modifies DEST in any way other than by adding a constant integer to it.
+
+   If DEST is the frame pointer, we do nothing because we assume that
+   all assignments to the hard frame pointer are nonlocal gotos and are being
+   done at a time when they are valid and do not disturb anything else.
+   Some machines want to eliminate a fake argument pointer with either the
+   frame or stack pointer.  Assignments to the hard frame pointer must not
+   prevent this elimination.
+
+   Called via note_stores from reload before starting its passes to scan
+   the insns of the function.  */
+
+static void
+mark_not_eliminable (dest, x)
+     rtx dest;
+     rtx x;
+{
+  register unsigned int i;
+
+  /* A SUBREG of a hard register here is just changing its mode.  We should
+     not see a SUBREG of an eliminable hard register, but check just in
+     case.  */
+  if (GET_CODE (dest) == SUBREG)
+    dest = SUBREG_REG (dest);
+
+  if (dest == hard_frame_pointer_rtx)
+    return;
+
+  for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
+    if (reg_eliminate[i].can_eliminate && dest == reg_eliminate[i].to_rtx
+       && (GET_CODE (x) != SET
+           || GET_CODE (SET_SRC (x)) != PLUS
+           || XEXP (SET_SRC (x), 0) != dest
+           || GET_CODE (XEXP (SET_SRC (x), 1)) != CONST_INT))
+      {
+       reg_eliminate[i].can_eliminate_previous
+         = reg_eliminate[i].can_eliminate = 0;
+       num_eliminable--;
+      }
+}
+
+/* Verify that the initial elimination offsets did not change since the
+   last call to set_initial_elim_offsets.  This is used to catch cases
+   where something illegal happened during reload_as_needed that could
+   cause incorrect code to be generated if we did not check for it.  */
+static void
+verify_initial_elim_offsets ()
+{
+  int t;
+
+#ifdef ELIMINABLE_REGS
+  struct elim_table *ep;
+
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    {
+      INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, t);
+      if (t != ep->initial_offset)
+       abort ();
+    }
+#else
+  INITIAL_FRAME_POINTER_OFFSET (t);
+  if (t != reg_eliminate[0].initial_offset)
+    abort ();
+#endif  
+}
+
+/* Reset all offsets on eliminable registers to their initial values.  */
+static void
+set_initial_elim_offsets ()
+{
+  struct elim_table *ep = reg_eliminate;
 
-#ifdef STACK_GROWS_DOWNWARD
-      ep->max_offset = MAX (ep->max_offset, ep->offset);
+#ifdef ELIMINABLE_REGS
+  for (; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    {
+      INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->initial_offset);
+      ep->previous_offset = ep->offset = ep->initial_offset;
+    }
 #else
-      ep->max_offset = MIN (ep->max_offset, ep->offset);
+  INITIAL_FRAME_POINTER_OFFSET (ep->initial_offset);
+  ep->previous_offset = ep->offset = ep->initial_offset;
 #endif
+
+  num_not_at_initial_offset = 0;
+}
+
+/* Initialize the known label offsets.
+   Set a known offset for each forced label to be at the initial offset
+   of each elimination.  We do this because we assume that all
+   computed jumps occur from a location where each elimination is
+   at its initial offset.
+   For all other labels, show that we don't know the offsets.  */
+
+static void
+set_initial_label_offsets ()
+{
+  rtx x;
+  bzero ((char *) &offsets_known_at[get_first_label_num ()], num_labels);
+
+  for (x = forced_labels; x; x = XEXP (x, 1))
+    if (XEXP (x, 0))
+      set_label_offsets (XEXP (x, 0), NULL_RTX, 1);
+}
+
+/* Set all elimination offsets to the known values for the code label given
+   by INSN.  */
+static void
+set_offsets_for_label (insn)
+     rtx insn;
+{
+  int i;
+  int label_nr = CODE_LABEL_NUMBER (insn);
+  struct elim_table *ep;
+
+  num_not_at_initial_offset = 0;
+  for (i = 0, ep = reg_eliminate; i < NUM_ELIMINABLE_REGS; ep++, i++)
+    {
+      ep->offset = ep->previous_offset = offsets_at[label_nr][i];
+      if (ep->can_eliminate && ep->offset != ep->initial_offset)
+       num_not_at_initial_offset++;
     }
+}
+
+/* See if anything that happened changes which eliminations are valid.
+   For example, on the Sparc, whether or not the frame pointer can
+   be eliminated can depend on what registers have been used.  We need
+   not check some conditions again (such as flag_omit_frame_pointer)
+   since they can't have changed.  */
+
+static void
+update_eliminables (pset)
+     HARD_REG_SET *pset;
+{
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+  int previous_frame_pointer_needed = frame_pointer_needed;
+#endif
+  struct elim_table *ep;
+
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    if ((ep->from == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED)
+#ifdef ELIMINABLE_REGS
+       || ! CAN_ELIMINATE (ep->from, ep->to)
+#endif
+       )
+      ep->can_eliminate = 0;
+
+  /* Look for the case where we have discovered that we can't replace
+     register A with register B and that means that we will now be
+     trying to replace register A with register C.  This means we can
+     no longer replace register C with register B and we need to disable
+     such an elimination, if it exists.  This occurs often with A == ap,
+     B == sp, and C == fp.  */
+
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    {
+      struct elim_table *op;
+      register int new_to = -1;
 
- done:
-  /* If we changed something, perform elimination in REG_NOTES.  This is
-     needed even when REPLACE is zero because a REG_DEAD note might refer
-     to a register that we eliminate and could cause a different number
-     of spill registers to be needed in the final reload pass than in
-     the pre-passes.  */
-  if (val && REG_NOTES (insn) != 0)
-    REG_NOTES (insn) = eliminate_regs (REG_NOTES (insn), 0, REG_NOTES (insn));
+      if (! ep->can_eliminate && ep->can_eliminate_previous)
+       {
+         /* Find the current elimination for ep->from, if there is a
+            new one.  */
+         for (op = reg_eliminate;
+              op < &reg_eliminate[NUM_ELIMINABLE_REGS]; op++)
+           if (op->from == ep->from && op->can_eliminate)
+             {
+               new_to = op->to;
+               break;
+             }
 
-  if (! replace)
-    pop_obstacks ();
+         /* See if there is an elimination of NEW_TO -> EP->TO.  If so,
+            disable it.  */
+         for (op = reg_eliminate;
+              op < &reg_eliminate[NUM_ELIMINABLE_REGS]; op++)
+           if (op->from == new_to && op->to == ep->to)
+             op->can_eliminate = 0;
+       }
+    }
 
-  return val;
-}
+  /* See if any registers that we thought we could eliminate the previous
+     time are no longer eliminable.  If so, something has changed and we
+     must spill the register.  Also, recompute the number of eliminable
+     registers and see if the frame pointer is needed; it is if there is
+     no elimination of the frame pointer that we can perform.  */
 
-/* Given X, a SET or CLOBBER of DEST, if DEST is the target of a register
-   replacement we currently believe is valid, mark it as not eliminable if X
-   modifies DEST in any way other than by adding a constant integer to it.
+  frame_pointer_needed = 1;
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    {
+      if (ep->can_eliminate && ep->from == FRAME_POINTER_REGNUM
+         && ep->to != HARD_FRAME_POINTER_REGNUM)
+       frame_pointer_needed = 0;
 
-   If DEST is the frame pointer, we do nothing because we assume that
-   all assignments to the hard frame pointer are nonlocal gotos and are being
-   done at a time when they are valid and do not disturb anything else.
-   Some machines want to eliminate a fake argument pointer with either the
-   frame or stack pointer.  Assignments to the hard frame pointer must not
-   prevent this elimination.
+      if (! ep->can_eliminate && ep->can_eliminate_previous)
+       {
+         ep->can_eliminate_previous = 0;
+         SET_HARD_REG_BIT (*pset, ep->from);
+         num_eliminable--;
+       }
+    }
 
-   Called via note_stores from reload before starting its passes to scan
-   the insns of the function.  */
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+  /* If we didn't need a frame pointer last time, but we do now, spill
+     the hard frame pointer.  */
+  if (frame_pointer_needed && ! previous_frame_pointer_needed)
+    SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM);
+#endif
+}
 
+/* Initialize the table of registers to eliminate.  */
 static void
-mark_not_eliminable (dest, x)
-     rtx dest;
-     rtx x;
+init_elim_table ()
 {
-  register int i;
+  struct elim_table *ep;
 
-  /* A SUBREG of a hard register here is just changing its mode.  We should
-     not see a SUBREG of an eliminable hard register, but check just in
-     case.  */
-  if (GET_CODE (dest) == SUBREG)
-    dest = SUBREG_REG (dest);
+  /* Does this function require a frame pointer?  */
 
-  if (dest == hard_frame_pointer_rtx)
-    return;
+  frame_pointer_needed = (! flag_omit_frame_pointer
+#ifdef EXIT_IGNORE_STACK
+                         /* ?? If EXIT_IGNORE_STACK is set, we will not save
+                            and restore sp for alloca.  So we can't eliminate
+                            the frame pointer in that case.  At some point,
+                            we should improve this by emitting the
+                            sp-adjusting insns for this case.  */
+                         || (current_function_calls_alloca
+                             && EXIT_IGNORE_STACK)
+#endif
+                         || FRAME_POINTER_REQUIRED);
 
-  for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
-    if (reg_eliminate[i].can_eliminate && dest == reg_eliminate[i].to_rtx
-       && (GET_CODE (x) != SET
-           || GET_CODE (SET_SRC (x)) != PLUS
-           || XEXP (SET_SRC (x), 0) != dest
-           || GET_CODE (XEXP (SET_SRC (x), 1)) != CONST_INT))
-      {
-       reg_eliminate[i].can_eliminate_previous
-         = reg_eliminate[i].can_eliminate = 0;
-       num_eliminable--;
-      }
+  num_eliminable = 0;
+
+#ifdef ELIMINABLE_REGS
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    {
+      ep->can_eliminate = ep->can_eliminate_previous
+       = (CAN_ELIMINATE (ep->from, ep->to)
+          && ! (ep->to == STACK_POINTER_REGNUM && frame_pointer_needed));
+    }
+#else
+  reg_eliminate[0].can_eliminate = reg_eliminate[0].can_eliminate_previous
+    = ! frame_pointer_needed;
+#endif
+
+  /* Count the number of eliminable registers and build the FROM and TO
+     REG rtx's.  Note that code in gen_rtx will cause, e.g.,
+     gen_rtx (REG, Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx.
+     We depend on this.  */
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    {
+      num_eliminable += ep->can_eliminate;
+      ep->from_rtx = gen_rtx_REG (Pmode, ep->from);
+      ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
+    }
 }
 \f
 /* Kick all pseudos out of hard register REGNO.
-   If GLOBAL is nonzero, try to find someplace else to put them.
    If DUMPFILE is nonzero, log actions taken on that file.
 
    If CANT_ELIMINATE is nonzero, it means that we are doing this spill
@@ -3646,21 +3641,19 @@ mark_not_eliminable (dest, x)
 
    Return nonzero if any pseudos needed to be kicked out.  */
 
-static int
-spill_hard_reg (regno, global, dumpfile, cant_eliminate)
+static void
+spill_hard_reg (regno, dumpfile, cant_eliminate)
      register int regno;
-     int global;
      FILE *dumpfile;
      int cant_eliminate;
 {
-  enum reg_class class = REGNO_REG_CLASS (regno);
-  int something_changed = 0;
   register int i;
 
-  SET_HARD_REG_BIT (forbidden_regs, regno);
-
   if (cant_eliminate)
-    regs_ever_live[regno] = 1;
+    {
+      SET_HARD_REG_BIT (bad_spill_regs_global, regno);
+      regs_ever_live[regno] = 1;
+    }
 
   /* Spill every pseudo reg that was allocated to this reg
      or to something that overlaps this reg.  */
@@ -3672,66 +3665,163 @@ spill_hard_reg (regno, global, dumpfile, cant_eliminate)
            + HARD_REGNO_NREGS (reg_renumber[i],
                                PSEUDO_REGNO_MODE (i))
            > regno))
-      {
-       /* If this register belongs solely to a basic block which needed no
-          spilling of any class that this register is contained in,
-          leave it be, unless we are spilling this register because
-          it was a hard register that can't be eliminated.   */
-
-       if (! cant_eliminate
-           && basic_block_needs[0]
-           && REG_BASIC_BLOCK (i) >= 0
-           && basic_block_needs[(int) class][REG_BASIC_BLOCK (i)] == 0)
-         {
-           enum reg_class *p;
+      SET_REGNO_REG_SET (spilled_pseudos, i);
+}
 
-           for (p = reg_class_superclasses[(int) class];
-                *p != LIM_REG_CLASSES; p++)
-             if (basic_block_needs[(int) *p][REG_BASIC_BLOCK (i)] > 0)
-               break;
+/* I'm getting weird preprocessor errors if I use IOR_HARD_REG_SET
+   from within EXECUTE_IF_SET_IN_REG_SET.  Hence this awkwardness.  */
+static void
+ior_hard_reg_set (set1, set2)
+     HARD_REG_SET *set1, *set2;
+{
+  IOR_HARD_REG_SET (*set1, *set2);
+}
+  
+/* After find_reload_regs has been run for all insn that need reloads,
+   and/or spill_hard_regs was called, this function is used to actually
+   spill pseudo registers and try to reallocate them.  It also sets up the
+   spill_regs array for use by choose_reload_regs.  */
 
-           if (*p == LIM_REG_CLASSES)
-             continue;
-         }
+static int
+finish_spills (global, dumpfile)
+     int global;
+     FILE *dumpfile;
+{
+  struct insn_chain *chain;
+  int something_changed = 0;
+  int i;
+
+  /* Build the spill_regs array for the function.  */
+  /* If there are some registers still to eliminate and one of the spill regs
+     wasn't ever used before, additional stack space may have to be
+     allocated to store this register.  Thus, we may have changed the offset
+     between the stack and frame pointers, so mark that something has changed.
+
+     One might think that we need only set VAL to 1 if this is a call-used
+     register.  However, the set of registers that must be saved by the
+     prologue is not identical to the call-used set.  For example, the
+     register used by the call insn for the return PC is a call-used register,
+     but must be saved by the prologue.  */
+
+  n_spills = 0;
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (TEST_HARD_REG_BIT (used_spill_regs, i))
+      {
+       spill_reg_order[i] = n_spills;
+       spill_regs[n_spills++] = i;
+       if (num_eliminable && ! regs_ever_live[i])
+         something_changed = 1;
+       regs_ever_live[i] = 1;
+      }
+    else
+      spill_reg_order[i] = -1;
 
+  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+    if (REGNO_REG_SET_P (spilled_pseudos, i))
+      {
+       /* Record the current hard register the pseudo is allocated to in
+          pseudo_previous_regs so we avoid reallocating it to the same
+          hard reg in a later pass.  */
+       if (reg_renumber[i] < 0)
+         abort ();
+       SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
        /* Mark it as no longer having a hard register home.  */
        reg_renumber[i] = -1;
        /* We will need to scan everything again.  */
        something_changed = 1;
-       if (global)
-         retry_global_alloc (i, forbidden_regs);
+      }
+
+  /* Retry global register allocation if possible.  */
+  if (global)
+    {
+      bzero ((char *) pseudo_forbidden_regs, max_regno * sizeof (HARD_REG_SET));
+      /* For every insn that needs reloads, set the registers used as spill
+        regs in pseudo_forbidden_regs for every pseudo live across the
+        insn.  */
+      for (chain = insns_need_reload; chain; chain = chain->next_need_reload)
+       {
+         EXECUTE_IF_SET_IN_REG_SET
+           (chain->live_before, FIRST_PSEUDO_REGISTER, i,
+            {
+              ior_hard_reg_set (pseudo_forbidden_regs + i,
+                                &chain->used_spill_regs);
+            });
+         EXECUTE_IF_SET_IN_REG_SET
+           (chain->live_after, FIRST_PSEUDO_REGISTER, i,
+            {
+              ior_hard_reg_set (pseudo_forbidden_regs + i,
+                                &chain->used_spill_regs);
+            });
+       }
 
-       alter_reg (i, regno);
-       if (dumpfile)
+      /* Retry allocating the spilled pseudos.  For each reg, merge the
+        various reg sets that indicate which hard regs can't be used,
+        and call retry_global_alloc.
+         We change spill_pseudos here to only contain pseudos that did not
+        get a new hard register.  */
+      for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+       if (reg_old_renumber[i] != reg_renumber[i])
          {
-           if (reg_renumber[i] == -1)
-             fprintf (dumpfile, " Register %d now on stack.\n\n", i);
-           else
-             fprintf (dumpfile, " Register %d now in %d.\n\n",
-                      i, reg_renumber[i]);
+           HARD_REG_SET forbidden;
+           COPY_HARD_REG_SET (forbidden, bad_spill_regs_global);
+           IOR_HARD_REG_SET (forbidden, pseudo_forbidden_regs[i]);
+           IOR_HARD_REG_SET (forbidden, pseudo_previous_regs[i]);
+           retry_global_alloc (i, forbidden);
+           if (reg_renumber[i] >= 0)
+             CLEAR_REGNO_REG_SET (spilled_pseudos, i);
          }
-      }
-  for (i = 0; i < scratch_list_length; i++)
+    }
+
+  /* Fix up the register information in the insn chain.
+     This involves deleting those of the spilled pseudos which did not get
+     a new hard register home from the live_{before,after} sets.  */
+  for (chain = reload_insn_chain; chain; chain = chain->next)
     {
-      if (scratch_list[i] && REGNO (scratch_list[i]) == regno)
-       {
-         if (! cant_eliminate && basic_block_needs[0]
-             && ! basic_block_needs[(int) class][scratch_block[i]])
-           {
-             enum reg_class *p;
+      HARD_REG_SET used_by_pseudos;
+      HARD_REG_SET used_by_pseudos2;
 
-             for (p = reg_class_superclasses[(int) class];
-                  *p != LIM_REG_CLASSES; p++)
-               if (basic_block_needs[(int) *p][scratch_block[i]] > 0)
-                 break;
+      AND_COMPL_REG_SET (chain->live_before, spilled_pseudos);
+      AND_COMPL_REG_SET (chain->live_after, spilled_pseudos);
 
-             if (*p == LIM_REG_CLASSES)
-               continue;
-           }
-         PUT_CODE (scratch_list[i], SCRATCH);
-         scratch_list[i] = 0;
-         something_changed = 1;
-         continue;
+      /* Mark any unallocated hard regs as available for spills.  That
+        makes inheritance work somewhat better.  */
+      if (chain->need_reload)
+       {
+         REG_SET_TO_HARD_REG_SET (used_by_pseudos, chain->live_before);
+         REG_SET_TO_HARD_REG_SET (used_by_pseudos2, chain->live_after);
+         IOR_HARD_REG_SET (used_by_pseudos, used_by_pseudos2);
+
+         /* Save the old value for the sanity test below.  */
+         COPY_HARD_REG_SET (used_by_pseudos2, chain->used_spill_regs);
+
+         compute_use_by_pseudos (&used_by_pseudos, chain->live_before);
+         compute_use_by_pseudos (&used_by_pseudos, chain->live_after);
+         COMPL_HARD_REG_SET (chain->used_spill_regs, used_by_pseudos);
+         AND_HARD_REG_SET (chain->used_spill_regs, used_spill_regs);
+
+         /* Make sure we only enlarge the set.  */
+         GO_IF_HARD_REG_SUBSET (used_by_pseudos2, chain->used_spill_regs, ok);
+         abort ();
+       ok:;
+       }
+    }
+
+  /* Let alter_reg modify the reg rtx's for the modified pseudos.  */
+  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+    {
+      int regno = reg_renumber[i];
+      if (reg_old_renumber[i] == regno)
+       continue;
+      
+      alter_reg (i, reg_old_renumber[i]);
+      reg_old_renumber[i] = regno;
+      if (dumpfile)
+       {
+         if (regno == -1)
+           fprintf (dumpfile, " Register %d now on stack.\n\n", i);
+         else
+           fprintf (dumpfile, " Register %d now in %d.\n\n",
+                    i, reg_renumber[i]);
        }
     }
 
@@ -3753,9 +3843,11 @@ scan_paradoxical_subregs (x)
   switch (code)
     {
     case REG:
+#if 0
       if (SMALL_REGISTER_CLASSES && REGNO (x) < FIRST_PSEUDO_REGISTER
          && REG_USERVAR_P (x))
-       SET_HARD_REG_BIT (forbidden_regs, REGNO (x));
+       SET_HARD_REG_BIT (bad_spill_regs_global, REGNO (x));
+#endif
       return;
 
     case CONST_INT:
@@ -3796,101 +3888,105 @@ scan_paradoxical_subregs (x)
 \f
 static int
 hard_reg_use_compare (p1p, p2p)
-  const GENERIC_PTR p1p;
-  const GENERIC_PTR p2p;
-{
-  struct hard_reg_n_uses *p1 = (struct hard_reg_n_uses *)p1p,
-                        *p2 = (struct hard_reg_n_uses *)p2p;
-  int tem = p1->uses - p2->uses;
-  if (tem != 0) return tem;
+     const GENERIC_PTR p1p;
+     const GENERIC_PTR p2p;
+{  
+  struct hard_reg_n_uses *p1 = (struct hard_reg_n_uses *)p1p;
+  struct hard_reg_n_uses *p2 = (struct hard_reg_n_uses *)p2p;
+  int bad1 = TEST_HARD_REG_BIT (bad_spill_regs, p1->regno);
+  int bad2 = TEST_HARD_REG_BIT (bad_spill_regs, p2->regno);
+  if (bad1 && bad2)
+    return p1->regno - p2->regno;
+  if (bad1)
+    return 1;
+  if (bad2)
+    return -1;
+  if (p1->uses > p2->uses)
+    return 1;
+  if (p1->uses < p2->uses)
+    return -1;
   /* If regs are equally good, sort by regno,
      so that the results of qsort leave nothing to chance.  */
   return p1->regno - p2->regno;
 }
 
+/* Used for communication between order_regs_for_reload and count_pseudo.
+   Used to avoid counting one pseudo twice.  */
+static regset pseudos_counted;
+
+/* Update the costs in N_USES, considering that pseudo REG is live.  */
+static void
+count_pseudo (n_uses, reg)
+     struct hard_reg_n_uses *n_uses;
+     int reg;
+{
+  int r = reg_renumber[reg];
+  int nregs;
+
+  if (REGNO_REG_SET_P (pseudos_counted, reg))
+    return;
+  SET_REGNO_REG_SET (pseudos_counted, reg);
+
+  if (r < 0)
+    abort ();
+
+  nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg));
+  while (nregs-- > 0)
+    n_uses[r++].uses += REG_N_REFS (reg);  
+}
 /* Choose the order to consider regs for use as reload registers
    based on how much trouble would be caused by spilling one.
    Store them in order of decreasing preference in potential_reload_regs.  */
 
 static void
-order_regs_for_reload (global)
-     int global;
+order_regs_for_reload (chain)
+     struct insn_chain *chain;
 {
   register int i;
   register int o = 0;
-  int large = 0;
-
   struct hard_reg_n_uses hard_reg_n_uses[FIRST_PSEUDO_REGISTER];
 
-  CLEAR_HARD_REG_SET (bad_spill_regs);
+  pseudos_counted = ALLOCA_REG_SET ();
 
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    potential_reload_regs[i] = -1;
+  COPY_HARD_REG_SET (bad_spill_regs, bad_spill_regs_global);
 
   /* Count number of uses of each hard reg by pseudo regs allocated to it
      and then order them by decreasing use.  */
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
-      hard_reg_n_uses[i].uses = 0;
-      hard_reg_n_uses[i].regno = i;
-    }
-
-  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-    {
-      int regno = reg_renumber[i];
-      if (regno >= 0)
-       {
-         int lim = regno + HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
-         while (regno < lim)
-           {
-             /* If allocated by local-alloc, show more uses since
-                we're not going to be able to reallocate it, but
-                we might if allocated by global alloc.  */
-             if (global && reg_allocno[i] < 0)
-               hard_reg_n_uses[regno].uses += (REG_N_REFS (i) + 1) / 2;
-
-             hard_reg_n_uses[regno++].uses += REG_N_REFS (i);
-           }
-       }
-      large += REG_N_REFS (i);
-    }
+      int j;
 
-  /* Now fixed registers (which cannot safely be used for reloading)
-     get a very high use count so they will be considered least desirable.
-     Registers used explicitly in the rtl code are almost as bad.  */
+      hard_reg_n_uses[i].regno = i;
+      hard_reg_n_uses[i].uses = 0;
 
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    {
-      if (fixed_regs[i])
+      /* Test the various reasons why we can't use a register for
+        spilling in this insn.  */
+      if (fixed_regs[i]
+         || REGNO_REG_SET_P (chain->live_before, i)
+         || REGNO_REG_SET_P (chain->live_after, i))
        {
-         hard_reg_n_uses[i].uses += 2 * large + 2;
          SET_HARD_REG_BIT (bad_spill_regs, i);
+         continue;
        }
-      else if (regs_explicitly_used[i])
-       {
-         hard_reg_n_uses[i].uses += large + 1;
-         if (! SMALL_REGISTER_CLASSES)
-           /* ??? We are doing this here because of the potential
-            that bad code may be generated if a register explicitly
-            used in an insn was used as a spill register for that
-            insn.  But not using these are spill registers may lose
-            on some machine.  We'll have to see how this works out.  */
-           SET_HARD_REG_BIT (bad_spill_regs, i);
-       }
-    }
-  hard_reg_n_uses[HARD_FRAME_POINTER_REGNUM].uses += 2 * large + 2;
-  SET_HARD_REG_BIT (bad_spill_regs, HARD_FRAME_POINTER_REGNUM);
 
-#ifdef ELIMINABLE_REGS
-  /* If registers other than the frame pointer are eliminable, mark them as
-     poor choices.  */
-  for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
-    {
-      hard_reg_n_uses[reg_eliminate[i].from].uses += 2 * large + 2;
-      SET_HARD_REG_BIT (bad_spill_regs, reg_eliminate[i].from);
+      /* Now find out which pseudos are allocated to it, and update
+        hard_reg_n_uses.  */
+      CLEAR_REG_SET (pseudos_counted);
+
+      EXECUTE_IF_SET_IN_REG_SET
+       (chain->live_before, FIRST_PSEUDO_REGISTER, j,
+        {
+          count_pseudo (hard_reg_n_uses, j);
+        });
+      EXECUTE_IF_SET_IN_REG_SET
+       (chain->live_after, FIRST_PSEUDO_REGISTER, j,
+        {
+          count_pseudo (hard_reg_n_uses, j);
+        });
     }
-#endif
+
+  FREE_REG_SET (pseudos_counted);
 
   /* Prefer registers not so far used, for use in temporary loading.
      Among them, if REG_ALLOC_ORDER is defined, use that order.
@@ -3901,18 +3997,21 @@ order_regs_for_reload (global)
     {
       int regno = reg_alloc_order[i];
 
-      if (hard_reg_n_uses[regno].uses == 0)
+      if (hard_reg_n_uses[regno].uses == 0
+         && ! TEST_HARD_REG_BIT (bad_spill_regs, regno))
        potential_reload_regs[o++] = regno;
     }
 #else
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
-      if (hard_reg_n_uses[i].uses == 0 && call_used_regs[i])
+      if (hard_reg_n_uses[i].uses == 0 && call_used_regs[i]
+         && ! TEST_HARD_REG_BIT (bad_spill_regs, i))
        potential_reload_regs[o++] = i;
     }
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
-      if (hard_reg_n_uses[i].uses == 0 && ! call_used_regs[i])
+      if (hard_reg_n_uses[i].uses == 0 && ! call_used_regs[i]
+         && ! TEST_HARD_REG_BIT (bad_spill_regs, i))
        potential_reload_regs[o++] = i;
     }
 #endif
@@ -3925,21 +4024,14 @@ order_regs_for_reload (global)
      registers will be at the end of this list.  */
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if (hard_reg_n_uses[i].uses != 0)
+    if (hard_reg_n_uses[i].uses != 0
+       && ! TEST_HARD_REG_BIT (bad_spill_regs, hard_reg_n_uses[i].regno))
+      potential_reload_regs[o++] = hard_reg_n_uses[i].regno;
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (TEST_HARD_REG_BIT (bad_spill_regs, hard_reg_n_uses[i].regno))
       potential_reload_regs[o++] = hard_reg_n_uses[i].regno;
 }
 \f
-/* Used in reload_as_needed to sort the spilled regs.  */
-
-static int
-compare_spill_regs (r1p, r2p)
-     const GENERIC_PTR r1p;
-     const GENERIC_PTR r2p;
-{
-  short r1 = *(short *)r1p, r2 = *(short *)r2p;
-  return r1 - r2;
-}
-
 /* Reload pseudo-registers into hard regs around each insn as needed.
    Additional register load insns are output before the insn that needs it
    and perhaps store insns after insns that modify the reloaded pseudo reg.
@@ -3950,15 +4042,12 @@ compare_spill_regs (r1p, r2p)
    as the insns are scanned.  */
 
 static void
-reload_as_needed (first, live_known)
-     rtx first;
+reload_as_needed (live_known)
      int live_known;
 {
-  register rtx insn;
+  struct insn_chain *chain;
   register int i;
-  int this_block = 0;
   rtx x;
-  rtx after_call = 0;
 
   bzero ((char *) spill_reg_rtx, sizeof spill_reg_rtx);
   bzero ((char *) spill_reg_store, sizeof spill_reg_store);
@@ -3967,84 +4056,23 @@ reload_as_needed (first, live_known)
   reg_has_output_reload = (char *) alloca (max_regno);
   CLEAR_HARD_REG_SET (reg_reloaded_valid);
 
-  /* Reset all offsets on eliminable registers to their initial values.  */
-#ifdef ELIMINABLE_REGS
-  for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
-    {
-      INITIAL_ELIMINATION_OFFSET (reg_eliminate[i].from, reg_eliminate[i].to,
-                                 reg_eliminate[i].initial_offset);
-      reg_eliminate[i].previous_offset
-       = reg_eliminate[i].offset = reg_eliminate[i].initial_offset;
-    }
-#else
-  INITIAL_FRAME_POINTER_OFFSET (reg_eliminate[0].initial_offset);
-  reg_eliminate[0].previous_offset
-    = reg_eliminate[0].offset = reg_eliminate[0].initial_offset;
-#endif
-
-  num_not_at_initial_offset = 0;
-
-  /* Order the spilled regs, so that allocate_reload_regs can guarantee to
-     pack registers with group needs.  */
-  if (n_spills > 1)
-    {
-      qsort (spill_regs, n_spills, sizeof (short), compare_spill_regs);
-      for (i = 0; i < n_spills; i++)
-       spill_reg_order[spill_regs[i]] = i;
-    }
+  set_initial_elim_offsets ();
 
-  for (insn = first; insn;)
+  for (chain = reload_insn_chain; chain; chain = chain->next)
     {
-      register rtx next = NEXT_INSN (insn);
-
-      /* Notice when we move to a new basic block.  */
-      if (live_known && this_block + 1 < n_basic_blocks
-         && insn == basic_block_head[this_block+1])
-       ++this_block;
+      rtx prev;
+      rtx insn = chain->insn;
+      rtx old_next = NEXT_INSN (insn);
 
       /* If we pass a label, copy the offsets from the label information
         into the current offsets of each elimination.  */
       if (GET_CODE (insn) == CODE_LABEL)
-       {
-         num_not_at_initial_offset = 0;
-         for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
-           {
-             reg_eliminate[i].offset = reg_eliminate[i].previous_offset
-               = offsets_at[CODE_LABEL_NUMBER (insn)][i];
-             if (reg_eliminate[i].can_eliminate
-                 && (reg_eliminate[i].offset
-                     != reg_eliminate[i].initial_offset))
-               num_not_at_initial_offset++;
-           }
-       }
+       set_offsets_for_label (insn);
 
       else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
        {
-         rtx avoid_return_reg = 0;
          rtx oldpat = PATTERN (insn);
 
-         /* Set avoid_return_reg if this is an insn
-            that might use the value of a function call.  */
-         if (SMALL_REGISTER_CLASSES && GET_CODE (insn) == CALL_INSN)
-           {
-             if (GET_CODE (PATTERN (insn)) == SET)
-               after_call = SET_DEST (PATTERN (insn));
-             else if (GET_CODE (PATTERN (insn)) == PARALLEL
-                      && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
-               after_call = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
-             else
-               after_call = 0;
-           }
-         else if (SMALL_REGISTER_CLASSES && after_call != 0
-                  && !(GET_CODE (PATTERN (insn)) == SET
-                       && SET_DEST (PATTERN (insn)) == stack_pointer_rtx)
-                  && GET_CODE (PATTERN (insn)) != USE)
-           {
-             if (reg_referenced_p (after_call, PATTERN (insn)))
-               avoid_return_reg = after_call;
-             after_call = 0;
-           }
-
          /* If this is a USE and CLOBBER of a MEM, ensure that any
             references to eliminable registers have been removed.  */
 
@@ -4058,17 +4086,25 @@ reload_as_needed (first, live_known)
 
          /* If we need to do register elimination processing, do so.
             This might delete the insn, in which case we are done.  */
-         if (num_eliminable && GET_MODE (insn) == QImode)
+         if (num_eliminable && chain->need_elim)
            {
              eliminate_regs_in_insn (insn, 1);
              if (GET_CODE (insn) == NOTE)
                {
-                 insn = next;
+                 update_eliminable_offsets ();
                  continue;
                }
            }
 
-         if (GET_MODE (insn) == VOIDmode)
+         /* If need_elim is nonzero but need_reload is zero, one might think
+            that we could simply set n_reloads to 0.  However, find_reloads
+            could have done some manipulation of the insn (such as swapping
+            commutative operands), and these manipulations are lost during
+            the first pass for every insn that needs register elimination.
+            So the actions of find_reloads must be redone here.  */
+
+         if (! chain->need_elim && ! chain->need_reload
+             && ! chain->need_operand_change)
            n_reloads = 0;
          /* First find the pseudo regs that must be reloaded for this insn.
             This info is returned in the tables reload_... (see reload.h).
@@ -4083,32 +4119,21 @@ reload_as_needed (first, live_known)
                            spill_reg_order);
            }
 
+         if (num_eliminable && chain->need_elim)
+           update_eliminable_offsets ();
+
          if (n_reloads > 0)
            {
-             rtx prev = PREV_INSN (insn), next = NEXT_INSN (insn);
+             rtx next = NEXT_INSN (insn);
              rtx p;
-             int class;
-
-             /* If this block has not had spilling done for a
-                particular clas and we have any non-optionals that need a
-                spill reg in that class, abort.  */
-
-             for (class = 0; class < N_REG_CLASSES; class++)
-               if (basic_block_needs[class] != 0
-                   && basic_block_needs[class][this_block] == 0)
-                 for (i = 0; i < n_reloads; i++)
-                   if (class == (int) reload_reg_class[i]
-                       && reload_reg_rtx[i] == 0
-                       && ! reload_optional[i]
-                       && (reload_in[i] != 0 || reload_out[i] != 0
-                           || reload_secondary_p[i] != 0))
-                     fatal_insn ("Non-optional registers need a spill register", insn);
+
+             prev = PREV_INSN (insn);
 
              /* Now compute which reload regs to reload them into.  Perhaps
                 reusing reload regs from previous insns, or else output
                 load insns to reload them.  Maybe output store insns too.
                 Record the choices of reload reg in reload_reg_rtx.  */
-             choose_reload_regs (insn, avoid_return_reg);
+             choose_reload_regs (chain);
 
              /* Merge any reloads that we didn't combine for fear of 
                 increasing the number of spill registers needed but now
@@ -4118,7 +4143,7 @@ reload_as_needed (first, live_known)
 
              /* Generate the insns to reload operands into or out of
                 their reload regs.  */
-             emit_reload_insns (insn);
+             emit_reload_insns (chain);
 
              /* Substitute the chosen reload regs from reload_reg_rtx
                 into the insn's body (or perhaps into the bodies of other
@@ -4154,12 +4179,65 @@ reload_as_needed (first, live_known)
 
          /* There may have been CLOBBER insns placed after INSN.  So scan
             between INSN and NEXT and use them to forget old reloads.  */
-         for (x = NEXT_INSN (insn); x != next; x = NEXT_INSN (x))
+         for (x = NEXT_INSN (insn); x != old_next; x = NEXT_INSN (x))
            if (GET_CODE (x) == INSN && GET_CODE (PATTERN (x)) == CLOBBER)
              note_stores (PATTERN (x), forget_old_reloads_1);
 
 #ifdef AUTO_INC_DEC
          /* Likewise for regs altered by auto-increment in this insn.
+            REG_INC notes have been changed by reloading:
+            find_reloads_address_1 records substitutions for them,
+            which have been performed by subst_reloads above.  */
+         for (i = n_reloads - 1; i >= 0; i--)
+           {
+             rtx in_reg = reload_in_reg[i];
+             if (in_reg)
+               {
+                 enum rtx_code code = GET_CODE (in_reg);
+                 /* PRE_INC / PRE_DEC will have the reload register ending up
+                    with the same value as the stack slot, but that doesn't
+                    hold true for POST_INC / POST_DEC.  Either we have to
+                    convert the memory access to a true POST_INC / POST_DEC,
+                    or we can't use the reload register for inheritance.  */
+                 if ((code == POST_INC || code == POST_DEC)
+                     && TEST_HARD_REG_BIT (reg_reloaded_valid,
+                                           REGNO (reload_reg_rtx[i]))
+                     /* Make sure it is the inc/dec pseudo, and not
+                        some other (e.g. output operand) pseudo.  */
+                     && (reg_reloaded_contents[REGNO (reload_reg_rtx[i])]
+                         == REGNO (XEXP (in_reg, 0))))
+                                             
+                   {
+                     rtx reload_reg = reload_reg_rtx[i];
+                     enum machine_mode mode = GET_MODE (reload_reg);
+                     int n = 0;
+                     rtx p;
+
+                     for (p = PREV_INSN (old_next); p != prev; p = PREV_INSN (p))
+                       {
+                         /* We really want to ignore REG_INC notes here, so
+                            use PATTERN (p) as argument to reg_set_p .  */
+                         if (reg_set_p (reload_reg, PATTERN (p)))
+                           break;
+                         n = count_occurrences (PATTERN (p), reload_reg);
+                         if (! n)
+                           continue;
+                         if (n == 1)
+                           n = validate_replace_rtx (reload_reg,
+                                                     gen_rtx (code, mode,
+                                                              reload_reg), p);
+                         break;
+                       }
+                     if (n == 1)
+                       REG_NOTES (p) = gen_rtx_EXPR_LIST (REG_INC, reload_reg,
+                                                          REG_NOTES (p));
+                     else
+                       forget_old_reloads_1 (XEXP (in_reg, 0), NULL_RTX);
+                   }
+               }
+           }
+#if 0 /* ??? Is this code obsolete now?  Need to check carefully. */
+         /* Likewise for regs altered by auto-increment in this insn.
             But note that the reg-notes are not changed by reloading:
             they still contain the pseudo-regs, not the spill regs.  */
          for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
@@ -4176,6 +4254,7 @@ reload_as_needed (first, live_known)
                  forget_old_reloads_1 (XEXP (x, 0), NULL_RTX);
              }
 #endif
+#endif
        }
       /* A reload reg's contents are unknown after a label.  */
       if (GET_CODE (insn) == CODE_LABEL)
@@ -4196,8 +4275,6 @@ reload_as_needed (first, live_known)
          CLEAR_HARD_REG_BIT (reg_reloaded_valid, i);
 #endif
 
-      insn = next;
-
 #ifdef USE_C_ALLOCA
       alloca (0);
 #endif
@@ -4214,7 +4291,7 @@ reload_as_needed (first, live_known)
 static void
 forget_old_reloads_1 (x, ignored)
      rtx x;
-     rtx ignored;
+     rtx ignored ATTRIBUTE_UNUSED;
 {
   register int regno;
   int nr;
@@ -4336,6 +4413,10 @@ static HARD_REG_SET reload_reg_used_at_all;
    in the group.  */
 static HARD_REG_SET reload_reg_used_for_inherit;
 
+/* Records which hard regs are allocated to a pseudo during any point of the
+   current insn.  */
+static HARD_REG_SET reg_used_by_pseudo;
+
 /* Mark reg REGNO as in use for a reload of the sort spec'd by OPNUM and
    TYPE. MODE is used to indicate how many consecutive regs are
    actually used.  */
@@ -4413,57 +4494,104 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
      enum machine_mode mode;
 {
   int nregs = HARD_REGNO_NREGS (regno, mode);
+  int start_regno, end_regno;
   int i;
+  /* A complication is that for some reload types, inheritance might
+     allow multiple reloads of the same types to share a reload register.
+     We set check_opnum if we have to check only reloads with the same
+     operand number, and check_any if we have to check all reloads.  */
+  int check_opnum = 0;
+  int check_any = 0;
+  HARD_REG_SET *used_in_set;
 
-  for (i = regno; i < nregs + regno; i++)
+  switch (type)
     {
-      switch (type)
-       {
-       case RELOAD_OTHER:
-         CLEAR_HARD_REG_BIT (reload_reg_used, i);
-         break;
+    case RELOAD_OTHER:
+      used_in_set = &reload_reg_used;
+      break;
 
-       case RELOAD_FOR_INPUT_ADDRESS:
-         CLEAR_HARD_REG_BIT (reload_reg_used_in_input_addr[opnum], i);
-         break;
+    case RELOAD_FOR_INPUT_ADDRESS:
+      used_in_set = &reload_reg_used_in_input_addr[opnum];
+      break;
 
-       case RELOAD_FOR_INPADDR_ADDRESS:
-         CLEAR_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[opnum], i);
-         break;
+    case RELOAD_FOR_INPADDR_ADDRESS:
+      check_opnum = 1;
+      used_in_set = &reload_reg_used_in_inpaddr_addr[opnum];
+      break;
 
-       case RELOAD_FOR_OUTPUT_ADDRESS:
-         CLEAR_HARD_REG_BIT (reload_reg_used_in_output_addr[opnum], i);
-         break;
+    case RELOAD_FOR_OUTPUT_ADDRESS:
+      used_in_set = &reload_reg_used_in_output_addr[opnum];
+      break;
 
-       case RELOAD_FOR_OUTADDR_ADDRESS:
-         CLEAR_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], i);
-         break;
+    case RELOAD_FOR_OUTADDR_ADDRESS:
+      check_opnum = 1;
+      used_in_set = &reload_reg_used_in_outaddr_addr[opnum];
+      break;
 
-       case RELOAD_FOR_OPERAND_ADDRESS:
-         CLEAR_HARD_REG_BIT (reload_reg_used_in_op_addr, i);
-         break;
+    case RELOAD_FOR_OPERAND_ADDRESS:
+      used_in_set = &reload_reg_used_in_op_addr;
+      break;
 
-       case RELOAD_FOR_OPADDR_ADDR:
-         CLEAR_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, i);
-         break;
+    case RELOAD_FOR_OPADDR_ADDR:
+      check_any = 1;
+      used_in_set = &reload_reg_used_in_op_addr_reload;
+      break;
 
-       case RELOAD_FOR_OTHER_ADDRESS:
-         CLEAR_HARD_REG_BIT (reload_reg_used_in_other_addr, i);
-         break;
+    case RELOAD_FOR_OTHER_ADDRESS:
+      used_in_set = &reload_reg_used_in_other_addr;
+      check_any = 1;
+      break;
 
-       case RELOAD_FOR_INPUT:
-         CLEAR_HARD_REG_BIT (reload_reg_used_in_input[opnum], i);
-         break;
+    case RELOAD_FOR_INPUT:
+      used_in_set = &reload_reg_used_in_input[opnum];
+      break;
 
-       case RELOAD_FOR_OUTPUT:
-         CLEAR_HARD_REG_BIT (reload_reg_used_in_output[opnum], i);
-         break;
+    case RELOAD_FOR_OUTPUT:
+      used_in_set = &reload_reg_used_in_output[opnum];
+      break;
 
-       case RELOAD_FOR_INSN:
-         CLEAR_HARD_REG_BIT (reload_reg_used_in_insn, i);
-         break;
+    case RELOAD_FOR_INSN:
+      used_in_set = &reload_reg_used_in_insn;
+      break;
+    default:
+      abort ();
+    }
+  /* We resolve conflicts with remaining reloads of the same type by
+     excluding the intervals of of reload registers by them from the
+     interval of freed reload registers.  Since we only keep track of
+     one set of interval bounds, we might have to exclude somewhat
+     more then what would be necessary if we used a HARD_REG_SET here.
+     But this should only happen very infrequently, so there should
+     be no reason to worry about it.  */
+    
+  start_regno = regno;
+  end_regno = regno + nregs;
+  if (check_opnum || check_any)
+    {
+      for (i = n_reloads - 1; i >= 0; i--)
+       {
+         if (reload_when_needed[i] == type
+             && (check_any || reload_opnum[i] == opnum)
+             && reload_reg_rtx[i])
+           {
+             int conflict_start = true_regnum (reload_reg_rtx[i]);
+             int conflict_end
+               = (conflict_start
+                  + HARD_REGNO_NREGS (conflict_start, reload_mode[i]));
+
+             /* If there is an overlap with the first to-be-freed register,
+                adjust the interval start.  */
+             if (conflict_start <= start_regno && conflict_end > start_regno)
+               start_regno = conflict_end;
+             /* Otherwise, if there is a conflict with one of the other
+                to-be-freed registers, adjust the interval end.  */
+             if (conflict_start > start_regno && conflict_start < end_regno)
+               end_regno = conflict_start;
+           }
        }
     }
+  for (i = start_regno; i < end_regno; i++)
+    CLEAR_HARD_REG_BIT (*used_in_set, i);
 }
 
 /* 1 if reg REGNO is free as a reload reg for a reload of the sort
@@ -4537,7 +4665,7 @@ reload_reg_free_p (regno, opnum, type)
 
     case RELOAD_FOR_INPADDR_ADDRESS:
       /* Can't use a register if it is used for an input address
-         address for this operand or used as an input in an earlier
+         for this operand or used as an input in an earlier
          one.  */
       if (TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[opnum], regno))
        return 0;
@@ -4562,7 +4690,7 @@ reload_reg_free_p (regno, opnum, type)
 
     case RELOAD_FOR_OUTADDR_ADDRESS:
       /* Can't use a register if it is used for an output address
-         address for this operand or used as an output in this or a
+         for this operand or used as an output in this or a
          later operand.  */
       if (TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], regno))
        return 0;
@@ -4626,23 +4754,48 @@ reload_reg_free_p (regno, opnum, type)
 
    We can assume that the reload reg was already tested for availability
    at the time it is needed, and we should not check this again,
-   in case the reg has already been marked in use.  */
+   in case the reg has already been marked in use.
+
+   However, if EQUIV is set, we are checking the availability of a register
+   holding an equivalence to the value to be loaded into the reload register,
+   not the availability of the reload register itself.
+
+   This is still less stringent than what reload_reg_free_p checks; for
+   example, compare the checks for RELOAD_OTHER.  */
 
 static int
-reload_reg_free_before_p (regno, opnum, type)
+reload_reg_free_before_p (regno, opnum, type, equiv)
      int regno;
      int opnum;
      enum reload_type type;
+     int equiv;
 {
   int i;
 
+  /* The code to handle EQUIV below is wrong.
+
+     If we wnat to know if a value in a particular reload register is available
+     at a particular point in time during reloading, we must check *all*
+     prior reloads to see if they clobber the value.
+
+     Note this is significantly different from determining when a register is
+     free for usage in a reload!
+
+     This change is temporary.  It will go away.  */
+  if (equiv)
+    return 0;
+
   switch (type)
     {
     case RELOAD_FOR_OTHER_ADDRESS:
       /* These always come first.  */
+      if (equiv && TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno))
+       return 0;
       return 1;
 
     case RELOAD_OTHER:
+      if (equiv && TEST_HARD_REG_BIT (reload_reg_used, regno))
+       return 0;
       return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
 
       /* If this use is for part of the insn,
@@ -4654,15 +4807,25 @@ reload_reg_free_before_p (regno, opnum, type)
         the first place, since we know that it was allocated.  */
 
     case RELOAD_FOR_OUTPUT_ADDRESS:
+      if (equiv
+         && TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[opnum], regno))
+       return 0;
+      /* Earlier reloads include RELOAD_FOR_OUTADDR_ADDRESS reloads.  */
+      if (TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], regno))
+       return 0;
+      /* ... fall through ...  */
     case RELOAD_FOR_OUTADDR_ADDRESS:
+      if (equiv
+         && (TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], regno)
+             || TEST_HARD_REG_BIT (reload_reg_used, regno)))
+       return 0;
       /* Earlier reloads are for earlier outputs or their addresses,
         any RELOAD_FOR_INSN reloads, any inputs or their addresses, or any
         RELOAD_FOR_OTHER_ADDRESS reloads (we know it can't conflict with
         RELOAD_OTHER)..  */
       for (i = 0; i < opnum; i++)
        if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
-           || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno)
-           || TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
+           || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno))
          return 0;
 
       if (TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno))
@@ -4671,38 +4834,25 @@ reload_reg_free_before_p (regno, opnum, type)
       for (i = 0; i < reload_n_operands; i++)
        if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
            || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno)
-           || TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
+           || TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno)
+           || TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
          return 0;
 
       return (! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno)
              && ! TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno)
+             && ! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno)
              && ! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno));
                                   
     case RELOAD_FOR_OUTPUT:
-      /* This can't be used in the output address for this operand and
-        anything that can't be used for it, except that we've already
-        tested for RELOAD_FOR_INSN objects.  */
+    case RELOAD_FOR_INSN:
+      /* There is no reason to call this function for output reloads, thus
+        anything we'd put here wouldn't be tested.  So just abort.  */
+       abort ();
 
-      if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[opnum], regno)
-         || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], regno))
+    case RELOAD_FOR_OPERAND_ADDRESS:
+      if (equiv && TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno))
        return 0;
 
-      for (i = 0; i < opnum; i++)
-       if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
-           || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno)
-           || TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
-         return 0;
-
-      for (i = 0; i < reload_n_operands; i++)
-       if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
-           || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno)
-           || TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno)
-           || TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno))
-         return 0;
-
-      return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
-
-    case RELOAD_FOR_OPERAND_ADDRESS:
       /* Earlier reloads include RELOAD_FOR_OPADDR_ADDR reloads.  */
       if (TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno))
        return 0;
@@ -4710,7 +4860,15 @@ reload_reg_free_before_p (regno, opnum, type)
       /* ... fall through ...  */
 
     case RELOAD_FOR_OPADDR_ADDR:
-    case RELOAD_FOR_INSN:
+      if (equiv)
+       {
+         if (TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno)
+             || TEST_HARD_REG_BIT (reload_reg_used, regno))
+           return 0;
+         for (i = 0; i < reload_n_operands; i++)
+           if (TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
+             return 0;
+       }
       /* These can't conflict with inputs, or each other, so all we have to
         test is input addresses and the addresses of OTHER items.  */
 
@@ -4722,11 +4880,16 @@ reload_reg_free_before_p (regno, opnum, type)
       return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
 
     case RELOAD_FOR_INPUT:
+      if (equiv && TEST_HARD_REG_BIT (reload_reg_used, regno))
+       return 0;
+
       /* The only things earlier are the address for this and
         earlier inputs, other inputs (which we know we don't conflict
-        with), and addresses of RELOAD_OTHER objects.  */
+        with), and addresses of RELOAD_OTHER objects.
+        We can ignore the conflict with addresses of this operand, since
+         when we inherit this operand, its address reloads are discarded.  */
 
-      for (i = 0; i <= opnum; i++)
+      for (i = 0; i < opnum; i++)
        if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
            || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
          return 0;
@@ -4734,7 +4897,14 @@ reload_reg_free_before_p (regno, opnum, type)
       return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
 
     case RELOAD_FOR_INPUT_ADDRESS:
+      /* Earlier reloads include RELOAD_FOR_INPADDR_ADDRESS reloads.  */
+      if (TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[opnum], regno))
+       return 0;
+      /* ... fall through ...  */
     case RELOAD_FOR_INPADDR_ADDRESS:
+      if (equiv && TEST_HARD_REG_BIT (reload_reg_used, regno))
+       return 0;
+
       /* Similarly, all we have to check is for use in earlier inputs'
         addresses.  */
       for (i = 0; i < opnum; i++)
@@ -4976,6 +5146,162 @@ rtx reload_override_in[MAX_RELOADS];
    or -1 if we did not need a register for this reload.  */
 int reload_spill_index[MAX_RELOADS];
 
+/* Return 1 if the value in reload reg REGNO, as used by a reload
+   needed for the part of the insn specified by OPNUM and TYPE,
+   may be used to load VALUE into it.
+
+   Other read-only reloads with the same value do not conflict
+   unless OUT is non-zero and these other reloads have to live while
+   output reloads live.
+
+   RELOADNUM is the number of the reload we want to load this value for;
+   a reload does not conflict with itself.
+
+   The caller has to make sure that there is no conflict with the return
+   register.  */
+static int
+reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum)
+     int regno;
+     int opnum;
+     enum reload_type type;
+     rtx value, out;
+     int reloadnum;
+{
+  int time1;
+  int i;
+
+  /* We use some pseudo 'time' value to check if the lifetimes of the
+     new register use would overlap with the one of a previous reload
+     that is not read-only or uses a different value.
+     The 'time' used doesn't have to be linear in any shape or form, just
+     monotonic.
+     Some reload types use different 'buckets' for each operand.
+     So there are MAX_RECOG_OPERANDS different time values for each
+     such reload type.
+     We compute TIME1 as the time when the register for the prospective
+     new reload ceases to be live, and TIME2 for each existing
+     reload as the time when that the reload register of that reload
+     becomes live.
+     Where there is little to be gained by exact lifetime calculations,
+     we just make conservative assumptions, i.e. a longer lifetime;
+     this is done in the 'default:' cases.  */
+  switch (type)
+    {
+    case RELOAD_FOR_OTHER_ADDRESS:
+      time1 = 0;
+      break;
+    /* For each input, we might have a sequence of RELOAD_FOR_INPADDR_ADDRESS,
+       RELOAD_FOR_INPUT_ADDRESS and RELOAD_FOR_INPUT.  By adding 0 / 1 / 2 ,
+       respectively, to the time values for these, we get distinct time
+       values.  To get distinct time values for each operand, we have to
+       multiply opnum by at least three.  We round that up to four because
+       multiply by four is often cheaper.  */
+    case RELOAD_FOR_INPADDR_ADDRESS:
+      time1 = opnum * 4 + 1;
+      break;
+    case RELOAD_FOR_INPUT_ADDRESS:
+      time1 = opnum * 4 + 2;
+      break;
+    case RELOAD_FOR_OPADDR_ADDR:
+    /* opnum * 4 + 3 < opnum * 4 + 4
+       <= (MAX_RECOG_OPERANDS - 1) * 4 + 4 == MAX_RECOG_OPERANDS * 4 */
+      time1 = MAX_RECOG_OPERANDS * 4;
+      break;
+    case RELOAD_FOR_INPUT:
+      /* All RELOAD_FOR_INPUT reloads remain live till just before the
+        instruction is executed.  */
+      time1 = MAX_RECOG_OPERANDS * 4 + 1;
+      break;
+    case RELOAD_FOR_OPERAND_ADDRESS:
+      /* RELOAD_FOR_OPERAND_ADDRESS reloads are live even while the insn
+        is executed.  */
+      time1 = MAX_RECOG_OPERANDS * 4 + 2;
+      break;
+    case RELOAD_FOR_OUTPUT_ADDRESS:
+      time1 = MAX_RECOG_OPERANDS * 4 + 3 + opnum;
+      break;
+    default:
+      time1 = MAX_RECOG_OPERANDS * 5 + 3;
+    }
+
+  for (i = 0; i < n_reloads; i++)
+    {
+      rtx reg = reload_reg_rtx[i];
+      if (reg && GET_CODE (reg) == REG
+         && ((unsigned) regno - true_regnum (reg)
+             <= HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)) - (unsigned)1)
+         && i != reloadnum)
+       {
+         if (out
+             && reload_when_needed[i] != RELOAD_FOR_INPUT
+             && reload_when_needed[i] != RELOAD_FOR_INPUT_ADDRESS
+             && reload_when_needed[i] != RELOAD_FOR_INPADDR_ADDRESS)
+           return 0;
+         if (! reload_in[i] || ! rtx_equal_p (reload_in[i], value)
+             || reload_out[i])
+           {
+             int time2;
+             switch (reload_when_needed[i])
+               {
+               case RELOAD_FOR_OTHER_ADDRESS:
+                 time2 = 0;
+                 break;
+               case RELOAD_FOR_INPADDR_ADDRESS:
+                 /* find_reloads makes sure that a
+                    RELOAD_FOR_{INP,OP,OUT}ADDR_ADDRESS reload is only used
+                    by at most one - the first -
+                    RELOAD_FOR_{INPUT,OPERAND,OUTPUT}_ADDRESS .  If the
+                    address reload is inherited, the address address reload
+                    goes away, so we can ignore this conflict.  */
+                 if (type == RELOAD_FOR_INPUT_ADDRESS && reloadnum == i + 1)
+                   continue;
+                 time2 = reload_opnum[i] * 4 + 1;
+                 break;
+               case RELOAD_FOR_INPUT_ADDRESS:
+                 time2 = reload_opnum[i] * 4 + 2;
+                 break;
+               case RELOAD_FOR_INPUT:
+                 time2 = reload_opnum[i] * 4 + 3;
+                 break;
+               case RELOAD_FOR_OPADDR_ADDR:
+                 if (type == RELOAD_FOR_OPERAND_ADDRESS && reloadnum == i + 1)
+                   continue;
+                 time2 = MAX_RECOG_OPERANDS * 4;
+                 break;
+               case RELOAD_FOR_OPERAND_ADDRESS:
+                 time2 = MAX_RECOG_OPERANDS * 4 + 1;
+                 break;
+               case RELOAD_FOR_OUTPUT:
+               /* All RELOAD_FOR_OUTPUT reloads become live just after the
+                  instruction is executed.  */
+                 time2 = MAX_RECOG_OPERANDS * 4 + 3;
+                 break;
+               case RELOAD_FOR_OUTADDR_ADDRESS:
+                 if (type == RELOAD_FOR_OUTPUT_ADDRESS && reloadnum == i + 1)
+                   continue;
+               /* fall through. */
+               /* The first RELOAD_FOR_OUTPUT_ADDRESS reload conflicts with the
+                  RELOAD_FOR_OUTPUT reloads, so assign it the same time value.  */
+               case RELOAD_FOR_OUTPUT_ADDRESS:
+                 time2 = MAX_RECOG_OPERANDS * 4 + 3 + reload_opnum[i];
+                 break;
+               case RELOAD_OTHER:
+                 if (! reload_in[i] || rtx_equal_p (reload_in[i], value))
+                   {
+                     time2 = MAX_RECOG_OPERANDS * 4 + 3;
+                     break;
+                   }
+               default:
+                 time2 = 0;
+               }
+             if (time1 >= time2)
+               return 0;
+           }
+       }
+    }
+  return 1;
+}
+
 /* Find a spill register to use as a reload register for reload R.
    LAST_RELOAD is non-zero if this is the last reload for the insn being
    processed.
@@ -4986,17 +5312,15 @@ int reload_spill_index[MAX_RELOADS];
    or 0 if we couldn't find a spill reg and we didn't change anything.  */
 
 static int
-allocate_reload_reg (r, insn, last_reload, noerror)
+allocate_reload_reg (chain, r, last_reload, noerror)
+     struct insn_chain *chain;
      int r;
-     rtx insn;
      int last_reload;
      int noerror;
 {
-  int i;
-  int pass;
-  int count;
+  rtx insn = chain->insn;
+  int i, pass, count, regno;
   rtx new;
-  int regno;
 
   /* If we put this reload ahead, thinking it is a group,
      then insist on finding a group.  Otherwise we can grab a
@@ -5045,23 +5369,36 @@ allocate_reload_reg (r, insn, last_reload, noerror)
       for (count = 0; count < n_spills; count++)
        {
          int class = (int) reload_reg_class[r];
-
-         i = (i + 1) % n_spills;
-
-         if (reload_reg_free_p (spill_regs[i], reload_opnum[r],
-                                reload_when_needed[r])
-             && TEST_HARD_REG_BIT (reg_class_contents[class], spill_regs[i])
-             && HARD_REGNO_MODE_OK (spill_regs[i], reload_mode[r])
+         int regnum;
+
+         i++;
+         if (i >= n_spills)
+           i -= n_spills;
+         regnum = spill_regs[i];
+
+         if ((reload_reg_free_p (regnum, reload_opnum[r],
+                                 reload_when_needed[r])
+              || (reload_in[r]
+                     /* We check reload_reg_used to make sure we
+                        don't clobber the return register.  */
+                  && ! TEST_HARD_REG_BIT (reload_reg_used, regnum)
+                  && reload_reg_free_for_value_p (regnum,
+                                                 reload_opnum[r],
+                                                 reload_when_needed[r],
+                                                 reload_in[r],
+                                                 reload_out[r], r)))
+             && TEST_HARD_REG_BIT (reg_class_contents[class], regnum)
+             && HARD_REGNO_MODE_OK (regnum, reload_mode[r])
              /* Look first for regs to share, then for unshared.  But
                 don't share regs used for inherited reloads; they are
                 the ones we want to preserve.  */
              && (pass
                  || (TEST_HARD_REG_BIT (reload_reg_used_at_all,
-                                        spill_regs[i])
+                                        regnum)
                      && ! TEST_HARD_REG_BIT (reload_reg_used_for_inherit,
-                                             spill_regs[i]))))
+                                             regnum))))
            {
-             int nr = HARD_REGNO_NREGS (spill_regs[i], reload_mode[r]);
+             int nr = HARD_REGNO_NREGS (regnum, reload_mode[r]);
              /* Avoid the problem where spilling a GENERAL_OR_FP_REG
                 (on 68000) got us two FP regs.  If NR is 1,
                 we would reject both of them.  */
@@ -5079,15 +5416,15 @@ allocate_reload_reg (r, insn, last_reload, noerror)
                 are available here.
                 Also, don't use for a group registers that are
                 needed for nongroups.  */
-             if (! TEST_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]))
+             if (! TEST_HARD_REG_BIT (chain->counted_for_nongroups, regnum))
                while (nr > 1)
                  {
-                   regno = spill_regs[i] + nr - 1;
+                   regno = regnum + nr - 1;
                    if (!(TEST_HARD_REG_BIT (reg_class_contents[class], regno)
                          && spill_reg_order[regno] >= 0
                          && reload_reg_free_p (regno, reload_opnum[r],
                                                reload_when_needed[r])
-                         && ! TEST_HARD_REG_BIT (counted_for_nongroups,
+                         && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups,
                                                  regno)))
                      break;
                    nr--;
@@ -5183,14 +5520,15 @@ allocate_reload_reg (r, insn, last_reload, noerror)
    finding a reload reg in the proper class.  */
 
 static void
-choose_reload_regs (insn, avoid_return_reg)
-     rtx insn;
-     rtx avoid_return_reg;
+choose_reload_regs (chain)
+     struct insn_chain *chain;
 {
+  rtx insn = chain->insn;
   register int i, j;
   int max_group_size = 1;
   enum reg_class group_class = NO_REGS;
   int inheritance;
+  int pass;
 
   rtx save_reload_reg_rtx[MAX_RELOADS];
   char save_reload_inherited[MAX_RELOADS];
@@ -5221,6 +5559,10 @@ choose_reload_regs (insn, avoid_return_reg)
   CLEAR_HARD_REG_SET (reload_reg_used_in_insn);
   CLEAR_HARD_REG_SET (reload_reg_used_in_other_addr);
 
+  CLEAR_HARD_REG_SET (reg_used_by_pseudo);
+  compute_use_by_pseudos (&reg_used_by_pseudo, chain->live_before);
+  compute_use_by_pseudos (&reg_used_by_pseudo, chain->live_after);
+  
   for (i = 0; i < reload_n_operands; i++)
     {
       CLEAR_HARD_REG_SET (reload_reg_used_in_output[i]);
@@ -5231,29 +5573,8 @@ choose_reload_regs (insn, avoid_return_reg)
       CLEAR_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i]);
     }
 
-  /* Don't bother with avoiding the return reg
-     if we have no mandatory reload that could use it.  */
-  if (SMALL_REGISTER_CLASSES && avoid_return_reg)
-    {
-      int do_avoid = 0;
-      int regno = REGNO (avoid_return_reg);
-      int nregs
-       = HARD_REGNO_NREGS (regno, GET_MODE (avoid_return_reg));
-      int r;
-
-      for (r = regno; r < regno + nregs; r++)
-       if (spill_reg_order[r] >= 0)
-         for (j = 0; j < n_reloads; j++)
-           if (!reload_optional[j] && reload_reg_rtx[j] == 0
-               && (reload_in[j] != 0 || reload_out[j] != 0
-                   || reload_secondary_p[j])
-               &&
-               TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[j]], r))
-             do_avoid = 1;
-      if (!do_avoid)
-       avoid_return_reg = 0;
-    }
-
+  IOR_COMPL_HARD_REG_SET (reload_reg_used, chain->used_spill_regs);
+  
 #if 0  /* Not needed, now that we can always retry without inheritance.  */
   /* See if we have more mandatory reloads than spill regs.
      If so, then we cannot risk optimizations that could prevent
@@ -5263,7 +5584,7 @@ choose_reload_regs (insn, avoid_return_reg)
      unless it is equal to reload_in or reload_out, count such reloads.  */
 
   {
-    int tem = SMALL_REGISTER_CLASSES? (avoid_return_reg != 0): 0;
+    int tem = 0;
     for (j = 0; j < n_reloads; j++)
       if (! reload_optional[j]
          && (reload_in[j] != 0 || reload_out[j] != 0 || reload_secondary_p[j])
@@ -5276,20 +5597,6 @@ choose_reload_regs (insn, avoid_return_reg)
   }
 #endif
 
-  /* Don't use the subroutine call return reg for a reload
-     if we are supposed to avoid it.  */
-  if (SMALL_REGISTER_CLASSES && avoid_return_reg)
-    {
-      int regno = REGNO (avoid_return_reg);
-      int nregs
-       = HARD_REGNO_NREGS (regno, GET_MODE (avoid_return_reg));
-      int r;
-
-      for (r = regno; r < regno + nregs; r++)
-       if (spill_reg_order[r] >= 0)
-         SET_HARD_REG_BIT (reload_reg_used, r);
-    }
-
   /* In order to be certain of getting the registers we need,
      we must sort the reloads into order of increasing register class.
      Then our grabbing of reload registers will parallel the process
@@ -5404,13 +5711,16 @@ choose_reload_regs (insn, avoid_return_reg)
              && ! reload_secondary_p[r])
            continue;
 
-         /* If find_reloads chose to use reload_in or reload_out as a reload
+         /* If find_reloads chose to use reload_in or reload_out as a reload
             register, we don't need to chose one.  Otherwise, try even if it
             found one since we might save an insn if we find the value lying
-            around.  */
+            around.
+            Try also when reload_in is a pseudo without a hard reg.  */
          if (reload_in[r] != 0 && reload_reg_rtx[r] != 0
              && (rtx_equal_p (reload_in[r], reload_reg_rtx[r])
-                 || rtx_equal_p (reload_out[r], reload_reg_rtx[r])))
+                 || (rtx_equal_p (reload_out[r], reload_reg_rtx[r])
+                     && GET_CODE (reload_in[r]) != MEM
+                     && true_regnum (reload_in[r]) < FIRST_PSEUDO_REGISTER)))
            continue;
 
 #if 0 /* No longer needed for correct operation.
@@ -5426,7 +5736,7 @@ choose_reload_regs (insn, avoid_return_reg)
                   || reload_secondary_p[reload_order[i]])
                  && ! reload_optional[reload_order[i]]
                  && reload_reg_rtx[reload_order[i]] == 0)
-               allocate_reload_reg (reload_order[i], insn, 0, inheritance);
+               allocate_reload_reg (chain, reload_order[i], 0, inheritance);
 #endif
 
          /* First see if this pseudo is already available as reloaded
@@ -5445,9 +5755,9 @@ choose_reload_regs (insn, avoid_return_reg)
 
          if (inheritance)
            {
+             int word = 0;
              register int regno = -1;
              enum machine_mode mode;
-             rtx in, use_insn = 0;
 
              if (reload_in[r] == 0)
                ;
@@ -5461,34 +5771,27 @@ choose_reload_regs (insn, avoid_return_reg)
                  regno = REGNO (reload_in_reg[r]);
                  mode = GET_MODE (reload_in_reg[r]);
                }
-             else if (GET_CODE (reload_in[r]) == MEM)
+             else if (GET_CODE (reload_in_reg[r]) == SUBREG
+                      && GET_CODE (SUBREG_REG (reload_in_reg[r])) == REG)
                {
-                 rtx prev = prev_nonnote_insn (insn), note;
-
-                 if (prev && GET_CODE (prev) == INSN
-                     && GET_CODE (PATTERN (prev)) == USE
-                     && GET_CODE (XEXP (PATTERN (prev), 0)) == REG
-                     && (REGNO (XEXP (PATTERN (prev), 0))
-                         >= FIRST_PSEUDO_REGISTER)
-                     && (note = find_reg_note (prev, REG_EQUAL, NULL_RTX))
-                     && GET_CODE (XEXP (note, 0)) == MEM)
-                   {
-                     rtx addr = XEXP (XEXP (note, 0), 0);
-                     int size_diff
-                       = (GET_MODE_SIZE (GET_MODE (addr))
-                          - GET_MODE_SIZE (GET_MODE (reload_in[r])));
-                     if (size_diff >= 0
-                         && rtx_equal_p ((BYTES_BIG_ENDIAN
-                                          ? plus_constant (addr, size_diff)
-                                          : addr),
-                                         XEXP (reload_in[r], 0)))
-                       {
-                         regno = REGNO (XEXP (PATTERN (prev), 0));
-                         mode = GET_MODE (reload_in[r]);
-                         use_insn = prev;
-                       }
-                   }
+                 word = SUBREG_WORD (reload_in_reg[r]);
+                 regno = REGNO (SUBREG_REG (reload_in_reg[r]));
+                 if (regno < FIRST_PSEUDO_REGISTER)
+                   regno += word;
+                 mode = GET_MODE (reload_in_reg[r]);
+               }
+#ifdef AUTO_INC_DEC
+             else if ((GET_CODE (reload_in_reg[r]) == PRE_INC
+                       || GET_CODE (reload_in_reg[r]) == PRE_DEC
+                       || GET_CODE (reload_in_reg[r]) == POST_INC
+                       || GET_CODE (reload_in_reg[r]) == POST_DEC)
+                      && GET_CODE (XEXP (reload_in_reg[r], 0)) == REG)
+               {
+                 regno = REGNO (XEXP (reload_in_reg[r], 0));
+                 mode = GET_MODE (XEXP (reload_in_reg[r], 0));
+                 reload_out[r] = reload_in[r];
                }
+#endif
 #if 0
              /* This won't work, since REGNO can be a pseudo reg number.
                 Also, it takes much more hair to keep track of all the things
@@ -5500,22 +5803,46 @@ choose_reload_regs (insn, avoid_return_reg)
 
              if (regno >= 0 && reg_last_reload_reg[regno] != 0)
                {
-                 i = REGNO (reg_last_reload_reg[regno]);
-
-                 if (reg_reloaded_contents[i] == regno
+                 enum reg_class class = reload_reg_class[r], last_class;
+                 rtx last_reg = reg_last_reload_reg[regno];
+                 
+                 i = REGNO (last_reg) + word;
+                 last_class = REGNO_REG_CLASS (i);
+                 if ((GET_MODE_SIZE (GET_MODE (last_reg))
+                      >= GET_MODE_SIZE (mode) + word * UNITS_PER_WORD)
+                     && reg_reloaded_contents[i] == regno
                      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
-                     && (GET_MODE_SIZE (GET_MODE (reg_last_reload_reg[regno]))
-                         >= GET_MODE_SIZE (mode))
                      && HARD_REGNO_MODE_OK (i, reload_mode[r])
-                     && TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
-                                           i)
+                     && (TEST_HARD_REG_BIT (reg_class_contents[(int) class], i)
+                         /* Even if we can't use this register as a reload
+                            register, we might use it for reload_override_in,
+                            if copying it to the desired class is cheap
+                            enough.  */
+                         || ((REGISTER_MOVE_COST (last_class, class)
+                              < MEMORY_MOVE_COST (mode, class, 1))
+#ifdef SECONDARY_INPUT_RELOAD_CLASS
+                             && (SECONDARY_INPUT_RELOAD_CLASS (class, mode,
+                                                               last_reg)
+                                 == NO_REGS)
+#endif
+#ifdef SECONDARY_MEMORY_NEEDED
+                             && ! SECONDARY_MEMORY_NEEDED (last_class, class,
+                                                           mode)
+#endif
+                             ))
+
                      && (reload_nregs[r] == max_group_size
                          || ! TEST_HARD_REG_BIT (reg_class_contents[(int) group_class],
                                                  i))
-                     && reload_reg_free_p (i, reload_opnum[r],
-                                           reload_when_needed[r])
-                     && reload_reg_free_before_p (i, reload_opnum[r],
-                                                  reload_when_needed[r]))
+                     && ((reload_reg_free_p (i, reload_opnum[r],
+                                             reload_when_needed[r])
+                          && reload_reg_free_before_p (i, reload_opnum[r],
+                                                       reload_when_needed[r],
+                                                       0))
+                         || reload_reg_free_for_value_p (i, reload_opnum[r],
+                                                         reload_when_needed[r],
+                                                         reload_in[r],
+                                                         reload_out[r], r)))
                    {
                      /* If a group is needed, verify that all the subsequent
                         registers still have their values intact.  */
@@ -5532,6 +5859,9 @@ choose_reload_regs (insn, avoid_return_reg)
                        {
                          int i1;
 
+                         last_reg = (GET_MODE (last_reg) == mode
+                                     ? last_reg : gen_rtx_REG (mode, i));
+
                          /* We found a register that contains the
                             value we need.  If this register is the
                             same as an `earlyclobber' operand of the
@@ -5547,14 +5877,27 @@ choose_reload_regs (insn, avoid_return_reg)
 
                          if (i1 != n_earlyclobbers
                              /* Don't use it if we'd clobber a pseudo reg.  */
-                             || (spill_reg_order[i] < 0
+                             || (TEST_HARD_REG_BIT (reg_used_by_pseudo, i)
                                  && reload_out[r]
                                  && ! TEST_HARD_REG_BIT (reg_reloaded_dead, i))
                              /* Don't really use the inherited spill reg
                                 if we need it wider than we've got it.  */
                              || (GET_MODE_SIZE (reload_mode[r])
-                                 > GET_MODE_SIZE (mode)))
-                           reload_override_in[r] = reg_last_reload_reg[regno];
+                                 > GET_MODE_SIZE (mode))
+                             || ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
+                                                     i)
+
+                             /* If find_reloads chose reload_out as reload
+                                register, stay with it - that leaves the
+                                inherited register for subsequent reloads.  */
+                             || (reload_out[r] && reload_reg_rtx[r]
+                                 && rtx_equal_p (reload_out[r],
+                                                 reload_reg_rtx[r])))
+                           {
+                             reload_override_in[r] = last_reg;
+                             reload_inheritance_insn[r]
+                               = reg_reloaded_insn[i];
+                           }
                          else
                            {
                              int k;
@@ -5565,7 +5908,7 @@ choose_reload_regs (insn, avoid_return_reg)
                                                      reload_opnum[r],
                                                      reload_when_needed[r],
                                                      reload_mode[r]);
-                             reload_reg_rtx[r] = reg_last_reload_reg[regno];
+                             reload_reg_rtx[r] = last_reg;
                              reload_inherited[r] = 1;
                              reload_inheritance_insn[r]
                                = reg_reloaded_insn[i];
@@ -5616,16 +5959,15 @@ choose_reload_regs (insn, avoid_return_reg)
              /* If we found a spill reg, reject it unless it is free
                 and of the desired class.  */
              if (equiv != 0
-                 && ((spill_reg_order[regno] >= 0
-                      && ! reload_reg_free_before_p (regno, reload_opnum[r],
-                                                     reload_when_needed[r]))
+                 && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
+                      && ! reload_reg_free_for_value_p (regno, reload_opnum[r],
+                                                        reload_when_needed[r],
+                                                        reload_in[r],
+                                                        reload_out[r], r))
                      || ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
                                              regno)))
                equiv = 0;
 
-             if (equiv != 0 && TEST_HARD_REG_BIT (reload_reg_used_at_all, regno))
-               equiv = 0;
-
              if (equiv != 0 && ! HARD_REGNO_MODE_OK (regno, reload_mode[r]))
                equiv = 0;
 
@@ -5644,14 +5986,30 @@ choose_reload_regs (insn, avoid_return_reg)
                      break;
                    }
 
-             /* JRV: If the equiv register we have found is
-                explicitly clobbered in the current insn, mark but
-                don't use, as above.  */
+             /* If the equiv register we have found is explicitly clobbered
+                in the current insn, it depends on the reload type if we
+                can use it, use it for reload_override_in, or not at all.
+                In particular, we then can't use EQUIV for a
+                RELOAD_FOR_OUTPUT_ADDRESS reload.  */
 
              if (equiv != 0 && regno_clobbered_p (regno, insn))
                {
-                 reload_override_in[r] = equiv;
-                 equiv = 0;
+                 switch (reload_when_needed[r])
+                   {
+                   case RELOAD_FOR_OTHER_ADDRESS:
+                   case RELOAD_FOR_INPADDR_ADDRESS:
+                   case RELOAD_FOR_INPUT_ADDRESS:
+                   case RELOAD_FOR_OPADDR_ADDR:
+                     break;
+                   case RELOAD_OTHER:
+                   case RELOAD_FOR_INPUT:
+                   case RELOAD_FOR_OPERAND_ADDRESS:
+                     reload_override_in[r] = equiv;
+                     /* Fall through. */
+                   default:
+                     equiv = 0;
+                     break;
+                   }
                }
 
              /* If we found an equivalent reg, say no code need be generated
@@ -5663,6 +6021,12 @@ choose_reload_regs (insn, avoid_return_reg)
                  reload_reg_rtx[r] = equiv;
                  reload_inherited[r] = 1;
 
+                 /* If reg_reloaded_valid is not set for this register,
+                    there might be a stale spill_reg_store lying around.
+                    We must clear it, since otherwise emit_reload_insns
+                    might delete the store.  */
+                 if (! TEST_HARD_REG_BIT (reg_reloaded_valid, regno))
+                   spill_reg_store[regno] = NULL_RTX;
                  /* If any of the hard registers in EQUIV are spill
                     registers, mark them as in use for this insn.  */
                  for (k = 0; k < nr; k++)
@@ -5716,7 +6080,7 @@ choose_reload_regs (insn, avoid_return_reg)
          if (i == n_reloads)
            continue;
 
-         allocate_reload_reg (r, insn, j == n_reloads - 1, inheritance);
+         allocate_reload_reg (chain, r, j == n_reloads - 1, inheritance);
 #endif
        }
 
@@ -5735,7 +6099,7 @@ choose_reload_regs (insn, avoid_return_reg)
          if (reload_reg_rtx[r] != 0 || reload_optional[r])
            continue;
 
-         if (! allocate_reload_reg (r, insn, j == n_reloads - 1, inheritance))
+         if (! allocate_reload_reg (chain, r, j == n_reloads - 1, inheritance))
            break;
        }
 
@@ -5743,7 +6107,6 @@ choose_reload_regs (insn, avoid_return_reg)
       if (j == n_reloads)
        break;
 
-    fail:
       /* Loop around and try without any inheritance.  */
       /* First undo everything done by the failed attempt
         to allocate with inheritance.  */
@@ -5788,29 +6151,56 @@ choose_reload_regs (insn, avoid_return_reg)
 
   /* If we thought we could inherit a reload, because it seemed that
      nothing else wanted the same reload register earlier in the insn,
-     verify that assumption, now that all reloads have been assigned.  */
+     verify that assumption, now that all reloads have been assigned.
+     Likewise for reloads where reload_override_in has been set.  */
 
-  for (j = 0; j < n_reloads; j++)
+  /* If doing expensive optimizations, do one preliminary pass that doesn't
+     cancel any inheritance, but removes reloads that have been needed only
+     for reloads that we know can be inherited.  */
+  for (pass = flag_expensive_optimizations; pass >= 0; pass--)
     {
-      register int r = reload_order[j];
-
-      if (reload_inherited[r] && reload_reg_rtx[r] != 0
-         && ! reload_reg_free_before_p (true_regnum (reload_reg_rtx[r]),
-                                        reload_opnum[r],
-                                        reload_when_needed[r]))
-       reload_inherited[r] = 0;
-
-      /* If we found a better place to reload from,
-        validate it in the same fashion, if it is a reload reg.  */
-      if (reload_override_in[r]
-         && (GET_CODE (reload_override_in[r]) == REG
-             || GET_CODE (reload_override_in[r]) == SUBREG))
+      for (j = 0; j < n_reloads; j++)
        {
-         int regno = true_regnum (reload_override_in[r]);
-         if (spill_reg_order[regno] >= 0
-             && ! reload_reg_free_before_p (regno, reload_opnum[r],
-                                            reload_when_needed[r]))
-           reload_override_in[r] = 0;
+         register int r = reload_order[j];
+         rtx check_reg;
+         if (reload_inherited[r] && reload_reg_rtx[r])
+           check_reg = reload_reg_rtx[r];
+         else if (reload_override_in[r]
+                  && (GET_CODE (reload_override_in[r]) == REG
+                            || GET_CODE (reload_override_in[r]) == SUBREG))
+           check_reg = reload_override_in[r];
+         else
+           continue;
+         if (! (reload_reg_free_before_p (true_regnum (check_reg),
+                                      reload_opnum[r], reload_when_needed[r],
+                                      ! reload_inherited[r])
+                || reload_reg_free_for_value_p (true_regnum (check_reg),
+                                            reload_opnum[r],
+                                            reload_when_needed[r],
+                                            reload_in[r],
+                                            reload_out[r], r)))
+           {
+             if (pass)
+               continue;
+             reload_inherited[r] = 0;
+             reload_override_in[r] = 0;
+           }
+         /* If we can inherit a RELOAD_FOR_INPUT, or can use a
+            reload_override_in, then we do not need its related
+            RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS reloads;
+            likewise for other reload types.
+            We handle this by removing a reload when its only replacement
+            is mentioned in reload_in of the reload we are going to inherit.
+            A special case are auto_inc expressions; even if the input is
+            inherited, we still need the address for the output.  We can
+            recognize them because they have RELOAD_OUT set but not
+            RELOAD_OUT_REG.
+            If we suceeded removing some reload and we are doing a preliminary
+            pass just to remove such reloads, make another pass, since the
+            removal of one reload might allow us to inherit another one.  */
+         else if ((! reload_out[r] || reload_out_reg[r])
+                  && remove_address_replacements (reload_in[r]) && pass)
+           pass = 2;
        }
     }
 
@@ -5847,10 +6237,10 @@ choose_reload_regs (insn, avoid_return_reg)
       /* I is nonneg if this reload uses a register.
         If reload_reg_rtx[r] is 0, this is an optional reload
         that we opted to ignore.  */
-      if (reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG
+      if (reload_out_reg[r] != 0 && GET_CODE (reload_out_reg[r]) == REG
          && reload_reg_rtx[r] != 0)
        {
-         register int nregno = REGNO (reload_out[r]);
+         register int nregno = REGNO (reload_out_reg[r]);
          int nr = 1;
 
          if (nregno < FIRST_PSEUDO_REGISTER)
@@ -5873,6 +6263,24 @@ choose_reload_regs (insn, avoid_return_reg)
        }
     }
 }
+
+/* Deallocate the reload register for reload R.  This is called from
+   remove_address_replacements.  */
+void
+deallocate_reload_reg (r)
+     int r;
+{
+  int regno;
+
+  if (! reload_reg_rtx[r])
+    return;
+  regno = true_regnum (reload_reg_rtx[r]);
+  reload_reg_rtx[r] = 0;
+  if (spill_reg_order[regno] >= 0)
+    clear_reload_reg_in_use (regno, reload_opnum[r], reload_when_needed[r],
+                            reload_mode[r]);
+  reload_spill_index[r] = -1;
+}
 \f
 /* If SMALL_REGISTER_CLASSES is non-zero, we may not have merged two
    reloads of the same item for fear that we might not have enough reload
@@ -5899,6 +6307,10 @@ merge_assigned_reloads (insn)
 
   for (i = 0; i < n_reloads; i++)
     {
+      int conflicting_input = 0;
+      int max_input_address_opnum = -1;
+      int min_conflicting_input_opnum = MAX_RECOG_OPERANDS;
+
       if (reload_in[i] == 0 || reload_when_needed[i] == RELOAD_OTHER
          || reload_out[i] != 0 || reload_reg_rtx[i] == 0
          || reg_set_p (reload_reg_rtx[i], insn))
@@ -5917,27 +6329,46 @@ merge_assigned_reloads (insn)
                                            reload_reg_rtx[i]))
            continue;
 
+         if (reload_when_needed[j] == RELOAD_FOR_INPUT_ADDRESS
+             && reload_opnum[j] > max_input_address_opnum)
+           max_input_address_opnum = reload_opnum[j];
+
          /* If the reload regs aren't exactly the same (e.g, different modes)
-            or if the values are different, we can't merge anything with this
-            reload register.  */
+            or if the values are different, we can't merge this reload.
+            But if it is an input reload, we might still merge
+            RELOAD_FOR_INPUT_ADDRESS and RELOAD_FOR_OTHER_ADDRESS reloads.  */
 
          if (! rtx_equal_p (reload_reg_rtx[i], reload_reg_rtx[j])
              || reload_out[j] != 0 || reload_in[j] == 0
              || ! rtx_equal_p (reload_in[i], reload_in[j]))
-           break;
+           {
+             if (reload_when_needed[j] != RELOAD_FOR_INPUT
+                 || ((reload_when_needed[i] != RELOAD_FOR_INPUT_ADDRESS
+                      || reload_opnum[i] > reload_opnum[j])
+                     && reload_when_needed[i] != RELOAD_FOR_OTHER_ADDRESS))
+               break;
+             conflicting_input = 1;
+             if (min_conflicting_input_opnum > reload_opnum[j])
+               min_conflicting_input_opnum = reload_opnum[j];
+           }
        }
 
       /* If all is OK, merge the reloads.  Only set this to RELOAD_OTHER if
         we, in fact, found any matching reloads.  */
 
-      if (j == n_reloads)
+      if (j == n_reloads
+         && max_input_address_opnum <= min_conflicting_input_opnum)
        {
          for (j = 0; j < n_reloads; j++)
            if (i != j && reload_reg_rtx[j] != 0
-               && rtx_equal_p (reload_reg_rtx[i], reload_reg_rtx[j]))
+               && rtx_equal_p (reload_reg_rtx[i], reload_reg_rtx[j])
+               && (! conflicting_input
+                   || reload_when_needed[j] == RELOAD_FOR_INPUT_ADDRESS
+                   || reload_when_needed[j] == RELOAD_FOR_OTHER_ADDRESS))
              {
                reload_when_needed[i] = RELOAD_OTHER;
                reload_in[j] = 0;
+               reload_spill_index[j] = -1;
                transfer_replacements (i, j);
              }
 
@@ -5965,9 +6396,11 @@ merge_assigned_reloads (insn)
 /* Output insns to reload values in and out of the chosen reload regs.  */
 
 static void
-emit_reload_insns (insn)
-     rtx insn;
+emit_reload_insns (chain)
+     struct insn_chain *chain;
 {
+  rtx insn = chain->insn;
+
   register int j;
   rtx input_reload_insns[MAX_RECOG_OPERANDS];
   rtx other_input_address_reload_insns = 0;
@@ -5981,7 +6414,7 @@ emit_reload_insns (insn)
   rtx other_operand_reload_insns = 0;
   rtx other_output_reload_insns[MAX_RECOG_OPERANDS];
   rtx following_insn = NEXT_INSN (insn);
-  rtx before_insn = insn;
+  rtx before_insn = PREV_INSN (insn);
   int special;
   /* Values to be put in spill_reg_store are put here first.  */
   rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
@@ -6008,11 +6441,17 @@ emit_reload_insns (insn)
       rtx this_reload_insn = 0;
       int expect_occurrences = 1;
 
-      if (reload_spill_index[j] >= 0)
-       new_spill_reg_store[reload_spill_index[j]] = 0;
+      if (reload_reg_rtx[j]
+         && REGNO (reload_reg_rtx[j]) < FIRST_PSEUDO_REGISTER)
+       new_spill_reg_store[REGNO (reload_reg_rtx[j])] = 0;
+
+      old = (reload_in[j] && GET_CODE (reload_in[j]) == MEM
+            ? reload_in_reg[j] : reload_in[j]);
 
-      old = reload_in[j];
-      if (old != 0 && ! reload_inherited[j]
+      if (old != 0
+         /* AUTO_INC reloads need to be handled even if inherited.  We got an
+            AUTO_INC reload if reload_out is set but reload_out_reg isn't.  */
+         && (! reload_inherited[j] || (reload_out[j] && ! reload_out_reg[j]))
          && ! rtx_equal_p (reload_reg_rtx[j], old)
          && reload_reg_rtx[j] != 0)
        {
@@ -6099,7 +6538,7 @@ emit_reload_insns (insn)
                  && (! reload_reg_free_p (regno, reload_opnum[j],
                                           reload_when_needed[j])
                      || ! reload_reg_free_before_p (regno, reload_opnum[j],
-                                                    reload_when_needed[j])))
+                                                    reload_when_needed[j], 1)))
                oldequiv = 0;
 
              /* If OLDEQUIV is not a spill register,
@@ -6126,22 +6565,32 @@ emit_reload_insns (insn)
                  && ((REGNO_REG_CLASS (regno) != reload_reg_class[j]
                       && (REGISTER_MOVE_COST (REGNO_REG_CLASS (regno),
                                               reload_reg_class[j])
-                          >= MEMORY_MOVE_COST (mode, REGNO_REG_CLASS (regno),
-                                               1)))
+                          >= MEMORY_MOVE_COST (mode, reload_reg_class[j], 1)))
 #ifdef SECONDARY_INPUT_RELOAD_CLASS
                      || (SECONDARY_INPUT_RELOAD_CLASS (reload_reg_class[j],
                                                        mode, oldequiv)
                          != NO_REGS)
 #endif
 #ifdef SECONDARY_MEMORY_NEEDED
-                     || SECONDARY_MEMORY_NEEDED (reload_reg_class[j],
-                                                 REGNO_REG_CLASS (regno),
+                     || SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (regno),
+                                                 reload_reg_class[j],
                                                  mode)
 #endif
                      ))
                oldequiv = 0;
            }
 
+         /* delete_output_reload is only invoked properly if old contains
+            the original pseudo register.  Since this is replaced with a
+            hard reg when RELOAD_OVERRIDE_IN is set, see if we can
+            find the pseudo in RELOAD_IN_REG.  */
+         if (oldequiv == 0
+             && reload_override_in[j]
+             && GET_CODE (reload_in_reg[j]) == REG)
+           {
+             oldequiv = old;
+             old = reload_in_reg[j];
+           }
          if (oldequiv == 0)
            oldequiv = old;
          else if (GET_CODE (oldequiv) == REG)
@@ -6156,11 +6605,11 @@ emit_reload_insns (insn)
          if (optimize && GET_CODE (oldequiv) == REG
              && REGNO (oldequiv) < FIRST_PSEUDO_REGISTER
              && spill_reg_store[REGNO (oldequiv)]
-             && GET_CODE (old) == REG && dead_or_set_p (insn, old)
-             /* This is unsafe if operand occurs more than once in current
-                insn.  Perhaps some occurrences weren't reloaded.  */
-             && count_occurrences (PATTERN (insn), old) == 1)
-           delete_output_reload (insn, j, spill_reg_store[REGNO (oldequiv)]);
+             && GET_CODE (old) == REG
+             && (dead_or_set_p (insn, spill_reg_stored_to[REGNO (oldequiv)])
+                 || rtx_equal_p (spill_reg_stored_to[REGNO (oldequiv)],
+                                 reload_out_reg[j])))
+           delete_output_reload (insn, j, REGNO (oldequiv));
 
          /* Encapsulate both RELOADREG and OLDEQUIV into that mode,
             then load RELOADREG from OLDEQUIV.  Note that we cannot use
@@ -6214,20 +6663,35 @@ emit_reload_insns (insn)
          special = 0;
 
          /* Auto-increment addresses must be reloaded in a special way.  */
-         if (GET_CODE (oldequiv) == POST_INC
-             || GET_CODE (oldequiv) == POST_DEC
-             || GET_CODE (oldequiv) == PRE_INC
-             || GET_CODE (oldequiv) == PRE_DEC)
+         if (reload_out[j] && ! reload_out_reg[j])
            {
              /* We are not going to bother supporting the case where a
                 incremented register can't be copied directly from
                 OLDEQUIV since this seems highly unlikely.  */
              if (reload_secondary_in_reload[j] >= 0)
                abort ();
+
+             if (reload_inherited[j])
+               oldequiv = reloadreg;
+
+             old = XEXP (reload_in_reg[j], 0);
+
+             if (optimize && GET_CODE (oldequiv) == REG
+                 && REGNO (oldequiv) < FIRST_PSEUDO_REGISTER
+                 && spill_reg_store[REGNO (oldequiv)]
+                 && GET_CODE (old) == REG
+                 && (dead_or_set_p (insn,
+                                    spill_reg_stored_to[REGNO (oldequiv)])
+                     || rtx_equal_p (spill_reg_stored_to[REGNO (oldequiv)],
+                                     old)))
+               delete_output_reload (insn, j, REGNO (oldequiv));
+
              /* Prevent normal processing of this reload.  */
              special = 1;
              /* Output a special code sequence for this case.  */
-             inc_for_reload (reloadreg, oldequiv, reload_inc[j]);
+             new_spill_reg_store[REGNO (reloadreg)]
+               = inc_for_reload (reloadreg, oldequiv, reload_out[j],
+                                 reload_inc[j]);
            }
 
          /* If we are reloading a pseudo-register that was set by the previous
@@ -6241,7 +6705,7 @@ emit_reload_insns (insn)
                      uses the same reg first.  */
                   && reload_reg_free_before_p (REGNO (reloadreg),
                                                reload_opnum[j],
-                                               reload_when_needed[j]))
+                                               reload_when_needed[j], 0))
            {
              rtx temp = PREV_INSN (insn);
              while (temp && GET_CODE (temp) == NOTE)
@@ -6303,15 +6767,31 @@ emit_reload_insns (insn)
                  /* If OLDEQUIV is a pseudo with a MEM, get the real MEM
                     and similarly for OLD.
                     See comments in get_secondary_reload in reload.c.  */
+                 /* If it is a pseudo that cannot be replaced with its
+                    equivalent MEM, we must fall back to reload_in, which
+                    will have all the necessary substitutions registered.  */
+                               
                  if (GET_CODE (oldequiv) == REG
                      && REGNO (oldequiv) >= FIRST_PSEUDO_REGISTER
-                     && reg_equiv_mem[REGNO (oldequiv)] != 0)
-                   real_oldequiv = reg_equiv_mem[REGNO (oldequiv)];
+                     && reg_equiv_memory_loc[REGNO (oldequiv)] != 0)
+                   {
+                     if (reg_equiv_address[REGNO (oldequiv)]
+                         || num_not_at_initial_offset)
+                       real_oldequiv = reload_in[j];
+                     else
+                       real_oldequiv = reg_equiv_mem[REGNO (oldequiv)];
+                   }
 
                  if (GET_CODE (old) == REG
                      && REGNO (old) >= FIRST_PSEUDO_REGISTER
-                     && reg_equiv_mem[REGNO (old)] != 0)
-                   real_old = reg_equiv_mem[REGNO (old)];
+                     && reg_equiv_memory_loc[REGNO (old)] != 0)
+                   {
+                     if (reg_equiv_address[REGNO (old)]
+                         || num_not_at_initial_offset)
+                       real_old = reload_in[j];
+                     else
+                       real_old = reg_equiv_mem[REGNO (old)];
+                   }
 
                  second_reload_reg = reload_reg_rtx[secondary_reload];
                  icode = reload_secondary_in_icode[j];
@@ -6396,7 +6876,7 @@ emit_reload_insns (insn)
                                           third_reload_reg)));
                            }
                          else
-                           gen_reload (second_reload_reg, oldequiv,
+                           gen_reload (second_reload_reg, real_oldequiv,
                                        reload_opnum[j],
                                        reload_when_needed[j]);
 
@@ -6407,37 +6887,34 @@ emit_reload_insns (insn)
 #endif
 
              if (! special && ! rtx_equal_p (reloadreg, oldequiv))
-               gen_reload (reloadreg, oldequiv, reload_opnum[j],
-                           reload_when_needed[j]);
-
-#if defined(SECONDARY_INPUT_RELOAD_CLASS) && defined(PRESERVE_DEATH_INFO_REGNO_P)
-             /* We may have to make a REG_DEAD note for the secondary reload
-                register in the insns we just made.  Find the last insn that
-                mentioned the register.  */
-             if (! special && second_reload_reg
-                 && PRESERVE_DEATH_INFO_REGNO_P (REGNO (second_reload_reg)))
                {
-                 rtx prev;
+                 rtx real_oldequiv = oldequiv;
 
-                 for (prev = get_last_insn (); prev;
-                      prev = PREV_INSN (prev))
-                   if (GET_RTX_CLASS (GET_CODE (prev) == 'i')
-                       && reg_overlap_mentioned_for_reload_p (second_reload_reg,
-                                                              PATTERN (prev)))
-                     {
-                       REG_NOTES (prev) = gen_rtx_EXPR_LIST (REG_DEAD,
-                                                             second_reload_reg,
-                                                             REG_NOTES (prev));
-                       break;
-                     }
+                 if ((GET_CODE (oldequiv) == REG
+                      && REGNO (oldequiv) >= FIRST_PSEUDO_REGISTER
+                      && reg_equiv_memory_loc[REGNO (oldequiv)] != 0)
+                     || (GET_CODE (oldequiv) == SUBREG
+                         && GET_CODE (SUBREG_REG (oldequiv)) == REG
+                         && (REGNO (SUBREG_REG (oldequiv))
+                             >= FIRST_PSEUDO_REGISTER)
+                         && (reg_equiv_memory_loc
+                             [REGNO (SUBREG_REG (oldequiv))] != 0)))
+                   real_oldequiv = reload_in[j];
+                 gen_reload (reloadreg, real_oldequiv, reload_opnum[j],
+                             reload_when_needed[j]);
                }
-#endif
+
            }
 
          this_reload_insn = get_last_insn ();
          /* End this sequence.  */
          *where = get_insns ();
          end_sequence ();
+
+         /* Update reload_override_in so that delete_address_reloads_1
+            can see the actual register usage.  */
+         if (oldequiv_reg)
+           reload_override_in[j] = oldequiv;
        }
 
       /* When inheriting a wider reload, we have a MEM in reload_in[j],
@@ -6445,6 +6922,7 @@ emit_reload_insns (insn)
         (mem:HI (plus:SI (reg:SI 14 fp) (const_int 10)))  */
       if (optimize && reload_inherited[j] && reload_in[j]
          && GET_CODE (reload_in[j]) == MEM
+         && GET_CODE (reload_in_reg[j]) == MEM
          && reload_spill_index[j] >= 0
          && TEST_HARD_REG_BIT (reg_reloaded_valid, reload_spill_index[j]))
        {
@@ -6453,143 +6931,31 @@ emit_reload_insns (insn)
          reload_in[j]
            = regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]];
        }
-      /* Add a note saying the input reload reg
-        dies in this insn, if anyone cares.  */
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-      if (old != 0
-         && reload_reg_rtx[j] != old
-         && reload_reg_rtx[j] != 0
-         && reload_out[j] == 0
-         && ! reload_inherited[j]
-         && PRESERVE_DEATH_INFO_REGNO_P (REGNO (reload_reg_rtx[j])))
-       {
-         register rtx reloadreg = reload_reg_rtx[j];
-
-#if 0
-         /* We can't abort here because we need to support this for sched.c.
-            It's not terrible to miss a REG_DEAD note, but we should try
-            to figure out how to do this correctly.  */
-         /* The code below is incorrect for address-only reloads.  */
-         if (reload_when_needed[j] != RELOAD_OTHER
-             && reload_when_needed[j] != RELOAD_FOR_INPUT)
-           abort ();
-#endif
-
-         /* Add a death note to this insn, for an input reload.  */
-
-         if ((reload_when_needed[j] == RELOAD_OTHER
-              || reload_when_needed[j] == RELOAD_FOR_INPUT)
-             && ! dead_or_set_p (insn, reloadreg))
-           REG_NOTES (insn)
-             = gen_rtx_EXPR_LIST (REG_DEAD,
-                                  reloadreg, REG_NOTES (insn));
-       }
-
-      /* When we inherit a reload, the last marked death of the reload reg
-        may no longer really be a death.  */
-      if (reload_reg_rtx[j] != 0
-         && PRESERVE_DEATH_INFO_REGNO_P (REGNO (reload_reg_rtx[j]))
-         && reload_inherited[j])
-       {
-         /* Handle inheriting an output reload.
-            Remove the death note from the output reload insn.  */
-         if (reload_spill_index[j] >= 0
-             && GET_CODE (reload_in[j]) == REG
-             && spill_reg_store[reload_spill_index[j]] != 0
-             && find_regno_note (spill_reg_store[reload_spill_index[j]],
-                                 REG_DEAD, REGNO (reload_reg_rtx[j])))
-           remove_death (REGNO (reload_reg_rtx[j]),
-                         spill_reg_store[reload_spill_index[j]]);
-         /* Likewise for input reloads that were inherited.  */
-         else if (reload_spill_index[j] >= 0
-                  && GET_CODE (reload_in[j]) == REG
-                  && spill_reg_store[reload_spill_index[j]] == 0
-                  && reload_inheritance_insn[j] != 0
-                  && find_regno_note (reload_inheritance_insn[j], REG_DEAD,
-                                      REGNO (reload_reg_rtx[j])))
-           remove_death (REGNO (reload_reg_rtx[j]),
-                         reload_inheritance_insn[j]);
-         else
-           {
-             rtx prev;
-
-             /* We got this register from find_equiv_reg.
-                Search back for its last death note and get rid of it.
-                But don't search back too far.
-                Don't go past a place where this reg is set,
-                since a death note before that remains valid.  */
-             for (prev = PREV_INSN (insn);
-                  prev && GET_CODE (prev) != CODE_LABEL;
-                  prev = PREV_INSN (prev))
-               if (GET_RTX_CLASS (GET_CODE (prev)) == 'i'
-                   && dead_or_set_p (prev, reload_reg_rtx[j]))
-                 {
-                   if (find_regno_note (prev, REG_DEAD,
-                                        REGNO (reload_reg_rtx[j])))
-                     remove_death (REGNO (reload_reg_rtx[j]), prev);
-                   break;
-                 }
-           }
-       }
-
-      /* We might have used find_equiv_reg above to choose an alternate
-        place from which to reload.  If so, and it died, we need to remove
-        that death and move it to one of the insns we just made.  */
-
-      if (oldequiv_reg != 0
-         && PRESERVE_DEATH_INFO_REGNO_P (true_regnum (oldequiv_reg)))
-       {
-         rtx prev, prev1;
-
-         for (prev = PREV_INSN (insn); prev && GET_CODE (prev) != CODE_LABEL;
-              prev = PREV_INSN (prev))
-           if (GET_RTX_CLASS (GET_CODE (prev)) == 'i'
-               && dead_or_set_p (prev, oldequiv_reg))
-             {
-               if (find_regno_note (prev, REG_DEAD, REGNO (oldequiv_reg)))
-                 {
-                   for (prev1 = this_reload_insn;
-                        prev1; prev1 = PREV_INSN (prev1))
-                     if (GET_RTX_CLASS (GET_CODE (prev1) == 'i')
-                       && reg_overlap_mentioned_for_reload_p (oldequiv_reg,
-                                                              PATTERN (prev1)))
-                     {
-                       REG_NOTES (prev1) = gen_rtx_EXPR_LIST (REG_DEAD,
-                                                              oldequiv_reg,
-                                                              REG_NOTES (prev1));
-                       break;
-                     }
-                   remove_death (REGNO (oldequiv_reg), prev);
-                 }
-               break;
-             }
-       }
-#endif
 
       /* If we are reloading a register that was recently stored in with an
         output-reload, see if we can prove there was
         actually no need to store the old value in it.  */
 
-      if (optimize && reload_inherited[j] && reload_spill_index[j] >= 0
-         && reload_in[j] != 0
-         && GET_CODE (reload_in[j]) == REG
+      if (optimize
+         && (reload_inherited[j] || reload_override_in[j])
+         && reload_reg_rtx[j]
+         && GET_CODE (reload_reg_rtx[j]) == REG
+         && spill_reg_store[REGNO (reload_reg_rtx[j])] != 0
 #if 0
          /* There doesn't seem to be any reason to restrict this to pseudos
             and doing so loses in the case where we are copying from a
             register of the wrong class.  */
-         && REGNO (reload_in[j]) >= FIRST_PSEUDO_REGISTER
+         && REGNO (spill_reg_stored_to[REGNO (reload_reg_rtx[j])])
+            >= FIRST_PSEUDO_REGISTER
 #endif
-         && spill_reg_store[reload_spill_index[j]] != 0
-         /* This is unsafe if some other reload uses the same reg first.  */
-         && reload_reg_free_before_p (reload_spill_index[j],
-                                      reload_opnum[j], reload_when_needed[j])
-         && dead_or_set_p (insn, reload_in[j])
-         /* This is unsafe if operand occurs more than once in current
-            insn.  Perhaps some occurrences weren't reloaded.  */
-         && (count_occurrences (PATTERN (insn), reload_in[j])
-             == expect_occurrences))
-       delete_output_reload (insn, j,
-                             spill_reg_store[reload_spill_index[j]]);
+            /* The insn might have already some references to stackslots
+               replaced by MEMs, while reload_out_reg still names the
+               original pseudo.  */
+         && (dead_or_set_p (insn,
+                            spill_reg_stored_to[REGNO (reload_reg_rtx[j])])
+             || rtx_equal_p (spill_reg_stored_to[REGNO (reload_reg_rtx[j])],
+                             reload_out_reg[j])))
+       delete_output_reload (insn, j, REGNO (reload_reg_rtx[j]));
 
       /* Input-reloading is done.  Now do output-reloading,
         storing the value from the reload-register after the main insn
@@ -6597,7 +6963,33 @@ emit_reload_insns (insn)
 
         ??? At some point we need to support handling output reloads of
         JUMP_INSNs or insns that set cc0.  */
-      old = reload_out[j];
+
+      /* If this is an output reload that stores something that is
+        not loaded in this same reload, see if we can eliminate a previous
+        store.  */
+      {
+       rtx pseudo = reload_out_reg[j];
+         
+       if (pseudo
+           && GET_CODE (pseudo) == REG
+           && ! rtx_equal_p (reload_in_reg[j], pseudo)
+           && REGNO (pseudo) >= FIRST_PSEUDO_REGISTER
+           && reg_last_reload_reg[REGNO (pseudo)])
+         {
+           int pseudo_no = REGNO (pseudo);
+           int last_regno = REGNO (reg_last_reload_reg[pseudo_no]);
+
+           /* We don't need to test full validity of last_regno for
+              inherit here; we only want to know if the store actually
+              matches the pseudo.  */
+           if (reg_reloaded_contents[last_regno] == pseudo_no
+               && spill_reg_store[last_regno]
+               && rtx_equal_p (pseudo, spill_reg_stored_to[last_regno]))
+             delete_output_reload (insn, j, last_regno);
+         }
+      }
+
+      old = reload_out_reg[j];
       if (old != 0
          && reload_reg_rtx[j] != old
          && reload_reg_rtx[j] != 0)
@@ -6653,6 +7045,8 @@ emit_reload_insns (insn)
          else
            push_to_sequence (output_reload_insns[reload_opnum[j]]);
 
+         old = reload_out[j];
+
          /* Determine the mode to reload in.
             See comments above (for input reloading).  */
 
@@ -6754,33 +7148,21 @@ emit_reload_insns (insn)
 
          /* Output the last reload insn.  */
          if (! special)
-           gen_reload (old, reloadreg, reload_opnum[j],
-                       reload_when_needed[j]);
-
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-         /* If final will look at death notes for this reg,
-            put one on the last output-reload insn to use it.  Similarly
-            for any secondary register.  */
-         if (PRESERVE_DEATH_INFO_REGNO_P (REGNO (reloadreg)))
-           for (p = get_last_insn (); p; p = PREV_INSN (p))
-             if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
-                 && reg_overlap_mentioned_for_reload_p (reloadreg,
-                                                        PATTERN (p)))
-               REG_NOTES (p) = gen_rtx_EXPR_LIST (REG_DEAD,
-                                                  reloadreg, REG_NOTES (p));
+           {
+             rtx set;
+
+             /* Don't output the last reload if OLD is not the dest of
+                INSN and is in the src and is clobbered by INSN. */
+             if (! flag_expensive_optimizations
+                 || GET_CODE (old) != REG
+                 || !(set = single_set (insn))
+                 || rtx_equal_p (old, SET_DEST (set))
+                 || !reg_mentioned_p (old, SET_SRC (set))
+                 || !regno_clobbered_p (REGNO (old), insn))
+               gen_reload (old, reloadreg, reload_opnum[j],
+                           reload_when_needed[j]);
+           }
 
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
-         if (! special && second_reloadreg
-             && PRESERVE_DEATH_INFO_REGNO_P (REGNO (second_reloadreg)))
-           for (p = get_last_insn (); p; p = PREV_INSN (p))
-             if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
-                 && reg_overlap_mentioned_for_reload_p (second_reloadreg,
-                                                        PATTERN (p)))
-               REG_NOTES (p) = gen_rtx_EXPR_LIST (REG_DEAD,
-                                                  second_reloadreg,
-                                                  REG_NOTES (p));
-#endif
-#endif
          /* Look at all insns we emitted, just to be safe.  */
          for (p = get_insns (); p; p = NEXT_INSN (p))
            if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
@@ -6795,19 +7177,53 @@ emit_reload_insns (insn)
 
                if (reg_mentioned_p (reload_reg_rtx[j], pat))
                  {
+                   rtx set = single_set (insn);
                    if (reload_spill_index[j] < 0
-                       && GET_CODE (pat) == SET
-                       && SET_SRC (pat) == reload_reg_rtx[j])
+                       && set
+                       && SET_SRC (set) == reload_reg_rtx[j])
                      {
-                       int src = REGNO (SET_SRC (pat));
+                       int src = REGNO (SET_SRC (set));
 
                        reload_spill_index[j] = src;
                        SET_HARD_REG_BIT (reg_is_output_reload, src);
                        if (find_regno_note (insn, REG_DEAD, src))
                          SET_HARD_REG_BIT (reg_reloaded_died, src);
                      }
-                   if (reload_spill_index[j] >= 0)
-                     new_spill_reg_store[reload_spill_index[j]] = p;
+                   if (REGNO (reload_reg_rtx[j]) < FIRST_PSEUDO_REGISTER)
+                     {
+                       int s = reload_secondary_out_reload[j];
+                       set = single_set (p);
+                       /* If this reload copies only to the secondary reload
+                          register, the secondary reload does the actual
+                          store.  */
+                       if (s >= 0 && set == NULL_RTX)
+                         ; /* We can't tell what function the secondary reload
+                              has and where the actual store to the pseudo is
+                              made; leave new_spill_reg_store alone.  */
+                       else if (s >= 0
+                           && SET_SRC (set) == reload_reg_rtx[j]
+                           && SET_DEST (set) == reload_reg_rtx[s])
+                         {
+                           /* Usually the next instruction will be the
+                              secondary reload insn;  if we can confirm
+                              that it is, setting new_spill_reg_store to
+                              that insn will allow an extra optimization.  */
+                           rtx s_reg = reload_reg_rtx[s];
+                           rtx next = NEXT_INSN (p);
+                           reload_out[s] = reload_out[j];
+                           reload_out_reg[s] = reload_out_reg[j];
+                           set = single_set (next);
+                           if (set && SET_SRC (set) == s_reg
+                               && ! new_spill_reg_store[REGNO (s_reg)])
+                             {
+                               SET_HARD_REG_BIT (reg_is_output_reload,
+                                                 REGNO (s_reg));
+                               new_spill_reg_store[REGNO (s_reg)] = next;
+                             }
+                         }
+                       else
+                         new_spill_reg_store[REGNO (reload_reg_rtx[j])] = p;
+                     }
                  }
              }
 
@@ -6847,18 +7263,18 @@ emit_reload_insns (insn)
      reloads for the operand.  The RELOAD_OTHER output reloads are
      output in descending order by reload number.  */
 
-  emit_insns_before (other_input_address_reload_insns, before_insn);
-  emit_insns_before (other_input_reload_insns, before_insn);
+  emit_insns_before (other_input_address_reload_insns, insn);
+  emit_insns_before (other_input_reload_insns, insn);
 
   for (j = 0; j < reload_n_operands; j++)
     {
-      emit_insns_before (inpaddr_address_reload_insns[j], before_insn);
-      emit_insns_before (input_address_reload_insns[j], before_insn);
-      emit_insns_before (input_reload_insns[j], before_insn);
+      emit_insns_before (inpaddr_address_reload_insns[j], insn);
+      emit_insns_before (input_address_reload_insns[j], insn);
+      emit_insns_before (input_reload_insns[j], insn);
     }
 
-  emit_insns_before (other_operand_reload_insns, before_insn);
-  emit_insns_before (operand_reload_insns, before_insn);
+  emit_insns_before (other_operand_reload_insns, insn);
+  emit_insns_before (operand_reload_insns, insn);
 
   for (j = 0; j < reload_n_operands; j++)
     {
@@ -6868,49 +7284,14 @@ emit_reload_insns (insn)
       emit_insns_before (other_output_reload_insns[j], following_insn);
     }
 
-  /* Move death notes from INSN
-     to output-operand-address and output reload insns.  */
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-  {
-    rtx insn1;
-    /* Loop over those insns, last ones first.  */
-    for (insn1 = PREV_INSN (following_insn); insn1 != insn;
-        insn1 = PREV_INSN (insn1))
-      if (GET_CODE (insn1) == INSN && GET_CODE (PATTERN (insn1)) == SET)
-       {
-         rtx source = SET_SRC (PATTERN (insn1));
-         rtx dest = SET_DEST (PATTERN (insn1));
-
-         /* The note we will examine next.  */
-         rtx reg_notes = REG_NOTES (insn);
-         /* The place that pointed to this note.  */
-         rtx *prev_reg_note = &REG_NOTES (insn);
-
-         /* If the note is for something used in the source of this
-            reload insn, or in the output address, move the note.  */
-         while (reg_notes)
-           {
-             rtx next_reg_notes = XEXP (reg_notes, 1);
-             if (REG_NOTE_KIND (reg_notes) == REG_DEAD
-                 && GET_CODE (XEXP (reg_notes, 0)) == REG
-                 && ((GET_CODE (dest) != REG
-                      && reg_overlap_mentioned_for_reload_p (XEXP (reg_notes, 0),
-                                                             dest))
-                     || reg_overlap_mentioned_for_reload_p (XEXP (reg_notes, 0),
-                                                            source)))
-               {
-                 *prev_reg_note = next_reg_notes;
-                 XEXP (reg_notes, 1) = REG_NOTES (insn1);
-                 REG_NOTES (insn1) = reg_notes;
-               }
-             else
-               prev_reg_note = &XEXP (reg_notes, 1);
-
-             reg_notes = next_reg_notes;
-           }
-       }
-  }
-#endif
+  /* Keep basic block info up to date.  */
+  if (n_basic_blocks)
+    {
+      if (basic_block_head[chain->block] == insn)
+        basic_block_head[chain->block] = NEXT_INSN (before_insn);
+      if (basic_block_end[chain->block] == insn)
+        basic_block_end[chain->block] = PREV_INSN (following_insn);
+    }
 
   /* For all the spill regs newly reloaded in this instruction,
      record what they were reloaded from, so subsequent instructions
@@ -6958,14 +7339,25 @@ emit_reload_insns (insn)
                CLEAR_HARD_REG_BIT (reg_reloaded_valid, i + k);
 
              /* Maybe the spill reg contains a copy of reload_out.  */
-             if (reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
+             if (reload_out[r] != 0
+                 && (GET_CODE (reload_out[r]) == REG
+#ifdef AUTO_INC_DEC
+                     || ! reload_out_reg[r]
+#endif
+                     || GET_CODE (reload_out_reg[r]) == REG))
                {
-                 register int nregno = REGNO (reload_out[r]);
+                 rtx out = (GET_CODE (reload_out[r]) == REG
+                            ? reload_out[r]
+                            : reload_out_reg[r]
+                            ? reload_out_reg[r]
+/* AUTO_INC */              : XEXP (reload_in_reg[r], 0));
+                 register int nregno = REGNO (out);
                  int nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
                             : HARD_REGNO_NREGS (nregno,
                                                 GET_MODE (reload_reg_rtx[r])));
 
                  spill_reg_store[i] = new_spill_reg_store[i];
+                 spill_reg_stored_to[i] = out;
                  reg_last_reload_reg[nregno] = reload_reg_rtx[r];
 
                  /* If NREGNO is a hard register, it may occupy more than
@@ -6998,21 +7390,25 @@ emit_reload_insns (insn)
              /* Maybe the spill reg contains a copy of reload_in.  Only do
                 something if there will not be an output reload for
                 the register being reloaded.  */
-             else if (reload_out[r] == 0
+             else if (reload_out_reg[r] == 0
                       && reload_in[r] != 0
-                      && spill_reg_order[i] >= 0
                       && ((GET_CODE (reload_in[r]) == REG
+                           && REGNO (reload_in[r]) >= FIRST_PSEUDO_REGISTER
                            && ! reg_has_output_reload[REGNO (reload_in[r])])
                           || (GET_CODE (reload_in_reg[r]) == REG
-                              && ! reg_has_output_reload[REGNO (reload_in_reg[r])])))
+                              && ! reg_has_output_reload[REGNO (reload_in_reg[r])]))
+                      && ! reg_set_p (reload_reg_rtx[r], PATTERN (insn)))
                {
                  register int nregno;
                  int nnr;
 
-                 if (GET_CODE (reload_in[r]) == REG)
+                 if (GET_CODE (reload_in[r]) == REG
+                     && REGNO (reload_in[r]) >= FIRST_PSEUDO_REGISTER)
                    nregno = REGNO (reload_in[r]);
-                 else
+                 else if (GET_CODE (reload_in_reg[r]) == REG)
                    nregno = REGNO (reload_in_reg[r]);
+                 else
+                   nregno = REGNO (XEXP (reload_in_reg[r], 0));
 
                  nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
                         : HARD_REGNO_NREGS (nregno,
@@ -7029,8 +7425,11 @@ emit_reload_insns (insn)
                           : 0);
 
                  /* Unless we inherited this reload, show we haven't
-                    recently done a store.  */
-                 if (! reload_inherited[r])
+                    recently done a store.
+                    Previous stores of inherited auto_inc expressions
+                    also have to be discarded.  */
+                 if (! reload_inherited[r]
+                     || (reload_out[r] && ! reload_out_reg[r]))
                    spill_reg_store[i] = 0;
 
                  for (k = 0; k < nr; k++)
@@ -7066,11 +7465,77 @@ emit_reload_insns (insn)
         that invalidates any previous reloaded copy of it.
         But forget_old_reloads_1 won't get to see it, because
         it thinks only about the original insn.  So invalidate it here.  */
-      if (i < 0 && reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
+      if (i < 0 && reload_out[r] != 0
+         && (GET_CODE (reload_out[r]) == REG
+             || (GET_CODE (reload_out[r]) == MEM
+                 && GET_CODE (reload_out_reg[r]) == REG)))
        {
-         register int nregno = REGNO (reload_out[r]);
+         rtx out = (GET_CODE (reload_out[r]) == REG
+                    ? reload_out[r] : reload_out_reg[r]);
+         register int nregno = REGNO (out);
          if (nregno >= FIRST_PSEUDO_REGISTER)
-           reg_last_reload_reg[nregno] = 0;
+           {
+             rtx src_reg, store_insn;
+
+             reg_last_reload_reg[nregno] = 0;
+
+             /* If we can find a hard register that is stored, record
+                the storing insn so that we may delete this insn with
+                delete_output_reload.  */
+             src_reg = reload_reg_rtx[r];
+
+             /* If this is an optional reload, try to find the source reg
+                from an input reload.  */
+             if (! src_reg)
+               {
+                 rtx set = single_set (insn);
+                 if (SET_DEST (set) == reload_out[r])
+                   {
+                     int k;
+
+                     src_reg = SET_SRC (set);
+                     store_insn = insn;
+                     for (k = 0; k < n_reloads; k++)
+                       {
+                         if (reload_in[k] == src_reg)
+                           {
+                             src_reg = reload_reg_rtx[k];
+                             break;
+                           }
+                       }
+                   }
+               }
+             else
+               store_insn = new_spill_reg_store[REGNO (src_reg)];
+             if (src_reg && GET_CODE (src_reg) == REG
+                 && REGNO (src_reg) < FIRST_PSEUDO_REGISTER)
+               {
+                 int src_regno = REGNO (src_reg);
+                 int nr = HARD_REGNO_NREGS (src_regno, reload_mode[r]);
+                 /* The place where to find a death note varies with
+                    PRESERVE_DEATH_INFO_REGNO_P .  The condition is not
+                    necessarily checked exactly in the code that moves
+                    notes, so just check both locations.  */
+                 rtx note = find_regno_note (insn, REG_DEAD, src_regno);
+                 if (! note)
+                   note = find_regno_note (store_insn, REG_DEAD, src_regno);
+                 while (nr-- > 0)
+                   {
+                     spill_reg_store[src_regno + nr] = store_insn;
+                     spill_reg_stored_to[src_regno + nr] = out;
+                     reg_reloaded_contents[src_regno + nr] = nregno;
+                     reg_reloaded_insn[src_regno + nr] = store_insn;
+                     CLEAR_HARD_REG_BIT (reg_reloaded_dead, src_regno + nr);
+                     SET_HARD_REG_BIT (reg_reloaded_valid, src_regno + nr);
+                     SET_HARD_REG_BIT (reg_is_output_reload, src_regno + nr);
+                     if (note)
+                       SET_HARD_REG_BIT (reg_reloaded_died, src_regno);
+                     else
+                       CLEAR_HARD_REG_BIT (reg_reloaded_died, src_regno);
+                   }
+                 reg_last_reload_reg[nregno] = src_reg;
+               }
+           }
          else
            {
              int num_regs = HARD_REGNO_NREGS (nregno,GET_MODE (reload_out[r]));
@@ -7232,13 +7697,19 @@ gen_reload (out, in, opnum, type)
             its validity determination, i.e., the way it would after reload
             has completed.  */
          if (constrain_operands (code, 1))
-           return insn;
+           {
+             /* Add a REG_EQUIV note so that find_equiv_reg can find it.  */
+             REG_NOTES (insn)
+               = gen_rtx_EXPR_LIST (REG_EQUIV, in, REG_NOTES (insn));
+             return insn;
+           }
        }
 
       delete_insns_since (last);
 
       gen_reload (out, op1, opnum, type);
-      emit_insn (gen_add2_insn (out, op0));
+      insn = emit_insn (gen_add2_insn (out, op0));
+      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUIV, in, REG_NOTES (insn));
     }
 
 #ifdef SECONDARY_MEMORY_NEEDED
@@ -7290,22 +7761,68 @@ gen_reload (out, in, opnum, type)
    First we double-check.
 
    INSN is the insn now being processed.
-   OUTPUT_RELOAD_INSN is the insn of the output reload.
-   J is the reload-number for this insn.  */
+   LAST_RELOAD_REG is the hard register number for which we want to delete
+   the last output reload.
+   J is the reload-number that originally used REG.  The caller has made
+   certain that reload J doesn't use REG any longer for input.  */
 
 static void
-delete_output_reload (insn, j, output_reload_insn)
+delete_output_reload (insn, j, last_reload_reg)
      rtx insn;
      int j;
-     rtx output_reload_insn;
+     int last_reload_reg;
 {
+  rtx output_reload_insn = spill_reg_store[last_reload_reg];
+  rtx reg = spill_reg_stored_to[last_reload_reg];
+  int k;
+  int n_occurrences;
+  int n_inherited = 0;
   register rtx i1;
-
+  rtx substed;
+  
   /* Get the raw pseudo-register referred to.  */
 
-  rtx reg = reload_in[j];
   while (GET_CODE (reg) == SUBREG)
     reg = SUBREG_REG (reg);
+  substed = reg_equiv_memory_loc[REGNO (reg)];
+
+  /* This is unsafe if the operand occurs more often in the current
+     insn than it is inherited.  */
+  for (k = n_reloads - 1; k >= 0; k--)
+    {
+      rtx reg2 = reload_in[k];
+      if (! reg2)
+       continue;
+      if (GET_CODE (reg2) == MEM || reload_override_in[k])
+       reg2 = reload_in_reg[k];
+#ifdef AUTO_INC_DEC
+      if (reload_out[k] && ! reload_out_reg[k])
+       reg2 = XEXP (reload_in_reg[k], 0);
+#endif
+      while (GET_CODE (reg2) == SUBREG)
+       reg2 = SUBREG_REG (reg2);
+      if (rtx_equal_p (reg2, reg))
+       {
+         if (reload_inherited[k] || reload_override_in[k] || k == j)
+           {
+             n_inherited++;
+             reg2 = reload_out_reg[k];
+             if (! reg2)
+               continue;
+             while (GET_CODE (reg2) == SUBREG)
+               reg2 = XEXP (reg2, 0);
+             if (rtx_equal_p (reg2, reg))
+               n_inherited++;
+           }
+         else
+           return;
+       }
+    }
+  n_occurrences = count_occurrences (PATTERN (insn), reg);
+  if (substed)
+    n_occurrences += count_occurrences (PATTERN (insn), substed);
+  if (n_occurrences > n_inherited)
+    return;
 
   /* If the pseudo-reg we are reloading is no longer referenced
      anywhere between the store into it and here,
@@ -7319,20 +7836,33 @@ delete_output_reload (insn, j, output_reload_insn)
        return;
       if ((GET_CODE (i1) == INSN || GET_CODE (i1) == CALL_INSN)
          && reg_mentioned_p (reg, PATTERN (i1)))
-       return;
+       {
+         /* If this is USE in front of INSN, we only have to check that
+            there are no more references than accounted for by inheritance.  */
+         while (GET_CODE (i1) == INSN && GET_CODE (PATTERN (i1)) == USE)
+           {
+             n_occurrences += rtx_equal_p (reg, XEXP (PATTERN (i1), 0)) != 0;
+             i1 = NEXT_INSN (i1);
+           }
+         if (n_occurrences <= n_inherited && i1 == insn)
+           break;
+         return;
+       }
     }
 
-  /* If this insn will store in the pseudo again,
-     the previous store can be removed.  */
-  if (reload_out[j] == reload_in[j])
-    delete_insn (output_reload_insn);
-
-  /* See if the pseudo reg has been completely replaced
+  /* The caller has already checked that REG dies or is set in INSN.
+     It has also checked that we are optimizing, and thus some inaccurancies
+     in the debugging information are acceptable.
+     So we could just delete output_reload_insn.
+     But in some cases we can improve the debugging information without
+     sacrificing optimization - maybe even improving the code:
+     See if the pseudo reg has been completely replaced
      with reload regs.  If so, delete the store insn
      and forget we had a stack slot for the pseudo.  */
-  else if (REG_N_DEATHS (REGNO (reg)) == 1
-          && REG_BASIC_BLOCK (REGNO (reg)) >= 0
-          && find_regno_note (insn, REG_DEAD, REGNO (reg)))
+  if (reload_out[j] != reload_in[j]
+      && REG_N_DEATHS (REGNO (reg)) == 1
+      && REG_BASIC_BLOCK (REGNO (reg)) >= 0
+      && find_regno_note (insn, REG_DEAD, REGNO (reg)))
     {
       rtx i2;
 
@@ -7354,9 +7884,15 @@ delete_output_reload (insn, j, output_reload_insn)
            break;
          if ((GET_CODE (i2) == INSN || GET_CODE (i2) == CALL_INSN)
              && reg_mentioned_p (reg, PATTERN (i2)))
-           /* Some other ref remains;
-              we can't do anything.  */
-           return;
+           {
+             /* Some other ref remains; just delete the output reload we
+                know to be dead.  */
+             delete_address_reloads (output_reload_insn, insn);
+             PUT_CODE (output_reload_insn, NOTE);
+             NOTE_SOURCE_FILE (output_reload_insn) = 0;
+             NOTE_LINE_NUMBER (output_reload_insn) = NOTE_INSN_DELETED;
+             return;
+           }
        }
 
       /* Delete the now-dead stores into this pseudo.  */
@@ -7366,6 +7902,7 @@ delete_output_reload (insn, j, output_reload_insn)
 
          if (set != 0 && SET_DEST (set) == reg)
            {
+             delete_address_reloads (i2, insn);
              /* This might be a basic block head,
                 thus don't use delete_insn.  */
              PUT_CODE (i2, NOTE);
@@ -7382,20 +7919,178 @@ delete_output_reload (insn, j, output_reload_insn)
       reg_renumber[REGNO (reg)] = REGNO (reload_reg_rtx[j]);
       alter_reg (REGNO (reg), -1);
     }
+  delete_address_reloads (output_reload_insn, insn);
+  PUT_CODE (output_reload_insn, NOTE);
+  NOTE_SOURCE_FILE (output_reload_insn) = 0;
+  NOTE_LINE_NUMBER (output_reload_insn) = NOTE_INSN_DELETED;
+
+}
+
+/* We are going to delete DEAD_INSN.  Recursively delete loads of
+   reload registers used in DEAD_INSN that are not used till CURRENT_INSN.
+   CURRENT_INSN is being reloaded, so we have to check its reloads too.  */
+static void
+delete_address_reloads (dead_insn, current_insn)
+     rtx dead_insn, current_insn;
+{
+  rtx set = single_set (dead_insn);
+  rtx set2, dst, prev, next;
+  if (set)
+    {
+      rtx dst = SET_DEST (set);
+      if (GET_CODE (dst) == MEM)
+       delete_address_reloads_1 (dead_insn, XEXP (dst, 0), current_insn);
+    }
+  /* If we deleted the store from a reloaded post_{in,de}c expression,
+     we can delete the matching adds.  */
+  prev = PREV_INSN (dead_insn);
+  next = NEXT_INSN (dead_insn);
+  if (! prev || ! next)
+    return;
+  set = single_set (next);
+  set2 = single_set (prev);
+  if (! set || ! set2
+      || GET_CODE (SET_SRC (set)) != PLUS || GET_CODE (SET_SRC (set2)) != PLUS
+      || GET_CODE (XEXP (SET_SRC (set), 1)) != CONST_INT
+      || GET_CODE (XEXP (SET_SRC (set2), 1)) != CONST_INT)
+    return;
+  dst = SET_DEST (set);
+  if (! rtx_equal_p (dst, SET_DEST (set2))
+      || ! rtx_equal_p (dst, XEXP (SET_SRC (set), 0))
+      || ! rtx_equal_p (dst, XEXP (SET_SRC (set2), 0))
+      || (INTVAL (XEXP (SET_SRC (set), 1))
+         != - INTVAL (XEXP (SET_SRC (set2), 1))))
+    return;
+  delete_insn (prev);
+  delete_insn (next);
+}
+
+/* Subfunction of delete_address_reloads: process registers found in X.  */
+static void
+delete_address_reloads_1 (dead_insn, x, current_insn)
+     rtx dead_insn, x, current_insn;
+{
+  rtx prev, set, dst, i2;
+  int i, j;
+  enum rtx_code code = GET_CODE (x);
+
+  if (code != REG)
+    {
+      char *fmt= GET_RTX_FORMAT (code);
+      for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+       {
+         if (fmt[i] == 'e')
+           delete_address_reloads_1 (dead_insn, XEXP (x, i), current_insn);
+         else if (fmt[i] == 'E')
+           {
+             for (j = XVECLEN (x, i) - 1; j >=0; j--)
+               delete_address_reloads_1 (dead_insn, XVECEXP (x, i, j),
+                                         current_insn);
+           }
+       }
+      return;
+    }
+
+  if (spill_reg_order[REGNO (x)] < 0)
+    return;
+
+  /* Scan backwards for the insn that sets x.  This might be a way back due
+     to inheritance.  */
+  for (prev = PREV_INSN (dead_insn); prev; prev = PREV_INSN (prev))
+    {
+      code = GET_CODE (prev);
+      if (code == CODE_LABEL || code == JUMP_INSN)
+       return;
+      if (GET_RTX_CLASS (code) != 'i')
+       continue;
+      if (reg_set_p (x, PATTERN (prev)))
+       break;
+      if (reg_referenced_p (x, PATTERN (prev)))
+       return;
+    }
+  if (! prev || INSN_UID (prev) < reload_first_uid)
+    return;
+  /* Check that PREV only sets the reload register.  */
+  set = single_set (prev);
+  if (! set)
+    return;
+  dst = SET_DEST (set);
+  if (GET_CODE (dst) != REG
+      || ! rtx_equal_p (dst, x))
+    return;
+  if (! reg_set_p (dst, PATTERN (dead_insn)))
+    {
+      /* Check if DST was used in a later insn -
+        it might have been inherited.  */
+      for (i2 = NEXT_INSN (dead_insn); i2; i2 = NEXT_INSN (i2))
+       {
+         if (GET_CODE (i2) == CODE_LABEL)
+           break;
+         if (GET_RTX_CLASS (GET_CODE (i2)) != 'i')
+           continue;
+         if (reg_referenced_p (dst, PATTERN (i2)))
+           {
+             /* If there is a reference to the register in the current insn,
+                it might be loaded in a non-inherited reload.  If no other
+                reload uses it, that means the register is set before
+                referenced.  */
+             if (i2 == current_insn)
+               {
+                 for (j = n_reloads - 1; j >= 0; j--)
+                   if ((reload_reg_rtx[j] == dst && reload_inherited[j])
+                       || reload_override_in[j] == dst)
+                     return;
+                 for (j = n_reloads - 1; j >= 0; j--)
+                   if (reload_in[j] && reload_reg_rtx[j] == dst)
+                     break;
+                 if (j >= 0)
+                   break;
+               }
+             return;
+           }
+         if (GET_CODE (i2) == JUMP_INSN)
+           break;
+         if (reg_set_p (dst, PATTERN (i2)))
+           break;
+         /* If DST is still live at CURRENT_INSN, check if it is used for
+            any reload.  */
+         if (i2 == current_insn)
+           {
+             for (j = n_reloads - 1; j >= 0; j--)
+               if ((reload_reg_rtx[j] == dst && reload_inherited[j])
+                   || reload_override_in[j] == dst)
+                 return;
+             /* ??? We can't finish the loop here, because dst might be
+                allocated to a pseudo in this block if no reload in this
+                block needs any of the clsses containing DST - see
+                spill_hard_reg.  There is no easy way to tell this, so we
+                have to scan till the end of the basic block.  */
+           }
+       }
+    }
+  delete_address_reloads_1 (prev, SET_SRC (set), current_insn);
+  reg_reloaded_contents[REGNO (dst)] = -1;
+  /* Can't use delete_insn here because PREV might be a basic block head.  */
+  PUT_CODE (prev, NOTE);
+  NOTE_LINE_NUMBER (prev) = NOTE_INSN_DELETED;
+  NOTE_SOURCE_FILE (prev) = 0;
 }
 \f
 /* Output reload-insns to reload VALUE into RELOADREG.
    VALUE is an autoincrement or autodecrement RTX whose operand
    is a register or memory location;
    so reloading involves incrementing that location.
+   IN is either identical to VALUE, or some cheaper place to reload from.
 
    INC_AMOUNT is the number to increment or decrement by (always positive).
-   This cannot be deduced from VALUE.  */
+   This cannot be deduced from VALUE.
 
-static void
-inc_for_reload (reloadreg, value, inc_amount)
+   Return the instruction that stores into RELOADREG.  */
+
+static rtx
+inc_for_reload (reloadreg, in, value, inc_amount)
      rtx reloadreg;
-     rtx value;
+     rtx in, value;
      int inc_amount;
 {
   /* REG or MEM to be copied and incremented.  */
@@ -7406,6 +8101,8 @@ inc_for_reload (reloadreg, value, inc_amount)
   rtx inc;
   rtx add_insn;
   int code;
+  rtx store;
+  rtx real_in = in == value ? XEXP (in, 0) : in;
 
   /* No hard register is equivalent to this register after
      inc/dec operation.  If REG_LAST_RELOAD_REG were non-zero,
@@ -7420,36 +8117,38 @@ inc_for_reload (reloadreg, value, inc_amount)
   inc = GEN_INT (inc_amount);
 
   /* If this is post-increment, first copy the location to the reload reg.  */
-  if (post)
-    emit_insn (gen_move_insn (reloadreg, incloc));
+  if (post && real_in != reloadreg)
+    emit_insn (gen_move_insn (reloadreg, real_in));
 
-  /* See if we can directly increment INCLOC.  Use a method similar to that
-     in gen_reload.  */
+  if (in == value)
+    {
+      /* See if we can directly increment INCLOC.  Use a method similar to
+        that in gen_reload.  */
 
-  last = get_last_insn ();
-  add_insn = emit_insn (gen_rtx_SET (VOIDmode, incloc,
-                                    gen_rtx_PLUS (GET_MODE (incloc),
-                                                  incloc, inc)));
+      last = get_last_insn ();
+      add_insn = emit_insn (gen_rtx_SET (VOIDmode, incloc,
+                                        gen_rtx_PLUS (GET_MODE (incloc),
+                                                      incloc, inc)));
                                                          
-  code = recog_memoized (add_insn);
-  if (code >= 0)
-    {
-      insn_extract (add_insn);
-      if (constrain_operands (code, 1))
+      code = recog_memoized (add_insn);
+      if (code >= 0)
        {
-         /* If this is a pre-increment and we have incremented the value
-            where it lives, copy the incremented value to RELOADREG to
-            be used as an address.  */
+         insn_extract (add_insn);
+         if (constrain_operands (code, 1))
+           {
+             /* If this is a pre-increment and we have incremented the value
+                where it lives, copy the incremented value to RELOADREG to
+                be used as an address.  */
 
-         if (! post)
-           emit_insn (gen_move_insn (reloadreg, incloc));
+             if (! post)
+               emit_insn (gen_move_insn (reloadreg, incloc));
 
-         return;
+             return add_insn;
+           }
        }
+      delete_insns_since (last);
     }
 
-  delete_insns_since (last);
-
   /* If couldn't do the increment directly, must increment in RELOADREG.
      The way we do this depends on whether this is pre- or post-increment.
      For pre-increment, copy INCLOC to the reload register, increment it
@@ -7457,9 +8156,10 @@ inc_for_reload (reloadreg, value, inc_amount)
 
   if (! post)
     {
-      emit_insn (gen_move_insn (reloadreg, incloc));
+      if (in != reloadreg)
+       emit_insn (gen_move_insn (reloadreg, real_in));
       emit_insn (gen_add2_insn (reloadreg, inc));
-      emit_insn (gen_move_insn (incloc, reloadreg));
+      store = emit_insn (gen_move_insn (incloc, reloadreg));
     }
   else
     {
@@ -7468,16 +8168,16 @@ inc_for_reload (reloadreg, value, inc_amount)
         may not be available after the insn in an input reload, we must do
         the incrementation before the insn being reloaded for.
 
-        We have already copied INCLOC to RELOADREG.  Increment the copy in
+        We have already copied IN to RELOADREG.  Increment the copy in
         RELOADREG, save that back, then decrement RELOADREG so it has
         the original value.  */
 
       emit_insn (gen_add2_insn (reloadreg, inc));
-      emit_insn (gen_move_insn (incloc, reloadreg));
+      store = emit_insn (gen_move_insn (incloc, reloadreg));
       emit_insn (gen_add2_insn (reloadreg, GEN_INT (-inc_amount)));
     }
 
-  return;
+  return store;
 }
 \f
 /* Return 1 if we are certain that the constraint-string STRING allows
@@ -7556,6 +8256,10 @@ count_occurrences (x, find)
     case CC0:
       return 0;
 
+    case MEM:
+      if (GET_CODE (find) == MEM && rtx_equal_p (x, find))
+       return 1;
+      break;
     case SET:
       if (SET_DEST (x) == find)
        return count_occurrences (SET_SRC (x), find);
@@ -7610,13 +8314,6 @@ static rtx *reg_values;
 
 static rtx invalidate_regno_rtx;
 
-/* This is a set of registers for which we must remove REG_DEAD notes in
-   previous insns, because our modifications made them invalid.  That can
-   happen if we introduced the register into the current insn, or we deleted
-   the current insn which used to set the register.  */
-
-static HARD_REG_SET no_longer_dead_regs;
-
 /* Invalidate any entries in reg_values which depend on REGNO,
    including those for REGNO itself.  This is called if REGNO is
    changing.  If CLOBBER is true, then always forget anything we
@@ -7805,7 +8502,7 @@ reload_cse_invalidate_mem (mem_rtx)
 static void
 reload_cse_invalidate_rtx (dest, ignore)
      rtx dest;
-     rtx ignore;
+     rtx ignore ATTRIBUTE_UNUSED;
 {
   while (GET_CODE (dest) == STRICT_LOW_PART
         || GET_CODE (dest) == SIGN_EXTRACT
@@ -7819,55 +8516,6 @@ reload_cse_invalidate_rtx (dest, ignore)
     reload_cse_invalidate_mem (dest);
 }
 
-/* Possibly delete death notes on the insns before INSN if modifying INSN
-   extended the lifespan of the registers.  */
-
-static void
-reload_cse_delete_death_notes (insn)
-     rtx insn;
-{
-  int dreg;
-
-  for (dreg = 0; dreg < FIRST_PSEUDO_REGISTER; dreg++)
-    {
-      rtx trial;
-
-      if (! TEST_HARD_REG_BIT (no_longer_dead_regs, dreg))
-       continue;
-
-      for (trial = prev_nonnote_insn (insn);
-          (trial
-           && GET_CODE (trial) != CODE_LABEL
-           && GET_CODE (trial) != BARRIER);
-          trial = prev_nonnote_insn (trial))
-       {
-         if (find_regno_note (trial, REG_DEAD, dreg))
-           {
-             remove_death (dreg, trial);
-             break;
-           }
-       }
-    }
-}
-
-/* Record that the current insn uses hard reg REGNO in mode MODE.  This
-   will be used in reload_cse_delete_death_notes to delete prior REG_DEAD
-   notes for this register.  */
-
-static void
-reload_cse_no_longer_dead (regno, mode)
-     int regno;
-     enum machine_mode mode;
-{
-  int nregs = HARD_REGNO_NREGS (regno, mode);
-  while (nregs-- > 0)
-    {
-      SET_HARD_REG_BIT (no_longer_dead_regs, regno);
-      regno++;
-    }
-}
-
-
 /* Do a very simple CSE pass over the hard registers.
 
    This function detects no-op moves where we happened to assign two
@@ -7885,8 +8533,8 @@ reload_cse_no_longer_dead (regno, mode)
    hard register.  It then replaces the operand with the hard register
    if possible, much like an optional reload would.  */
 
-void
-reload_cse_regs (first)
+static void
+reload_cse_regs_1 (first)
      rtx first;
 {
   char *firstobj;
@@ -7897,8 +8545,7 @@ reload_cse_regs (first)
   init_alias_analysis ();
 
   reg_values = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    reg_values[i] = 0;
+  bzero ((char *)reg_values, FIRST_PSEUDO_REGISTER * sizeof (rtx));
 
   /* Create our EXPR_LIST structures on reload_obstack, so that we can
      free them when we are done.  */
@@ -7941,8 +8588,6 @@ reload_cse_regs (first)
       if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
        continue;
 
-      CLEAR_HARD_REG_SET (no_longer_dead_regs);
-
       /* If this is a call instruction, forget anything stored in a
         call clobbered register, or, if this is not a const call, in
         memory.  */
@@ -7962,58 +8607,96 @@ reload_cse_regs (first)
          int count = 0;
          if (reload_cse_noop_set_p (body, insn))
            {
-             PUT_CODE (insn, NOTE);
-             NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-             NOTE_SOURCE_FILE (insn) = 0;
-             reload_cse_delete_death_notes (insn);
+             /* If this sets the return value of the function, we must keep
+                a USE around, in case this is in a different basic block
+                than the final USE.  Otherwise, we could loose important
+                register lifeness information on SMALL_REGISTER_CLASSES
+                machines, where return registers might be used as spills:
+                subsequent passes assume that spill registers are dead at
+                the end of a basic block.  */
+             if (REG_FUNCTION_VALUE_P (SET_DEST (body)))
+               {
+                 pop_obstacks ();
+                 PATTERN (insn) = gen_rtx_USE (VOIDmode, SET_DEST (body));
+                 INSN_CODE (insn) = -1;
+                 REG_NOTES (insn) = NULL_RTX;
+                 push_obstacks (&reload_obstack, &reload_obstack);
+               }
+             else
+               {
+                 PUT_CODE (insn, NOTE);
+                 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+                 NOTE_SOURCE_FILE (insn) = 0;
+               }
 
              /* We're done with this insn.  */
              continue;
            }
 
          /* It's not a no-op, but we can try to simplify it.  */
-         CLEAR_HARD_REG_SET (no_longer_dead_regs);
          count += reload_cse_simplify_set (body, insn);
 
-         if (count > 0 && apply_change_group ())
-           reload_cse_delete_death_notes (insn);
-         else if (reload_cse_simplify_operands (insn))
-           reload_cse_delete_death_notes (insn);
+         if (count > 0)
+           apply_change_group ();
+         else
+           reload_cse_simplify_operands (insn);
            
          reload_cse_record_set (body, body);
        }
       else if (GET_CODE (body) == PARALLEL)
        {
          int count = 0;
+         rtx value = NULL_RTX;
 
          /* If every action in a PARALLEL is a noop, we can delete
              the entire PARALLEL.  */
          for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
-           if ((GET_CODE (XVECEXP (body, 0, i)) != SET
-                || ! reload_cse_noop_set_p (XVECEXP (body, 0, i), insn))
-               && GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
-             break;
+           {
+             rtx part = XVECEXP (body, 0, i);
+             if (GET_CODE (part) == SET)
+               {
+                 if (! reload_cse_noop_set_p (part, insn))
+                   break;
+                 if (REG_FUNCTION_VALUE_P (SET_DEST (part)))
+                   {
+                     if (value)
+                       break;
+                     value = SET_DEST (part);
+                   }
+               }
+             else if (GET_CODE (part) != CLOBBER)
+               break;
+           }
          if (i < 0)
            {
-             PUT_CODE (insn, NOTE);
-             NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-             NOTE_SOURCE_FILE (insn) = 0;
-             reload_cse_delete_death_notes (insn);
+             if (value)
+               {
+                 pop_obstacks ();
+                 PATTERN (insn) = gen_rtx_USE (VOIDmode, value);
+                 INSN_CODE (insn) = -1;
+                 REG_NOTES (insn) = NULL_RTX;
+                 push_obstacks (&reload_obstack, &reload_obstack);
+               }
+             else
+               {
+                 PUT_CODE (insn, NOTE);
+                 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+                 NOTE_SOURCE_FILE (insn) = 0;
+               }
 
              /* We're done with this insn.  */
              continue;
            }
          
          /* It's not a no-op, but we can try to simplify it.  */
-         CLEAR_HARD_REG_SET (no_longer_dead_regs);
          for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
            if (GET_CODE (XVECEXP (body, 0, i)) == SET)
              count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn);
 
-         if (count > 0 && apply_change_group ())
-           reload_cse_delete_death_notes (insn);
-         else if (reload_cse_simplify_operands (insn))
-           reload_cse_delete_death_notes (insn);
+         if (count > 0)
+           apply_change_group ();
+         else
+           reload_cse_simplify_operands (insn);
 
          /* Look through the PARALLEL and record the values being
              set, if possible.  Also handle any CLOBBERs.  */
@@ -8061,6 +8744,19 @@ reload_cse_regs (first)
   pop_obstacks ();
 }
 
+/* Call cse / combine like post-reload optimization phases.
+   FIRST is the first instruction.  */
+void
+reload_cse_regs (first)
+     rtx first;
+{
+  reload_cse_regs_1 (first);
+  reload_combine ();
+  reload_cse_move2add (first);
+  if (flag_expensive_optimizations)
+    reload_cse_regs_1 (first);
+}
+
 /* Return whether the values known for REGNO are equal to VAL.  MODE
    is the mode of the object that VAL is being copied to; this matters
    if VAL is a CONST_INT.  */
@@ -8079,6 +8775,8 @@ reload_cse_regno_equal_p (regno, val, mode)
   for (x = reg_values[regno]; x; x = XEXP (x, 1))
     if (XEXP (x, 0) != 0
        && rtx_equal_p (XEXP (x, 0), val)
+       && (! flag_float_store || GET_CODE (XEXP (x, 0)) != MEM
+           || GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT)
        && (GET_CODE (val) != CONST_INT
            || mode == GET_MODE (x)
            || (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x))
@@ -8177,14 +8875,6 @@ reload_cse_noop_set_p (set, insn)
        ret = 1;
     }
 
-  /* If we can delete this SET, then we need to look for an earlier
-     REG_DEAD note on DREG, and remove it if it exists.  */
-  if (ret && dreg >= 0)
-    {
-      if (! find_regno_note (insn, REG_UNUSED, dreg))
-       reload_cse_no_longer_dead (dreg, dest_mode);
-    }
-
   return ret;
 }
 
@@ -8215,12 +8905,16 @@ reload_cse_simplify_set (set, insn)
 
   dclass = REGNO_REG_CLASS (dreg);
 
-  /* If memory loads are cheaper than register copies, don't change
-     them.  */
+  /* If memory loads are cheaper than register copies, don't change them.  */
   if (GET_CODE (src) == MEM
       && MEMORY_MOVE_COST (GET_MODE (src), dclass, 1) < 2)
     return 0;
 
+  /* If the constant is cheaper than a register, don't change it.  */
+  if (CONSTANT_P (src)
+      && rtx_cost (src, SET) < 2)
+    return 0;
+
   dest_mode = GET_MODE (SET_DEST (set));
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
@@ -8240,11 +8934,8 @@ reload_cse_simplify_set (set, insn)
              storage.  */
          push_obstacks (&reload_obstack, &reload_obstack);
 
-         if (validated && ! find_regno_note (insn, REG_UNUSED, i))
-           {
-             reload_cse_no_longer_dead (i, dest_mode);
-             return 1;
-           }
+         if (validated)
+           return 1;
        }
     }
   return 0;
@@ -8282,6 +8973,7 @@ reload_cse_simplify_operands (insn)
   int *op_alt_regno[MAX_RECOG_OPERANDS];
   /* Array of alternatives, sorted in order of decreasing desirability.  */
   int *alternative_order;
+  rtx reg = gen_rtx_REG (VOIDmode, -1);
   
   /* Find out some information about this insn.  */
   insn_code_number = recog_memoized (insn);
@@ -8298,7 +8990,7 @@ reload_cse_simplify_operands (insn)
 
   /* Figure out which alternative currently matches.  */
   if (! constrain_operands (insn_code_number, 1))
-    abort ();
+    fatal_insn_not_found (insn);
 
   alternative_reject = (int *) alloca (n_alternatives * sizeof (int));
   alternative_nregs = (int *) alloca (n_alternatives * sizeof (int));
@@ -8348,6 +9040,9 @@ reload_cse_simplify_operands (insn)
          if (! reload_cse_regno_equal_p (regno, recog_operand[i], mode))
            continue;
 
+         REGNO (reg) = regno;
+         PUT_MODE (reg, mode);
+
          /* We found a register equal to this operand.  Now look for all
             alternatives that can accept this register and have not been
             assigned a register they can use yet.  */
@@ -8381,16 +9076,18 @@ reload_cse_simplify_operands (insn)
 
                default:
                  class
-                   = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER (c)];
+                   = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER ((unsigned char)c)];
                  break;
 
                case ',': case '\0':
                  /* See if REGNO fits this alternative, and set it up as the
                     replacement register if we don't have one for this
-                    alternative yet.  */
+                    alternative yet and the operand being replaced is not
+                    a cheap CONST_INT. */
                  if (op_alt_regno[i][j] == -1
-                     && reg_fits_class_p (gen_rtx_REG (mode, regno), class,
-                                          0, mode))
+                     && reg_fits_class_p (reg, class, 0, mode)
+                     && (GET_CODE (recog_operand[i]) != CONST_INT
+                         || rtx_cost (recog_operand[i], SET) > rtx_cost (reg, SET)))
                    {
                      alternative_nregs[j]++;
                      op_alt_regno[i][j] = regno;
@@ -8443,7 +9140,6 @@ reload_cse_simplify_operands (insn)
   /* Substitute the operands as determined by op_alt_regno for the best
      alternative.  */
   j = alternative_order[0];
-  CLEAR_HARD_REG_SET (no_longer_dead_regs);
 
   /* Pop back to the real obstacks while changing the insn.  */
   pop_obstacks ();
@@ -8454,7 +9150,6 @@ reload_cse_simplify_operands (insn)
       if (op_alt_regno[i][j] == -1)
        continue;
 
-      reload_cse_no_longer_dead (op_alt_regno[i][j], mode);
       validate_change (insn, recog_operand_loc[i],
                       gen_rtx_REG (mode, op_alt_regno[i][j]), 1);
     }
@@ -8467,7 +9162,6 @@ reload_cse_simplify_operands (insn)
       if (op_alt_regno[op][j] == -1)
        continue;
 
-      reload_cse_no_longer_dead (op_alt_regno[op][j], mode);
       validate_change (insn, recog_dup_loc[i],
                       gen_rtx_REG (mode, op_alt_regno[op][j]), 1);
     }
@@ -8495,7 +9189,7 @@ static rtx reload_cse_check_src;
 static void
 reload_cse_check_clobber (dest, ignore)
      rtx dest;
-     rtx ignore;
+     rtx ignore ATTRIBUTE_UNUSED;
 {
   if (reg_overlap_mentioned_p (dest, reload_cse_check_src))
     reload_cse_check_clobbered = 1;
@@ -8646,3 +9340,647 @@ reload_cse_record_set (set, body)
       abort ();
     }
 }
+\f
+/* If reload couldn't use reg+reg+offset addressing, try to use reg+reg
+   addressing now.
+   This code might also be useful when reload gave up on reg+reg addresssing
+   because of clashes between the return register and INDEX_REG_CLASS.  */
+
+/* The maximum number of uses of a register we can keep track of to
+   replace them with reg+reg addressing.  */
+#define RELOAD_COMBINE_MAX_USES 6
+
+/* INSN is the insn where a register has ben used, and USEP points to the
+   location of the register within the rtl.  */
+struct reg_use { rtx insn, *usep; };
+
+/* If the register is used in some unknown fashion, USE_INDEX is negative.
+   If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID
+   indicates where it becomes live again.
+   Otherwise, USE_INDEX is the index of the last encountered use of the
+   register (which is first among these we have seen since we scan backwards),
+   OFFSET contains the constant offset that is added to the register in
+   all encountered uses, and USE_RUID indicates the first encountered, i.e.
+   last, of these uses.  */
+static struct
+  {
+    struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
+    int use_index;
+    rtx offset;
+    int store_ruid;
+    int use_ruid;
+  } reg_state[FIRST_PSEUDO_REGISTER];
+
+/* Reverse linear uid.  This is increased in reload_combine while scanning
+   the instructions from last to first.  It is used to set last_label_ruid
+   and the store_ruid / use_ruid fields in reg_state.  */
+static int reload_combine_ruid;
+
+static void
+reload_combine ()
+{
+  rtx insn, set;
+  int first_index_reg = 1, last_index_reg = 0;
+  int i;
+  int last_label_ruid;
+
+  /* If reg+reg can be used in offsetable memory adresses, the main chunk of
+     reload has already used it where appropriate, so there is no use in
+     trying to generate it now.  */
+  if (double_reg_address_ok && INDEX_REG_CLASS != NO_REGS)
+    return;
+
+  /* To avoid wasting too much time later searching for an index register,
+     determine the minimum and maximum index register numbers.  */
+  for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
+    {
+      if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i))
+       {
+         if (! last_index_reg)
+           last_index_reg = i;
+         first_index_reg = i;
+       }
+    }
+  /* If no index register is available, we can quit now.  */
+  if (first_index_reg > last_index_reg)
+    return;
+
+  /* Initialize last_label_ruid, reload_combine_ruid and reg_state.  */
+  last_label_ruid = reload_combine_ruid = 0;
+  for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
+    {
+      if (fixed_regs[i])
+       reg_state[i].use_index = -1;
+      else
+       {
+         reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
+         reg_state[i].store_ruid = reload_combine_ruid;
+       }
+    }
+
+  for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
+    {
+      rtx note;
+
+      /* We cannot do our optimization across labels.  Invalidating all the use
+        information we have would be costly, so we just note where the label
+         is and then later disable any optimization that would cross it.  */
+      if (GET_CODE (insn) == CODE_LABEL)
+       last_label_ruid = reload_combine_ruid;
+      if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+       continue;
+      reload_combine_ruid++;
+
+      /* Look for (set (REGX) (CONST_INT))
+                 (set (REGX) (PLUS (REGX) (REGY)))
+                 ...
+                 ... (MEM (REGX)) ...
+        and convert it to
+                 (set (REGZ) (CONST_INT))
+                 ...
+                 ... (MEM (PLUS (REGZ) (REGY)))... .
+
+        First, check that we have (set (REGX) (PLUS (REGX) (REGY)))
+        and that we know all uses of REGX before it dies.  */
+      set = single_set (insn);
+      if (set != NULL_RTX
+         && GET_CODE (SET_DEST (set)) == REG
+         && (HARD_REGNO_NREGS (REGNO (SET_DEST (set)),
+                               GET_MODE (SET_DEST (set)))
+             == 1)
+         && GET_CODE (SET_SRC (set)) == PLUS
+         && GET_CODE (XEXP (SET_SRC (set), 1)) == REG
+         && rtx_equal_p (XEXP (SET_SRC (set), 0), SET_DEST (set))
+         && last_label_ruid < reg_state[REGNO (SET_DEST (set))].use_ruid)
+       {
+         rtx reg = SET_DEST (set);
+         rtx plus = SET_SRC (set);
+         rtx base = XEXP (plus, 1);
+         rtx prev = prev_nonnote_insn (insn);
+         rtx prev_set = prev ? single_set (prev) : NULL_RTX;
+         int regno = REGNO (reg);
+         rtx const_reg;
+         rtx reg_sum = NULL_RTX;
+
+         /* Now, we need an index register.
+            We'll set index_reg to this index register, const_reg to the
+            register that is to be loaded with the constant
+            (denoted as REGZ in the substitution illustration above),
+            and reg_sum to the register-register that we want to use to
+            substitute uses of REG (typically in MEMs) with.
+            First check REG and BASE for being index registers;
+            we can use them even if they are not dead.  */
+         if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno)
+             || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
+                                   REGNO (base)))
+           {
+             const_reg = reg;
+             reg_sum = plus;
+           }
+         else
+           {
+              /* Otherwise, look for a free index register.  Since we have
+                 checked above that neiter REG nor BASE are index registers,
+                 if we find anything at all, it will be different from these
+                 two registers.  */
+              for (i = first_index_reg; i <= last_index_reg; i++)
+               {
+                 if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i)
+                     && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
+                     && reg_state[i].store_ruid <= reg_state[regno].use_ruid
+                     && HARD_REGNO_NREGS (i, GET_MODE (reg)) == 1)
+                   {
+                     rtx index_reg = gen_rtx_REG (GET_MODE (reg), i);
+                     const_reg = index_reg;
+                     reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base);
+                     break;
+                   }
+               }
+           }
+         if (prev_set
+             && GET_CODE (SET_SRC (prev_set)) == CONST_INT
+             && rtx_equal_p (SET_DEST (prev_set), reg)
+             && reg_state[regno].use_index >= 0
+             && reg_sum)
+           {
+             int i;
+
+             /* Change destination register and - if necessary - the
+                constant value in PREV, the constant loading instruction.  */
+             validate_change (prev, &SET_DEST (prev_set), const_reg, 1);
+             if (reg_state[regno].offset != const0_rtx)
+               validate_change (prev,
+                                &SET_SRC (prev_set),
+                                GEN_INT (INTVAL (SET_SRC (prev_set))
+                                         + INTVAL (reg_state[regno].offset)),
+                                1);
+             /* Now for every use of REG that we have recorded, replace REG
+                with REG_SUM.  */
+             for (i = reg_state[regno].use_index;
+                  i < RELOAD_COMBINE_MAX_USES; i++)
+               validate_change (reg_state[regno].reg_use[i].insn,
+                                reg_state[regno].reg_use[i].usep,
+                                reg_sum, 1);
+
+             if (apply_change_group ())
+               {
+                 rtx *np;
+
+                 /* Delete the reg-reg addition.  */
+                 PUT_CODE (insn, NOTE);
+                 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+                 NOTE_SOURCE_FILE (insn) = 0;
+
+                 if (reg_state[regno].offset != const0_rtx)
+                   {
+                     /* Previous REG_EQUIV / REG_EQUAL notes for PREV
+                        are now invalid.  */
+                     for (np = &REG_NOTES (prev); *np; )
+                       {
+                         if (REG_NOTE_KIND (*np) == REG_EQUAL
+                             || REG_NOTE_KIND (*np) == REG_EQUIV)
+                           *np = XEXP (*np, 1);
+                         else
+                           np = &XEXP (*np, 1);
+                       }
+                   }
+                 reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
+                 reg_state[REGNO (const_reg)].store_ruid = reload_combine_ruid;
+                 continue;
+               }
+           }
+       }
+      note_stores (PATTERN (insn), reload_combine_note_store);
+      if (GET_CODE (insn) == CALL_INSN)
+       {
+         rtx link;
+
+         for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
+           {
+             if (call_used_regs[i])
+               {
+                 reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
+                 reg_state[i].store_ruid = reload_combine_ruid;
+               }
+           }
+         for (link = CALL_INSN_FUNCTION_USAGE (insn); link;
+              link = XEXP (link, 1))
+           {
+             rtx use = XEXP (link, 0);
+             int regno = REGNO (XEXP (use, 0));
+             if (GET_CODE (use) == CLOBBER)
+               {
+                 reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
+                 reg_state[regno].store_ruid = reload_combine_ruid;
+               }
+             else
+               reg_state[regno].use_index = -1;
+           }
+       }
+      if (GET_CODE (insn) == JUMP_INSN)
+       {
+         /* Non-spill registers might be used at the call destination in
+            some unknown fashion, so we have to mark the unknown use.  */
+         for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
+           {
+             if (1)
+               reg_state[i].use_index = -1;
+           }
+       }
+      reload_combine_note_use (&PATTERN (insn), insn);
+      for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+       {
+         if (REG_NOTE_KIND (note) == REG_INC
+             && GET_CODE (XEXP (note, 0)) == REG)
+           reg_state[REGNO (XEXP (note, 0))].use_index = -1;
+       }
+    }
+}
+
+/* Check if DST is a register or a subreg of a register; if it is,
+   update reg_state[regno].store_ruid and reg_state[regno].use_index
+   accordingly.  Called via note_stores from reload_combine.
+   The second argument, SET, is ignored.  */
+static void
+reload_combine_note_store (dst, set)
+     rtx dst, set ATTRIBUTE_UNUSED;
+{
+  int regno = 0;
+  int i;
+  unsigned size = GET_MODE_SIZE (GET_MODE (dst));
+
+  if (GET_CODE (dst) == SUBREG)
+    {
+      regno = SUBREG_WORD (dst);
+      dst = SUBREG_REG (dst);
+    }
+  if (GET_CODE (dst) != REG)
+    return;
+  regno += REGNO (dst);
+  /* note_stores might have stripped a STRICT_LOW_PART, so we have to be
+     careful with registers / register parts that are not full words.  */
+  if (size < (unsigned) UNITS_PER_WORD)
+    reg_state[regno].use_index = -1;
+  else
+    {
+      for (i = size / UNITS_PER_WORD - 1 + regno; i >= regno; i--)
+       {
+         reg_state[i].store_ruid = reload_combine_ruid;
+         reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
+       }
+    }
+}
+
+/* XP points to a piece of rtl that has to be checked for any uses of
+   registers.
+   *XP is the pattern of INSN, or a part of it.
+   Called from reload_combine, and recursively by itself.  */
+static void
+reload_combine_note_use (xp, insn)
+     rtx *xp, insn;
+{
+  rtx x = *xp;
+  enum rtx_code code = x->code;
+  char *fmt;
+  int i, j;
+  rtx offset = const0_rtx; /* For the REG case below.  */
+
+  switch (code)
+    {
+    case SET:
+      if (GET_CODE (SET_DEST (x)) == REG)
+       {
+         reload_combine_note_use (&SET_SRC (x), insn);
+         return;
+       }
+      break;
+
+    case CLOBBER:
+      if (GET_CODE (SET_DEST (x)) == REG)
+       return;
+      break;
+
+    case PLUS:
+      /* We are interested in (plus (reg) (const_int)) .  */
+      if (GET_CODE (XEXP (x, 0)) != REG || GET_CODE (XEXP (x, 1)) != CONST_INT)
+       break;
+      offset = XEXP (x, 1);
+      x = XEXP (x, 0);
+    /* Fall through.  */
+    case REG:
+      {
+       int regno = REGNO (x);
+       int use_index;
+
+       /* Some spurious USEs of pseudo registers might remain.
+          Just ignore them.  */
+       if (regno >= FIRST_PSEUDO_REGISTER)
+         return;
+
+       /* If this register is already used in some unknown fashion, we
+          can't do anything.
+          If we decrement the index from zero to -1, we can't store more
+          uses, so this register becomes used in an unknown fashion.  */
+       use_index = --reg_state[regno].use_index;
+       if (use_index < 0)
+         return;
+
+       if (use_index != RELOAD_COMBINE_MAX_USES - 1)
+         {
+           /* We have found another use for a register that is already
+              used later.  Check if the offsets match; if not, mark the
+              register as used in an unknown fashion.  */
+           if (! rtx_equal_p (offset, reg_state[regno].offset))
+             {
+               reg_state[regno].use_index = -1;
+               return;
+             }
+         }
+       else
+         {
+           /* This is the first use of this register we have seen since we
+              marked it as dead.  */
+           reg_state[regno].offset = offset;
+           reg_state[regno].use_ruid = reload_combine_ruid;
+         }
+       reg_state[regno].reg_use[use_index].insn = insn;
+       reg_state[regno].reg_use[use_index].usep = xp;
+       return;
+      }
+
+    default:
+      break;
+    }
+
+  /* Recursively process the components of X.  */
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'e')
+       reload_combine_note_use (&XEXP (x, i), insn);
+      else if (fmt[i] == 'E')
+       {
+         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+           reload_combine_note_use (&XVECEXP (x, i, j), insn);
+       }
+    }
+}
+\f
+/* See if we can reduce the cost of a constant by replacing a move with
+   an add.  */
+/* We cannot do our optimization across labels.  Invalidating all the
+   information about register contents we have would be costly, so we
+   use last_label_luid (local variable of reload_cse_move2add) to note
+   where the label is and then later disable any optimization that would
+   cross it.
+   reg_offset[n] / reg_base_reg[n] / reg_mode[n] are only valid if
+   reg_set_luid[n] is larger than last_label_luid[n] .  */
+static int reg_set_luid[FIRST_PSEUDO_REGISTER];
+/* reg_offset[n] has to be CONST_INT for it and reg_base_reg[n] /
+   reg_mode[n] to be valid.
+   If reg_offset[n] is a CONST_INT and reg_base_reg[n] is negative, register n
+   has been set to reg_offset[n] in mode reg_mode[n] .
+   If reg_offset[n] is a CONST_INT and reg_base_reg[n] is non-negative,
+   register n has been set to the sum of reg_offset[n] and register
+   reg_base_reg[n], calculated in mode reg_mode[n] .  */
+static rtx reg_offset[FIRST_PSEUDO_REGISTER];
+static int reg_base_reg[FIRST_PSEUDO_REGISTER];
+static enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
+/* move2add_luid is linearily increased while scanning the instructions
+   from first to last.  It is used to set reg_set_luid in
+   reload_cse_move2add and move2add_note_store.  */
+static int move2add_luid;
+
+static void
+reload_cse_move2add (first)
+     rtx first;
+{
+  int i;
+  rtx insn;
+  int last_label_luid;
+
+  for (i = FIRST_PSEUDO_REGISTER-1; i >= 0; i--)
+    reg_set_luid[i] = 0;
+
+  last_label_luid = 0;
+  move2add_luid = 1;
+  for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++)
+    {
+      rtx pat, note;
+
+      if (GET_CODE (insn) == CODE_LABEL)
+       last_label_luid = move2add_luid;
+      if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+       continue;
+      pat = PATTERN (insn);
+      /* For simplicity, we only perform this optimization on
+        straightforward SETs.  */
+      if (GET_CODE (pat) == SET
+         && GET_CODE (SET_DEST (pat)) == REG)
+       {
+         rtx reg = SET_DEST (pat);
+         int regno = REGNO (reg);
+         rtx src = SET_SRC (pat);
+
+         /* Check if we have valid information on the contents of this
+            register in the mode of REG.  */
+         /* ??? We don't know how zero / sign extension is handled, hence
+            we can't go from a narrower to a wider mode.  */
+         if (reg_set_luid[regno] > last_label_luid
+            && (GET_MODE_SIZE (GET_MODE (reg))
+                <= GET_MODE_SIZE (reg_mode[regno]))
+            && GET_CODE (reg_offset[regno]) == CONST_INT)
+           {
+             /* Try to transform (set (REGX) (CONST_INT A))
+                                 ...
+                                 (set (REGX) (CONST_INT B))
+                to
+                                 (set (REGX) (CONST_INT A))
+                                 ...
+                                 (set (REGX) (plus (REGX) (CONST_INT B-A)))  */
+
+             if (GET_CODE (src) == CONST_INT && reg_base_reg[regno] < 0)
+               {
+                 int success = 0;
+                 rtx new_src = GEN_INT (INTVAL (src)
+                                        - INTVAL (reg_offset[regno]));
+                 /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
+                    use (set (reg) (reg)) instead.
+                    We don't delete this insn, nor do we convert it into a
+                    note, to avoid losing register notes or the return
+                    value flag.  jump2 already knowns how to get rid of
+                    no-op moves.  */
+                 if (new_src == const0_rtx)
+                   success = validate_change (insn, &SET_SRC (pat), reg, 0);
+                 else if (rtx_cost (new_src, PLUS) < rtx_cost (src, SET)
+                          && have_add2_insn (GET_MODE (reg)))
+                   success = validate_change (insn, &PATTERN (insn),
+                                              gen_add2_insn (reg, new_src), 0);
+                 reg_set_luid[regno] = move2add_luid;
+                 reg_mode[regno] = GET_MODE (reg);
+                 reg_offset[regno] = src;
+                 continue;
+               }
+
+             /* Try to transform (set (REGX) (REGY))
+                                 (set (REGX) (PLUS (REGX) (CONST_INT A)))
+                                 ...
+                                 (set (REGX) (REGY))
+                                 (set (REGX) (PLUS (REGX) (CONST_INT B)))
+                to
+                                 (REGX) (REGY))
+                                 (set (REGX) (PLUS (REGX) (CONST_INT A)))
+                                 ...
+                                 (set (REGX) (plus (REGX) (CONST_INT B-A)))  */
+             else if (GET_CODE (src) == REG
+                      && reg_base_reg[regno] == REGNO (src)
+                      && reg_set_luid[regno] > reg_set_luid[REGNO (src)])
+               {
+                 rtx next = next_nonnote_insn (insn);
+                 rtx set;
+                 if (next)
+                   set = single_set (next);
+                 if (next
+                     && set
+                     && SET_DEST (set) == reg
+                     && GET_CODE (SET_SRC (set)) == PLUS
+                     && XEXP (SET_SRC (set), 0) == reg
+                     && GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
+                   {
+                     rtx src3 = XEXP (SET_SRC (set), 1);
+                     rtx new_src = GEN_INT (INTVAL (src3)
+                                            - INTVAL (reg_offset[regno]));
+                     int success = 0;
+
+                     if (new_src == const0_rtx)
+                       /* See above why we create (set (reg) (reg)) here.  */
+                       success
+                         = validate_change (next, &SET_SRC (set), reg, 0);
+                     else if ((rtx_cost (new_src, PLUS)
+                               < 2 + rtx_cost (src3, SET))
+                              && have_add2_insn (GET_MODE (reg)))
+                       success
+                         = validate_change (next, &PATTERN (next),
+                                            gen_add2_insn (reg, new_src), 0);
+                     if (success)
+                       {
+                         /* INSN might be the first insn in a basic block
+                            if the preceding insn is a conditional jump
+                            or a possible-throwing call.  */
+                         PUT_CODE (insn, NOTE);
+                         NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+                         NOTE_SOURCE_FILE (insn) = 0;
+                       }
+                     insn = next;
+                     reg_set_luid[regno] = move2add_luid;
+                     reg_mode[regno] = GET_MODE (reg);
+                     reg_offset[regno] = src3;
+                     continue;
+                   }
+               }
+           }
+       }
+
+      for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+       {
+         if (REG_NOTE_KIND (note) == REG_INC
+             && GET_CODE (XEXP (note, 0)) == REG)
+           {
+             /* Indicate that this register has been recently written to,
+                but the exact contents are not available.  */
+             int regno = REGNO (XEXP (note, 0));
+             if (regno < FIRST_PSEUDO_REGISTER)
+               {
+                 reg_set_luid[regno] = move2add_luid;
+                 reg_offset[regno] = note;
+               }
+           }
+       }
+      note_stores (PATTERN (insn), move2add_note_store);
+      /* If this is a CALL_INSN, all call used registers are stored with
+        unknown values.  */
+      if (GET_CODE (insn) == CALL_INSN)
+       {
+         for (i = FIRST_PSEUDO_REGISTER-1; i >= 0; i--)
+           {
+             if (call_used_regs[i])
+               {
+                 reg_set_luid[i] = move2add_luid;
+                 reg_offset[i] = insn; /* Invalidate contents.  */
+               }
+           }
+       }
+    }
+}
+
+/* SET is a SET or CLOBBER that sets DST.
+   Update reg_set_luid, reg_offset and reg_base_reg accordingly.
+   Called from reload_cse_move2add via note_stores.  */
+static void
+move2add_note_store (dst, set)
+     rtx dst, set;
+{
+  int regno = 0;
+  int i;
+
+  enum machine_mode mode = GET_MODE (dst);
+  if (GET_CODE (dst) == SUBREG)
+    {
+      regno = SUBREG_WORD (dst);
+      dst = SUBREG_REG (dst);
+    }
+  if (GET_CODE (dst) != REG)
+    return;
+
+  regno += REGNO (dst);
+
+  if (HARD_REGNO_NREGS (regno, mode) == 1 && GET_CODE (set) == SET)
+    {
+      rtx src = SET_SRC (set);
+
+      reg_mode[regno] = mode;
+      switch (GET_CODE (src))
+       {
+       case PLUS:
+         {
+           rtx src0 = XEXP (src, 0);
+           if (GET_CODE (src0) == REG)
+             {
+               if (REGNO (src0) != regno
+                   || reg_offset[regno] != const0_rtx)
+                 {
+                   reg_base_reg[regno] = REGNO (src0);
+                   reg_set_luid[regno] = move2add_luid;
+                 }
+               reg_offset[regno] = XEXP (src, 1);
+               break;
+             }
+           reg_set_luid[regno] = move2add_luid;
+           reg_offset[regno] = set;    /* Invalidate contents.  */
+           break;
+         }
+
+       case REG:
+         reg_base_reg[regno] = REGNO (SET_SRC (set));
+         reg_offset[regno] = const0_rtx;
+         reg_set_luid[regno] = move2add_luid;
+         break;
+
+       default:
+         reg_base_reg[regno] = -1;
+         reg_offset[regno] = SET_SRC (set);
+         reg_set_luid[regno] = move2add_luid;
+         break;
+       }
+    }
+  else
+    {
+      for (i = regno + HARD_REGNO_NREGS (regno, mode) - 1; i >= regno; i--)
+       {
+         /* Indicate that this register has been recently written to,
+            but the exact contents are not available.  */
+         reg_set_luid[i] = move2add_luid;
+         reg_offset[i] = dst;
+       }
+    }
+}