This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch to simplify reload register allocation


There are currently two reload register allocation mechanisms; one which is
used during the first pass(es) of reload, using calculate_needs and
find_reload_regs, and a second one (choose_reload_regs/allocate_reload_reg)
which is used during reload_as_needed.
These passes must work together, the first one must ensure that it makes
enough registers available for the second pass.  However, these passes
currently work in very different ways, and it is not at all obvious that
they will always agree on the number of reload regs needed.  Also, due to
historical reasons, the first pass is a lot more complex than it needs to
be: the calculate_needs code is left over from the time when we needed to
compute maximum needs across all insns.

The patch below tries to clean this up a little.  The first allocation pass
is simplified; it now uses reload_reg_class_lower just like the second pass
to compute a safe order for allocating registers to reloads, and then grabs
reload registers in that order; this is an algorithm similar to the one used
by the second pass.

This algorithm is not completely fail-safe, however.  Consider this scenario:
  * four registers: r0 .. r3
  * two classes: low_regs (r0 and r1) and all_regs (all four regs)
  * a group reload for class all_regs, and a single register reload for
    low_regs
Since reload_reg_class_lower puts the group reload in front of the other one,
we might end up grabbing r0 and r1 for the group, leaving nothing for the
single register reload.  I don't see any attempts to handle this case in the
current code, so I'm not sure this is an issue with any of the existing ports.
If it turns out to be a problem with this patch, it can probably be handled
relatively easily in find_reg.

With this patch, the information about which hard reg is allocated to which
reload is kept until reload_as_needed.  This is used in choose_reload_regs
in the no inheritance fallback case.  This way, it is guaranteed that the
second pass always finds a valid set of reload registers - it just uses the
one found during the first pass if necessary.  This makes the assumption that
find_reloads returns the same set of reloads during both passes explicit - it
will abort if the reloads appear different.

I'm not entirely sure what the force_group code in allocate_reload_regs is
supposed to do.  Probably it can now go away, since we can always provide a
safe allocation at this point.

The patch contains two more or less unrelated cleanup items: moving reload_mode
and reload_nregs into the reload structure and computing them only once, in
find_reloads; and getting rid of all the save_xxx nonsense in
choose_reload_regs.

This patch makes reload about 700 lines shorter, and it seems to run a bit
faster than before as well (calculate_needs showed up on some profiles pretty
well for some reason).  The generated code is nearly identical to the one
generated without the patch; in theory the cost calculation for multi-reg
spills is improved, but actual improvements are rare.  Occasionally, there are
also cases where code gets a little worse, but I haven't seen anything
dramatic in either direction.

Bootstrapped on i686-linux; random test cases compiled on i686-linux and
sh-elf to determine effect on code quality.

Long-term, I'd like to try and get rid of choose_reload_regs completely; if
we could do reload inheritance during the first pass we could just re-use the
existing reload register assignments during the second pass; this might even
avoid some spilling.

Bernd

	* reload.h (struct reload): New fields mode and nregs.
	(struct insn_chain): Delete fields group_size, group_mode,
	counted_for_groups, counted_for_nongroups, add fields rld and
	n_reloads.
	* reload.c (push_secondary_reload): Don't set nongroup field of
	new reloads.
	(push_reload): Likewise.
	(find_reloads): Delete code to compute nongroup fields.
	Add code to compute mode and nregs fields.
	* reload1.c (reload_insn_firstobj): New static variable.
	(calculate_needs, find_tworeg_group, find_group, possible_group_p,
	count_possible_groups, modes_equiv_for_class_p, new_spill_reg,
	dump_needs): Delete functions.
	(select_reload_regs, choose_reload_regs_init, failed_reload,
	set_reload_reg, copy_reloads, find_reg): New functions.
	(reload): Don't try to allocate reload registers if we already know
	we have to make another pass.  Call select_reload_regs.  Free memory
	starting with reload_firstobj when starting another pass.
	(calculate_needs_all_insns): Some cosmetic changes.
	Call copy_reloads for an insn that needs reloads; don't call
	calculate_needs.
	(spill_cost): New static array.
	(used_spill_regs_local): New static variable.
	(order_regs_for_reload): Compute spill_cost from hard_reg_n_uses.
	(maybe_mark_pseudo_spilled): Use used_spill_regs_local to determine
	which regs were spilled.
	(find_reload_regs): Completely rewritten to use find_reg.
	(allocate_reload_reg): Break out two functions, failed_reload and
	set_reload_reg.  Don't test counted_for_groups/counted_for_nongroups.
	(choose_reload_regs): Break out function choose_reload_regs_init and
	use it.  Don't compute reload_mode/reload_nregs here.
	Delete all code to save and restore state; call choose_reload_regs_init
	to undo the work of the first pass.
	Change inheritance for loop into if statement, add fallback code after
	it that uses the existing register allocation from find_reload_regs.

	(reload_mode, reload_nregs): Delete static arrays.
	(clear_reload_reg_in_use): Use struct reload's mode and nregs fields
	rather than these arrays.
	(allocate_reload_reg): Likewise.
	(choose_reload_regs): Likewise.
	(deallocate_reload_regs): Likewise.
	(emit_reload_insns): Likewise.

Index: reload.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/reload.h,v
retrieving revision 1.18
diff -u -p -r1.18 reload.h
--- reload.h	1999/09/12 14:54:55	1.18
+++ reload.h	1999/09/17 15:43:25
@@ -98,6 +98,10 @@ struct reload
   enum machine_mode inmode;
   /* The mode this operand should have when reloaded, on output.  */
   enum machine_mode outmode;
+  /* The mode for the reload register.  */
+  enum machine_mode mode;
+  /* Maximum number of hard regs this reload can occupy.  */
+  int nregs;
 
   /* Positive amount to increment or decrement by if
      reload_in is a PRE_DEC, PRE_INC, POST_DEC, POST_INC.
@@ -225,25 +229,9 @@ struct insn_chain 
   regset live_before;
   regset live_after;
 
-  /* For each class, size of group of consecutive regs
-     that is needed for the reloads of this class.  */
-  char group_size[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];
-
-  /* Indicates if a register was counted against the need for
-     groups.  0 means it can count against max_nongroup instead.  */
-  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.  */
-  HARD_REG_SET counted_for_nongroups;
+  /* Copies of the global variables computed by find_reloads.  */
+  struct reload *rld;
+  int n_reloads;
 
   /* Indicates which registers have already been used for spills.  */
   HARD_REG_SET used_spill_regs;
Index: reload.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/reload.c,v
retrieving revision 1.82
diff -u -p -r1.82 reload.c
--- reload.c	1999/09/12 14:54:55	1.82
+++ reload.c	1999/09/17 15:43:27
@@ -463,7 +463,6 @@ push_secondary_reload (in_p, x, opnum, o
 	  rld[t_reload].outmode = ! in_p ? t_mode : VOIDmode;
 	  rld[t_reload].reg_rtx = 0;
 	  rld[t_reload].optional = optional;
-	  rld[t_reload].nongroup = 0;
 	  rld[t_reload].inc = 0;
 	  /* Maybe we could combine these, but it seems too tricky.  */
 	  rld[t_reload].nocombine = 1;
@@ -533,7 +532,6 @@ push_secondary_reload (in_p, x, opnum, o
       rld[s_reload].outmode = ! in_p ? mode : VOIDmode;
       rld[s_reload].reg_rtx = 0;
       rld[s_reload].optional = optional;
-      rld[s_reload].nongroup = 0;
       rld[s_reload].inc = 0;
       /* Maybe we could combine these, but it seems too tricky.  */
       rld[s_reload].nocombine = 1;
@@ -1244,7 +1242,6 @@ push_reload (in, out, inloc, outloc, cla
       rld[i].outmode = outmode;
       rld[i].reg_rtx = 0;
       rld[i].optional = optional;
-      rld[i].nongroup = 0;
       rld[i].inc = 0;
       rld[i].nocombine = 0;
       rld[i].in_reg = inloc ? *inloc : 0;
@@ -4113,65 +4110,16 @@ find_reloads (insn, replace, ind_levels,
 	    rld[j].in = 0;
 	  }
 
-  /* Set which reloads must use registers not used in any group.  Start
-     with those that conflict with a group and then include ones that
-     conflict with ones that are already known to conflict with a group.  */
-
-  changed = 0;
+  /* Compute reload_mode and reload_nregs.  */
   for (i = 0; i < n_reloads; i++)
-    {
-      enum machine_mode mode = rld[i].inmode;
-      enum reg_class class = rld[i].class;
-      int size;
-
-      if (GET_MODE_SIZE (rld[i].outmode) > GET_MODE_SIZE (mode))
-	mode = rld[i].outmode;
-      size = CLASS_MAX_NREGS (class, mode);
-
-      if (size == 1)
-	for (j = 0; j < n_reloads; j++)
-	  if ((CLASS_MAX_NREGS (rld[j].class,
-				(GET_MODE_SIZE (rld[j].outmode)
-				 > GET_MODE_SIZE (rld[j].inmode))
-				? rld[j].outmode : rld[j].inmode)
-	       > 1)
-	      && !rld[j].optional
-	      && (rld[j].in != 0 || rld[j].out != 0
-		  || rld[j].secondary_p)
-	      && reloads_conflict (i, j)
-	      && reg_classes_intersect_p (class, rld[j].class))
-	    {
-	      rld[i].nongroup = 1;
-	      changed = 1;
-	      break;
-	    }
-    }
-
-  while (changed)
     {
-      changed = 0;
+      rld[i].mode
+	= (rld[i].inmode == VOIDmode
+	   || (GET_MODE_SIZE (rld[i].outmode)
+	       > GET_MODE_SIZE (rld[i].inmode)))
+	  ? rld[i].outmode : rld[i].inmode;
 
-      for (i = 0; i < n_reloads; i++)
-	{
-	  enum machine_mode mode = rld[i].inmode;
-	  enum reg_class class = rld[i].class;
-	  int size;
-
-	  if (GET_MODE_SIZE (rld[i].outmode) > GET_MODE_SIZE (mode))
-	    mode = rld[i].outmode;
-	  size = CLASS_MAX_NREGS (class, mode);
-
-	  if (! rld[i].nongroup && size == 1)
-	    for (j = 0; j < n_reloads; j++)
-	      if (rld[j].nongroup
-		  && reloads_conflict (i, j)
-		  && reg_classes_intersect_p (class, rld[j].class))
-		{
-		  rld[i].nongroup = 1;
-		  changed = 1;
-		  break;
-		}
-	}
+      rld[i].nregs = CLASS_MAX_NREGS (rld[i].class, rld[i].mode);
     }
 
 #else /* no REGISTER_CONSTRAINTS */
Index: reload1.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/reload1.c,v
retrieving revision 1.165
diff -u -p -r1.165 reload1.c
--- reload1.c	1999/09/16 09:55:48	1.165
+++ reload1.c	1999/09/17 15:43:30
@@ -274,9 +274,13 @@ struct obstack reload_obstack;
 char *reload_startobj;
 
 /* The point after all insn_chain structures.  Used to quickly deallocate
-   memory used while processing one insn.  */
+   memory allocated in copy_reloads during calculate_needs_all_insns.  */
 char *reload_firstobj;
 
+/* This points before all local rtl generated by register elimination.
+   Used to quickly free all memory after processing one insn.  */
+static char *reload_insn_firstobj;
+
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
@@ -371,24 +375,15 @@ struct hard_reg_n_uses
 };
 
 static void maybe_fix_stack_asms	PROTO((void));
+static void copy_reloads		PROTO((struct insn_chain *));
 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,
+static int find_reg			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 find_reload_regs		PROTO((struct insn_chain *, FILE *));
+static void select_reload_regs		PROTO((FILE *));
 static void delete_caller_save_insns	PROTO((void));
 
 static void spill_failure		PROTO((rtx));
-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));
@@ -417,10 +412,14 @@ static void mark_reload_reg_in_use	PROTO
 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_for_value_p	PROTO((int, int, enum reload_type, rtx, rtx, int, int));
+static int reload_reg_free_for_value_p	PROTO((int, int, enum reload_type,
+					       rtx, rtx, int, int));
 static int reload_reg_reaches_end_p	PROTO((int, int, enum reload_type));
 static int allocate_reload_reg		PROTO((struct insn_chain *, int, int,
 					       int));
+static void failed_reload		PROTO((rtx, int));
+static int set_reload_reg		PROTO((int, int));
+static void choose_reload_regs_init	PROTO((struct insn_chain *));
 static void choose_reload_regs		PROTO((struct insn_chain *));
 static void merge_assigned_reloads	PROTO((rtx));
 static void emit_reload_insns		PROTO((struct insn_chain *));
@@ -861,7 +860,6 @@ reload (first, global, dumpfile)
     {
       int something_changed;
       int did_spill;
-      struct insn_chain *chain;
 
       HOST_WIDE_INT starting_frame_size;
 
@@ -980,23 +978,25 @@ reload (first, global, dumpfile)
 	    }
       }
 
-      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);
-
-      if (failure)
-	goto failed;
+      /* No point in trying to select reload registers if we know we're
+	 going to re-run everything again.  */
+      if (! something_changed)
+	{
+	  select_reload_regs (dumpfile);
 
-      if (insns_need_reload != 0 || did_spill)
-	something_changed |= finish_spills (global, dumpfile);
+	  if (failure)
+	    goto failed;
 
+	  if (insns_need_reload != 0 || did_spill)
+	    something_changed |= finish_spills (global, dumpfile);
+	}
       if (! something_changed)
 	break;
 
       if (caller_save_needed)
 	delete_caller_save_insns ();
+
+      obstack_free (&reload_obstack, reload_firstobj);
     }
 
   /* If global-alloc was run, notify it of any register eliminations we have
@@ -1339,6 +1339,18 @@ maybe_fix_stack_asms ()
 }
 
 
+static void
+copy_reloads (chain)
+     struct insn_chain *chain;
+{
+  chain->n_reloads = n_reloads;
+  chain->rld
+    = (struct reload *) obstack_alloc (&reload_obstack,
+				       n_reloads * sizeof (struct reload));
+  memcpy (chain->rld, rld, n_reloads * sizeof (struct reload));
+  reload_insn_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+}
+
 /* 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.  */
@@ -1347,17 +1359,19 @@ calculate_needs_all_insns (global)
      int global;
 {
   struct insn_chain **pprev_reload = &insns_need_reload;
-  struct insn_chain **pchain;
+  struct insn_chain *chain;
 
   something_needs_elimination = 0;
 
-  for (pchain = &reload_insn_chain; *pchain != 0; pchain = &(*pchain)->next)
+  reload_insn_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+  for (chain = reload_insn_chain; chain != 0; chain = chain->next)
     {
-      rtx insn;
-      struct insn_chain *chain;
+      rtx insn = chain->insn;
 
-      chain = *pchain;
-      insn = chain->insn;
+      /* Clear out the shortcuts.  */
+      chain->need_elim = 0;
+      chain->need_reload = 0;
+      chain->need_operand_change = 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
@@ -1381,14 +1395,7 @@ calculate_needs_all_insns (global)
 	  if (set && GET_CODE (SET_DEST (set)) == REG
 	      && reg_renumber[REGNO (SET_DEST (set))] < 0
 	      && reg_equiv_constant[REGNO (SET_DEST (set))])
-	    {
-	      /* Must clear out the shortcuts, in case they were set last
-		 time through.  */
-	      chain->need_elim = 0;
-	      chain->need_reload = 0;
-	      chain->need_operand_change = 0;
-	      continue;
-	    }
+	    continue;
 
 	  /* If needed, eliminate any eliminable registers.  */
 	  if (num_eliminable || num_eliminable_invariants)
@@ -1431,7 +1438,7 @@ calculate_needs_all_insns (global)
 	  /* Discard any register replacements done.  */
 	  if (did_elimination)
 	    {
-	      obstack_free (&reload_obstack, reload_firstobj);
+	      obstack_free (&reload_obstack, reload_insn_firstobj);
 	      PATTERN (insn) = old_body;
 	      INSN_CODE (insn) = old_code;
 	      REG_NOTES (insn) = old_notes;
@@ -1442,400 +1449,204 @@ calculate_needs_all_insns (global)
 
 	  if (n_reloads != 0)
 	    {
+	      copy_reloads (chain);
 	      *pprev_reload = chain;
 	      pprev_reload = &chain->next_need_reload;
-
-	      calculate_needs (chain);
 	    }
 	}
     }
   *pprev_reload = 0;
 }
-
-/* Compute the most additional registers needed by one instruction,
-   given by CHAIN.  Collect information separately for each class of regs.
-
-   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.  */
+
+/* Comparison function for qsort to decide which of two reloads
+   should be handled first.  *P1 and *P2 are the reload numbers.  */
 
-static void
-calculate_needs (chain)
-     struct insn_chain *chain;
+static int
+reload_reg_class_lower (r1p, r2p)
+     const PTR r1p;
+     const PTR r2p;
 {
-  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 = rld[i].class;
-      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 (rld[i].reg_rtx != 0
-	  || rld[i].optional != 0
-	  || (rld[i].out == 0 && rld[i].in == 0
-	      && ! rld[i].secondary_p))
-	continue;
-
-      mode = rld[i].inmode;
-      if (GET_MODE_SIZE (rld[i].outmode) > GET_MODE_SIZE (mode))
-	mode = rld[i].outmode;
-      size = CLASS_MAX_NREGS (class, mode);
-
-      /* Decide which time-of-use to count this reload for.  */
-      switch (rld[i].when_needed)
-	{
-	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[rld[i].opnum];
-	  break;
-	case RELOAD_FOR_INPADDR_ADDRESS:
-	  this_needs = &insn_needs.in_addr_addr[rld[i].opnum];
-	  break;
-	case RELOAD_FOR_OUTPUT_ADDRESS:
-	  this_needs = &insn_needs.out_addr[rld[i].opnum];
-	  break;
-	case RELOAD_FOR_OUTADDR_ADDRESS:
-	  this_needs = &insn_needs.out_addr_addr[rld[i].opnum];
-	  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;
-	default:
-	  abort();
-	}
-
-      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++]++;
+  register int r1 = *(short *)r1p, r2 = *(short *)r2p;
+  register int t;
 
-	  /* 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;
+  /* Consider required reloads before optional ones.  */
+  t = rld[r1].optional - rld[r2].optional;
+  if (t != 0)
+    return t;
 
-	      chain->group_size[(int) class] = size;
-	      chain->group_mode[(int) class] = mode;
-	    }
-	  else
-	    {
-	      other_mode = mode;
-	      allocate_mode = chain->group_mode[(int) class];
-	    }
+  /* Count all solitary classes before non-solitary ones.  */
+  t = ((reg_class_size[(int) rld[r2].class] == 1)
+       - (reg_class_size[(int) rld[r1].class] == 1));
+  if (t != 0)
+    return t;
 
-	  /* Crash if two dissimilar machine modes both need
-	     groups of consecutive regs of the same class.  */
+  /* Aside from solitaires, consider all multi-reg groups first.  */
+  t = rld[r2].nregs - rld[r1].nregs;
+  if (t != 0)
+    return t;
 
-	  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)
-	{
-	  this_needs->regs[(unsigned char)rld[i].nongroup][(int) class] += 1;
-	  p = reg_class_superclasses[(int) class];
-	  while (*p != LIM_REG_CLASSES)
-	    this_needs->regs[(unsigned char)rld[i].nongroup][(int) *p++] += 1;
-	}
-      else
-	abort ();
-    }
+  /* Consider reloads in order of increasing reg-class number.  */
+  t = (int) rld[r1].class - (int) rld[r2].class;
+  if (t != 0)
+    return t;
 
-  /* 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.  */
+  /* If reloads are equally urgent, sort by reload number,
+     so that the results of qsort leave nothing to chance.  */
+  return r1 - r2;
+}
+
+/* The cost of spilling each hard reg.  */
+static int spill_cost[FIRST_PSEUDO_REGISTER];
 
-  for (i = 0; i < N_REG_CLASSES; i++)
-    {
-      int j, in_max, out_max;
+static int
+hard_reg_use_compare (p1p, p2p)
+     const PTR p1p;
+     const 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;
+}
 
-      /* Compute normal and nongroup needs.  */
-      for (j = 0; j <= 1; j++)
-	{
-	  int k;
-	  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]);
-	    }
+/* Used for communication between order_regs_for_reload and count_pseudo.
+   Used to avoid counting one pseudo twice.  */
+static regset pseudos_counted;
 
-	  /* 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.  */
+/* 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;
 
-	  in_max = MAX (MAX (insn_needs.op_addr.regs[j][i],
-			     insn_needs.op_addr_reload.regs[j][i]),
-			in_max);
+  if (REGNO_REG_SET_P (pseudos_counted, reg))
+    return;
+  SET_REGNO_REG_SET (pseudos_counted, reg);
 
-	  out_max = MAX (out_max, insn_needs.insn.regs[j][i]);
+  if (r < 0)
+    abort ();
 
-	  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]);
+  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.  */
 
-	  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]);
+static void
+order_regs_for_reload (chain)
+     struct insn_chain *chain;
+{
+  register int i, j;
+  register int o = 0;
+  struct hard_reg_n_uses hard_reg_n_uses[FIRST_PSEUDO_REGISTER];
 
-	}
+  pseudos_counted = ALLOCA_REG_SET ();
 
-      /* 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]);
-	}
+  COPY_HARD_REG_SET (bad_spill_regs, bad_spill_regs_global);
 
-      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]);
+  /* Count number of uses of each hard reg by pseudo regs allocated to it
+     and then order them by decreasing use.  */
 
-      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]);
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      hard_reg_n_uses[i].regno = i;
+      hard_reg_n_uses[i].uses = 0;
 
-      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]);
+      /* 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))
+	SET_HARD_REG_BIT (bad_spill_regs, i);
     }
+  /* Now find out which pseudos are allocated to it, and update
+     hard_reg_n_uses.  */
+  CLEAR_REG_SET (pseudos_counted);
 
-  /* Record the needs for later.  */
-  chain->need = insn_needs.other;
-}
-
-/* Find a group of exactly 2 registers.
+  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);
+     });
 
-   First try to fill out the group by spilling a single register which
-   would allow completion of the group.
+  FREE_REG_SET (pseudos_counted);
 
-   Then try to create a new group from a pair of registers, neither of
-   which are explicitly used.
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    spill_cost[i] = hard_reg_n_uses[i].uses;
 
-   Then try to create a group from any pair of registers.  */
+  /* Prefer registers not so far used, for use in temporary loading.
+     Among them, if REG_ALLOC_ORDER is defined, use that order.
+     Otherwise, prefer registers not preserved by calls.  */
 
-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.  */
+#ifdef REG_ALLOC_ORDER
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
-      int j, other;
+      int regno = reg_alloc_order[i];
 
-      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.  */
-	  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++;
-	    }
-
-	  /* 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;
-	}
+      if (hard_reg_n_uses[regno].uses == 0
+	  && ! TEST_HARD_REG_BIT (bad_spill_regs, regno))
+	potential_reload_regs[o++] = regno;
     }
-  /* 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;
-      }
-
-  /* I should be the index in potential_reload_regs
-     of the new reload reg we have found.  */
-
-  new_spill_reg (chain, i, class, 0, dumpfile);
-}
-
-/* Find a group of more than 2 registers.
-   Look for a sufficient sequence of unspilled registers, and spill them all
-   at once.  */
-
-static void
-find_group (chain, class, dumpfile)
-     struct insn_chain *chain;
-     int class;
-     FILE *dumpfile;
-{
-  int i;
-
+#else
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
-      int j = potential_reload_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]
+	  && ! TEST_HARD_REG_BIT (bad_spill_regs, i))
+	potential_reload_regs[o++] = i;
+    }
+#endif
 
-      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);
-		}
+  qsort (hard_reg_n_uses, FIRST_PSEUDO_REGISTER,
+	 sizeof hard_reg_n_uses[0], hard_reg_use_compare);
 
-	      /* 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++;
-		}
-	      return;
-	    }
-	}
-    }
-  /* There are no groups left.  */
-  spill_failure (chain->insn);
-  failure = 1;
+  /* Now add the regs that are already used,
+     preferring those used less often.  The fixed and otherwise forbidden
+     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
+	&& ! 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;
 }
+
+/* Vector of reload-numbers showing the order in which the reloads should
+   be processed.  */
+static short reload_order[MAX_RELOADS];
+
+/* This is used to keep track of the spill regs used in one insn.  */
+static HARD_REG_SET used_spill_regs_local;
 
 /* If pseudo REG conflicts with one of our reload registers, mark it as
    spilled.  */
@@ -1850,159 +1661,146 @@ maybe_mark_pseudo_spilled (reg)
   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])
+  for (i = 0; i < nregs; i++)
+    if (TEST_HARD_REG_BIT (used_spill_regs_local, r + i))
       {
 	SET_REGNO_REG_SET (spilled_pseudos, reg);
 	return;
       }
 }
 
+/* Find reload register to use for reload number ORDER.  */
+
+static int
+find_reg (chain, order, dumpfile)
+     struct insn_chain *chain;
+     int order;
+     FILE *dumpfile;
+{
+  int rnum = reload_order[order];
+  struct reload *rl = rld + rnum;
+  int best_cost = INT_MAX;
+  int best_reg = -1;
+  int i, j;
+  HARD_REG_SET not_usable;
+  HARD_REG_SET used_by_other_reload;
+
+  COPY_HARD_REG_SET (not_usable, bad_spill_regs);
+  IOR_HARD_REG_SET (not_usable, bad_spill_regs_global);
+  IOR_COMPL_HARD_REG_SET (not_usable, reg_class_contents[rl->class]);
+
+  CLEAR_HARD_REG_SET (used_by_other_reload);
+  for (i = 0; i < order; i++)
+    {
+      int other = reload_order[i];
+      if (rld[other].regno >= 0 && reloads_conflict (other, rnum))
+	for (j = 0; j < rld[other].nregs; j++)
+	  SET_HARD_REG_BIT (used_by_other_reload, rld[other].regno + j);
+    }
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      int regno = potential_reload_regs[i];
+      if (! TEST_HARD_REG_BIT (not_usable, regno)
+	  && ! TEST_HARD_REG_BIT (used_by_other_reload, regno)
+	  && HARD_REGNO_MODE_OK (regno, rl->mode))
+	{
+	  int this_cost = 0;
+	  int ok = 1;
+	  int this_nregs = HARD_REGNO_NREGS (regno, rl->mode);
+
+	  for (j = 0; j < this_nregs; j++)
+	    {
+	      this_cost += spill_cost[regno + j];
+	      if ((TEST_HARD_REG_BIT (not_usable, regno + j))
+		  || TEST_HARD_REG_BIT (used_by_other_reload, regno + j))
+		ok = 0;
+	    }
+	  if (rl->in && GET_CODE (rl->in) == REG && REGNO (rl->in) == regno)
+	    this_cost--;
+	  if (rl->out && GET_CODE (rl->out) == REG && REGNO (rl->out) == regno)
+	    this_cost--;
+	  if (ok && this_cost < best_cost)
+	    {
+	      best_reg = regno;
+	      best_cost = this_cost;
+	    }
+	}
+    }
+  if (best_reg == -1)
+    return 0;
+  if (dumpfile)
+    fprintf (dumpfile, "Using reg %d for reload %d\n", best_reg, rnum);
+  rl->nregs = HARD_REGNO_NREGS (best_reg, rl->mode);
+  rl->regno = best_reg;
+  for (i = 0; i < rl->nregs; i++)
+    {
+      spill_cost[best_reg + i] = 0;
+      SET_HARD_REG_BIT (used_spill_regs_local, best_reg + i);
+    }
+  return 1;
+}
+
 /* 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.
-
-   Count spilled regs in `spills', and add entries to
-   `spill_regs' and `spill_reg_order'.
+   for a smaller class even though it belongs to that class.  */
 
-   ??? 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.
-
-   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.
-
-   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.  */
-
 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 (dumpfile)
-    fprintf (dumpfile, "Spilling for insn %d.\n", INSN_UID (chain->insn));
-
-  /* Compute the order of preference for hard registers to spill.
-     Store them by decreasing preference in potential_reload_regs.  */
-
-  order_regs_for_reload (chain);
-
-  /* So far, no hard regs have been spilled.  */
-  n_spills = 0;
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    spill_reg_order[i] = -1;
+  int i;
 
-  CLEAR_HARD_REG_SET (chain->used_spill_regs);
-  CLEAR_HARD_REG_SET (chain->counted_for_groups);
-  CLEAR_HARD_REG_SET (chain->counted_for_nongroups);
+  /* 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
+     that provided the reload registers.  */
 
-  for (class = 0; class < N_REG_CLASSES; class++)
+  for (i = 0; i < chain->n_reloads; i++)
     {
-      /* First get the groups of registers.
-	 If we got single registers first, we might fragment
-	 possible groups.  */
-      while (group_needs[class] > 0)
+      /* Show whether this reload already has a hard reg.  */
+      if (chain->rld[i].reg_rtx)
 	{
-	  /* 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;
+	  int regno = REGNO (chain->rld[i].reg_rtx);
+	  chain->rld[i].regno = regno;
+	  chain->rld[i].nregs = HARD_REGNO_NREGS (regno, GET_MODE (chain->rld[i].reg_rtx));
 	}
+      else
+	chain->rld[i].regno = -1;
+      reload_order[i] = i;
+    }
 
-      /* Now similarly satisfy all need for single registers.  */
+  n_reloads = chain->n_reloads;
+  memcpy (rld, chain->rld, n_reloads * sizeof (struct reload));
 
-      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;
+  CLEAR_HARD_REG_SET (used_spill_regs_local);
 
-		    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 (dumpfile)
+    fprintf (dumpfile, "Spilling for insn %d.\n", INSN_UID (chain->insn));
 
-	  if (simple_needs[class] <= 0 && nongroup_needs[class] <= 0)
-	    break;
+  qsort (reload_order, n_reloads, sizeof (short), reload_reg_class_lower);
 
-	  /* 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++)
-	    {
-	      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;
-	    }
+  /* Compute the order of preference for hard registers to spill.  */
 
-	  /* 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;
+  order_regs_for_reload (chain);
 
-	  /* I should be the index in potential_reload_regs
-	     of the new reload reg we have found.  */
+  for (i = 0; i < n_reloads; i++)
+    {
+      int r = reload_order[i];
 
-	  new_spill_reg (chain, i, class, 1, dumpfile);
-	  if (failure)
+      /* Ignore reloads that got marked inoperative.  */
+      if ((rld[r].out != 0 || rld[r].in != 0 || rld[r].secondary_p)
+	  && ! rld[r].optional
+	  && rld[r].regno == -1)
+	if (! find_reg (chain, i, dumpfile))
+	  {
+	    spill_failure (chain->insn);
+	    failure = 1;
 	    return;
-	}
+	  }
     }
 
   /* We know which hard regs to use, now mark the pseudos that live in them
@@ -2017,38 +1815,22 @@ find_reload_regs (chain, dumpfile)
      {
        maybe_mark_pseudo_spilled (i);
      });
+  COPY_HARD_REG_SET (chain->used_spill_regs, used_spill_regs_local);
+  IOR_HARD_REG_SET (used_spill_regs, used_spill_regs_local);
 
-  IOR_HARD_REG_SET (used_spill_regs, chain->used_spill_regs);
+  memcpy (chain->rld, rld, n_reloads * sizeof (struct reload));
 }
 
-void
-dump_needs (chain, dumpfile)
-     struct insn_chain *chain;
+static void
+select_reload_regs (dumpfile)
      FILE *dumpfile;
 {
-  static const char * const reg_class_names[] = REG_CLASS_NAMES;
-  int i;
-  struct needs *n = &chain->need;
+  struct insn_chain *chain;
 
-  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",
-		 GET_MODE_NAME(chain->group_mode[i]),
-		 reg_class_names[i]);
-    }
+  /* 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);
 }
 
 /* Delete all insns that were inserted by emit_caller_save_insns during
@@ -2090,162 +1872,6 @@ delete_caller_save_insns ()
     }
 }
 
-/* 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 (chain, regno)
-     struct insn_chain *chain;
-     int regno;
-{
-  int i;
-  int class = (int) NO_REGS;
-
-  for (i = 0; i < (int) N_REG_CLASSES; i++)
-    if (chain->need.groups[i] > 0)
-      {
-	class = i;
-	break;
-      }
-
-  if (class == (int) NO_REGS)
-    return 1;
-
-  /* Consider each pair of consecutive registers.  */
-  for (i = 0; i < FIRST_PSEUDO_REGISTER - 1; i++)
-    {
-      /* Ignore pairs that include reg REGNO.  */
-      if (i == regno || i + 1 == regno)
-	continue;
-
-      /* Ignore pairs that are outside the class that needs the group.
-	 ??? Here we fail to handle the case where two different classes
-	 independently need groups.  But this never happens with our
-	 current machine descriptions.  */
-      if (! (TEST_HARD_REG_BIT (reg_class_contents[class], i)
-	     && TEST_HARD_REG_BIT (reg_class_contents[class], i + 1)))
-	continue;
-
-      /* A pair of consecutive regs we can still spill does the trick.  */
-      if (spill_reg_order[i] < 0 && spill_reg_order[i + 1] < 0
-	  && ! TEST_HARD_REG_BIT (bad_spill_regs, i)
-	  && ! TEST_HARD_REG_BIT (bad_spill_regs, i + 1))
-	return 1;
-
-      /* A pair of one already spilled and one we can spill does it
-	 provided the one already spilled is not otherwise reserved.  */
-      if (spill_reg_order[i] < 0
-	  && ! TEST_HARD_REG_BIT (bad_spill_regs, i)
-	  && spill_reg_order[i + 1] >= 0
-	  && ! 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 (chain->counted_for_groups, i)
-	  && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, i))
-	return 1;
-    }
-
-  return 0;
-}
-
-/* Count any groups of CLASS that can be formed from the registers recently
-   spilled.  */
-
-static void
-count_possible_groups (chain, class)
-     struct insn_chain *chain;
-     int class;
-{
-  HARD_REG_SET new;
-  int i, j;
-
-  /* Now find all consecutive groups of spilled registers
-     and mark each group off against the need for such groups.
-     But don't count them against ordinary need, yet.  */
-
-  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++)
-    {
-      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 && chain->need.groups[class] > 0; i++)
-    if (TEST_HARD_REG_BIT (new, i)
-	&& i + chain->group_size[class] <= FIRST_PSEUDO_REGISTER
-	&& HARD_REGNO_MODE_OK (i, chain->group_mode[class]))
-      {
-	for (j = 1; j < chain->group_size[class]; j++)
-	  if (! TEST_HARD_REG_BIT (new, i + j))
-	    break;
-
-	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;
-
-	    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++;
-	      }
-
-	    /* Don't count these registers again.  */
-	    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,
-	   it will then point to the first reg of the next possible group.  */
-	i += j - 1;
-      }
-}
-
-/* ALLOCATE_MODE is a register mode that needs to be reloaded.  OTHER_MODE is
-   another mode that needs to be reloaded for the same register class CLASS.
-   If any reg in CLASS allows ALLOCATE_MODE but not OTHER_MODE, fail.
-   ALLOCATE_MODE will never be smaller than OTHER_MODE.
-
-   This code used to also fail if any reg in CLASS allows OTHER_MODE but not
-   ALLOCATE_MODE.  This test is unnecessary, because we will never try to put
-   something of mode ALLOCATE_MODE into an OTHER_MODE register.  Testing this
-   causes unnecessary failures on machines requiring alignment of register
-   groups when the two modes are different sizes, because the larger mode has
-   more strict alignment rules than the smaller mode.  */
-
-static int
-modes_equiv_for_class_p (allocate_mode, other_mode, class)
-     enum machine_mode allocate_mode, other_mode;
-     enum reg_class class;
-{
-  register int regno;
-  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-    {
-      if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno)
-	  && HARD_REGNO_MODE_OK (regno, allocate_mode)
-	  && ! HARD_REGNO_MODE_OK (regno, other_mode))
-	return 0;
-    }
-  return 1;
-}
-
 /* Handle the failure to find a register to spill.
    INSN should be one of the insns which needed this particular spill reg.  */
 
@@ -2258,83 +1884,6 @@ spill_failure (insn)
   else
     fatal_insn ("Unable to find a register to spill.", insn);
 }
-
-/* 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.
-   NONGROUP is 0 if this register is part of a group.
-   DUMPFILE is the same as the one that `reload' got.  */
-
-static void
-new_spill_reg (chain, i, class, nongroup, dumpfile)
-     struct insn_chain *chain;
-     int i;
-     int class;
-     int nongroup;
-     FILE *dumpfile;
-{
-  register enum reg_class *p;
-  int regno = potential_reload_regs[i];
-
-  if (i >= FIRST_PSEUDO_REGISTER)
-    {
-      spill_failure (chain->insn);
-      failure = 1;
-      return;
-    }
-
-  if (TEST_HARD_REG_BIT (bad_spill_regs, regno))
-    {
-      static const char * const reg_class_names[] = REG_CLASS_NAMES;
-
-      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.  */
-
-  potential_reload_regs[i] = -1;
-  spill_regs[n_spills] = regno;
-  spill_reg_order[regno] = n_spills;
-  if (dumpfile)
-    fprintf (dumpfile, "Spilling reg %d.\n", regno);
-  SET_HARD_REG_BIT (chain->used_spill_regs, regno);
-
-  /* Clear off the needs we just satisfied.  */
-
-  chain->need.regs[0][class]--;
-  p = reg_class_superclasses[class];
-  while (*p != LIM_REG_CLASSES)
-    chain->need.regs[0][(int) *p++]--;
-
-  if (nongroup && chain->need.regs[1][class] > 0)
-    {
-      SET_HARD_REG_BIT (chain->counted_for_nongroups, regno);
-      chain->need.regs[1][class]--;
-      p = reg_class_superclasses[class];
-      while (*p != LIM_REG_CLASSES)
-	chain->need.regs[1][(int) *p++]--;
-    }
-
-  n_spills++;
-}
 
 /* Delete an unneeded INSN and any previous insns who sole purpose is loading
    data that is dead in INSN.  */
@@ -4040,149 +3589,9 @@ scan_paradoxical_subregs (x)
 	{
 	  register int j;
 	  for (j = XVECLEN (x, i) - 1; j >=0; j--)
-	    scan_paradoxical_subregs (XVECEXP (x, i, j));
-	}
-    }
-}
-
-static int
-hard_reg_use_compare (p1p, p2p)
-     const PTR p1p;
-     const 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 (chain)
-     struct insn_chain *chain;
-{
-  register int i;
-  register int o = 0;
-  struct hard_reg_n_uses hard_reg_n_uses[FIRST_PSEUDO_REGISTER];
-
-  pseudos_counted = ALLOCA_REG_SET ();
-
-  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].regno = i;
-      hard_reg_n_uses[i].uses = 0;
-
-      /* 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))
-	SET_HARD_REG_BIT (bad_spill_regs, i);
-    }
-
-  /* Now compute hard_reg_n_uses.  */
-  CLEAR_REG_SET (pseudos_counted);
-
-  EXECUTE_IF_SET_IN_REG_SET
-    (chain->live_before, FIRST_PSEUDO_REGISTER, i,
-     {
-       count_pseudo (hard_reg_n_uses, i);
-     });
-  EXECUTE_IF_SET_IN_REG_SET
-    (chain->live_after, FIRST_PSEUDO_REGISTER, i,
-     {
-       count_pseudo (hard_reg_n_uses, i);
-     });
-
-  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.
-     Otherwise, prefer registers not preserved by calls.  */
-
-#ifdef REG_ALLOC_ORDER
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    {
-      int regno = reg_alloc_order[i];
-
-      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]
-	  && ! 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]
-	  && ! TEST_HARD_REG_BIT (bad_spill_regs, i))
-	potential_reload_regs[o++] = i;
-    }
-#endif
-
-  qsort (hard_reg_n_uses, FIRST_PSEUDO_REGISTER,
-	 sizeof hard_reg_n_uses[0], hard_reg_use_compare);
-
-  /* Now add the regs that are already used,
-     preferring those used less often.  The fixed and otherwise forbidden
-     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
-	&& ! 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;
+	    scan_paradoxical_subregs (XVECEXP (x, i, j));
+	}
+    }
 }
 
 /* Reload pseudo-registers into hard regs around each insn as needed.
@@ -4532,49 +3941,6 @@ forget_old_reloads_1 (x, ignored)
       reg_last_reload_reg[regno + nr] = 0;
 }
 
-/* For each reload, the mode of the reload register.  */
-static enum machine_mode reload_mode[MAX_RELOADS];
-
-/* For each reload, the largest number of registers it will require.  */
-static int reload_nregs[MAX_RELOADS];
-
-/* Comparison function for qsort to decide which of two reloads
-   should be handled first.  *P1 and *P2 are the reload numbers.  */
-
-static int
-reload_reg_class_lower (r1p, r2p)
-     const PTR r1p;
-     const PTR r2p;
-{
-  register int r1 = *(short *)r1p, r2 = *(short *)r2p;
-  register int t;
-
-  /* Consider required reloads before optional ones.  */
-  t = rld[r1].optional - rld[r2].optional;
-  if (t != 0)
-    return t;
-
-  /* Count all solitary classes before non-solitary ones.  */
-  t = ((reg_class_size[(int) rld[r2].class] == 1)
-       - (reg_class_size[(int) rld[r1].class] == 1));
-  if (t != 0)
-    return t;
-
-  /* Aside from solitaires, consider all multi-reg groups first.  */
-  t = reload_nregs[r2] - reload_nregs[r1];
-  if (t != 0)
-    return t;
-
-  /* Consider reloads in order of increasing reg-class number.  */
-  t = (int) rld[r1].class - (int) rld[r2].class;
-  if (t != 0)
-    return t;
-
-  /* If reloads are equally urgent, sort by reload number,
-     so that the results of qsort leave nothing to chance.  */
-  return r1 - r2;
-}
-
 /* The following HARD_REG_SETs indicate when each hard register is
    used for a reload of various parts of the current insn.  */
 
@@ -4772,7 +4138,7 @@ clear_reload_reg_in_use (regno, opnum, t
 	      int conflict_start = true_regnum (rld[i].reg_rtx);
 	      int conflict_end
 		= (conflict_start
-		   + HARD_REGNO_NREGS (conflict_start, reload_mode[i]));
+		   + HARD_REGNO_NREGS (conflict_start, rld[i].mode));
 
 	      /* If there is an overlap with the first to-be-freed register,
 		 adjust the interval start.  */
@@ -5152,10 +4518,6 @@ reloads_conflict (r1, r2)
     }
 }
 
-/* Vector of reload-numbers showing the order in which the reloads should
-   be processed.  */
-short reload_order[MAX_RELOADS];
-
 /* Indexed by reload number, 1 if incoming value
    inherited from previous insns.  */
 char reload_inherited[MAX_RELOADS];
@@ -5386,6 +4748,71 @@ reload_reg_free_for_value_p (regno, opnu
   return 1;
 }
 
+static void
+failed_reload (insn, r)
+     rtx insn;
+     int r;
+{
+  if (asm_noperands (PATTERN (insn)) < 0)
+    /* It's the compiler's fault.  */
+    fatal_insn ("Could not find a spill register", insn);
+
+  /* It's the user's fault; the operand's mode and constraint
+     don't match.  Disable this reload so we don't crash in final.  */
+  error_for_asm (insn,
+		 "`asm' operand constraint incompatible with operand size");
+  rld[r].in = 0;
+  rld[r].out = 0;
+  rld[r].reg_rtx = 0;
+  rld[r].optional = 1;
+  rld[r].secondary_p = 1;
+}
+
+static int
+set_reload_reg (i, r)
+     int i, r;
+{
+  int regno;
+  rtx reg = spill_reg_rtx[i];
+
+  if (reg == 0 || GET_MODE (reg) != rld[r].mode)
+    spill_reg_rtx[i] = reg = gen_rtx_REG (rld[r].mode, spill_regs[i]);
+
+  regno = true_regnum (reg);
+
+  /* Detect when the reload reg can't hold the reload mode.
+     This used to be one `if', but Sequent compiler can't handle that.  */
+  if (HARD_REGNO_MODE_OK (regno, rld[r].mode))
+    {
+      enum machine_mode test_mode = VOIDmode;
+      if (rld[r].in)
+	test_mode = GET_MODE (rld[r].in);
+      /* If rld[r].in has VOIDmode, it means we will load it
+	 in whatever mode the reload reg has: to wit, rld[r].mode.
+	 We have already tested that for validity.  */
+      /* Aside from that, we need to test that the expressions
+	 to reload from or into have modes which are valid for this
+	 reload register.  Otherwise the reload insns would be invalid.  */
+      if (! (rld[r].in != 0 && test_mode != VOIDmode
+	     && ! HARD_REGNO_MODE_OK (regno, test_mode)))
+	if (! (rld[r].out != 0
+	       && ! HARD_REGNO_MODE_OK (regno, GET_MODE (rld[r].out))))
+	  {
+	    /* The reg is OK.  */
+	    last_spill_reg = i;
+
+	    /* Mark as in use for this insn the reload regs we use
+	       for this.  */
+	    mark_reload_reg_in_use (spill_regs[i], rld[r].opnum,
+				    rld[r].when_needed, rld[r].mode);
+
+	    rld[r].reg_rtx = reg;
+	    reload_spill_index[r] = spill_regs[i];
+	    return 1;
+	  }
+    }
+  return 0;
+}
 /* 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.
@@ -5404,7 +4831,6 @@ allocate_reload_reg (chain, r, last_relo
 {
   rtx insn = chain->insn;
   int i, pass, count, regno;
-  rtx new;
 
   /* If we put this reload ahead, thinking it is a group,
      then insist on finding a group.  Otherwise we can grab a
@@ -5419,7 +4845,7 @@ allocate_reload_reg (chain, r, last_relo
      Perhaps those classes should be avoided for reloading
      by use of more alternatives.  */
 
-  int force_group = reload_nregs[r] > 1 && ! last_reload;
+  int force_group = rld[r].nregs > 1 && ! last_reload;
 
   /* If we want a single register and haven't yet found one,
      take any reg in the right class and not in use.
@@ -5472,7 +4898,7 @@ allocate_reload_reg (chain, r, last_relo
 						   rld[r].in,
 						   rld[r].out, r, 1)))
 	      && TEST_HARD_REG_BIT (reg_class_contents[class], regnum)
-	      && HARD_REGNO_MODE_OK (regnum, reload_mode[r])
+	      && HARD_REGNO_MODE_OK (regnum, rld[r].mode)
 	      /* 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.  */
@@ -5482,12 +4908,12 @@ allocate_reload_reg (chain, r, last_relo
 		      && ! TEST_HARD_REG_BIT (reload_reg_used_for_inherit,
 					      regnum))))
 	    {
-	      int nr = HARD_REGNO_NREGS (regnum, reload_mode[r]);
+	      int nr = HARD_REGNO_NREGS (regnum, rld[r].mode);
 	      /* 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.  */
 	      if (force_group)
-		nr = CLASS_MAX_NREGS (rld[r].class, reload_mode[r]);
+		nr = CLASS_MAX_NREGS (rld[r].class, rld[r].mode);
 	      /* If we need only one reg, we have already won.  */
 	      if (nr == 1)
 		{
@@ -5497,22 +4923,17 @@ allocate_reload_reg (chain, r, last_relo
 		  break;
 		}
 	      /* Otherwise check that as many consecutive regs as we need
-		 are available here.
-		 Also, don't use for a group registers that are
-		 needed for nongroups.  */
-	      if (! TEST_HARD_REG_BIT (chain->counted_for_nongroups, regnum))
-		while (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, rld[r].opnum,
-						rld[r].when_needed)
-			  && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups,
-						  regno)))
-		      break;
-		    nr--;
-		  }
+		 are available here.  */
+	      while (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, rld[r].opnum,
+					      rld[r].when_needed)))
+		    break;
+		  nr--;
+		}
 	      if (nr == 1)
 		break;
 	    }
@@ -5524,113 +4945,28 @@ allocate_reload_reg (chain, r, last_relo
     }
 
   /* We should have found a spill register by now.  */
-  if (count == n_spills)
-    {
-      if (noerror)
-	return 0;
-      goto failure;
-    }
-
-  /* I is the index in SPILL_REG_RTX of the reload register we are to
-     allocate.  Get an rtx for it and find its register number.  */
-
-  new = spill_reg_rtx[i];
-
-  if (new == 0 || GET_MODE (new) != reload_mode[r])
-    spill_reg_rtx[i] = new
-      = gen_rtx_REG (reload_mode[r], spill_regs[i]);
-
-  regno = true_regnum (new);
-
-  /* Detect when the reload reg can't hold the reload mode.
-     This used to be one `if', but Sequent compiler can't handle that.  */
-  if (HARD_REGNO_MODE_OK (regno, reload_mode[r]))
+  if (count < n_spills)
     {
-      enum machine_mode test_mode = VOIDmode;
-      if (rld[r].in)
-	test_mode = GET_MODE (rld[r].in);
-      /* If rld[r].in has VOIDmode, it means we will load it
-	 in whatever mode the reload reg has: to wit, reload_mode[r].
-	 We have already tested that for validity.  */
-      /* Aside from that, we need to test that the expressions
-	 to reload from or into have modes which are valid for this
-	 reload register.  Otherwise the reload insns would be invalid.  */
-      if (! (rld[r].in != 0 && test_mode != VOIDmode
-	     && ! HARD_REGNO_MODE_OK (regno, test_mode)))
-	if (! (rld[r].out != 0
-	       && ! HARD_REGNO_MODE_OK (regno, GET_MODE (rld[r].out))))
-	  {
-	    /* The reg is OK.  */
-	    last_spill_reg = i;
-
-	    /* Mark as in use for this insn the reload regs we use
-	       for this.  */
-	    mark_reload_reg_in_use (spill_regs[i], rld[r].opnum,
-				    rld[r].when_needed, reload_mode[r]);
+      /* I is the index in SPILL_REG_RTX of the reload register we are to
+	 allocate.  Get an rtx for it and find its register number.  */
 
-	    rld[r].reg_rtx = new;
-	    reload_spill_index[r] = spill_regs[i];
-	    return 1;
-	  }
+      if (set_reload_reg (i, r))
+	return 1;
     }
 
-  /* The reg is not OK.  */
   if (noerror)
     return 0;
-
- failure:
-  if (asm_noperands (PATTERN (insn)) < 0)
-    /* It's the compiler's fault.  */
-    fatal_insn ("Could not find a spill register", insn);
 
-  /* It's the user's fault; the operand's mode and constraint
-     don't match.  Disable this reload so we don't crash in final.  */
-  error_for_asm (insn,
-		 "`asm' operand constraint incompatible with operand size");
-  rld[r].in = 0;
-  rld[r].out = 0;
-  rld[r].reg_rtx = 0;
-  rld[r].optional = 1;
-  rld[r].secondary_p = 1;
+  failed_reload (insn, r);
 
   return 1;
 }
 
-/* Assign hard reg targets for the pseudo-registers we must reload
-   into hard regs for this insn.
-   Also output the instructions to copy them in and out of the hard regs.
-
-   For machines with register classes, we are responsible for
-   finding a reload reg in the proper class.  */
-
 static void
-choose_reload_regs (chain)
+choose_reload_regs_init (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];
-  rtx save_reload_inheritance_insn[MAX_RELOADS];
-  rtx save_reload_override_in[MAX_RELOADS];
-  int save_reload_spill_index[MAX_RELOADS];
-  HARD_REG_SET save_reload_reg_used;
-  HARD_REG_SET save_reload_reg_used_in_input_addr[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_inpaddr_addr[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_output_addr[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_outaddr_addr[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_input[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_output[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_op_addr;
-  HARD_REG_SET save_reload_reg_used_in_op_addr_reload;
-  HARD_REG_SET save_reload_reg_used_in_insn;
-  HARD_REG_SET save_reload_reg_used_in_other_addr;
-  HARD_REG_SET save_reload_reg_used_at_all;
+  int i;
 
   bzero (reload_inherited, MAX_RELOADS);
   bzero ((char *) reload_inheritance_insn, MAX_RELOADS * sizeof (rtx));
@@ -5665,6 +5001,35 @@ choose_reload_regs (chain)
 
   IOR_COMPL_HARD_REG_SET (reload_reg_used, chain->used_spill_regs);
 
+  for (i = 0; i < n_reloads; i++)
+    /* If we have already decided to use a certain register,
+       don't use it in another way.  */
+    if (rld[i].reg_rtx)
+      mark_reload_reg_in_use (REGNO (rld[i].reg_rtx), rld[i].opnum,
+			      rld[i].when_needed, rld[i].mode);
+}
+
+/* Assign hard reg targets for the pseudo-registers we must reload
+   into hard regs for this insn.
+   Also output the instructions to copy them in and out of the hard regs.
+
+   For machines with register classes, we are responsible for
+   finding a reload reg in the proper class.  */
+
+static void
+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 pass, win;
+
+  rtx save_reload_reg_rtx[MAX_RELOADS];
+
+  choose_reload_regs_init (chain);
+
 #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
@@ -5701,74 +5066,26 @@ choose_reload_regs (chain)
       reload_order[j] = j;
       reload_spill_index[j] = -1;
 
-      reload_mode[j] = ((rld[j].inmode == VOIDmode
-			 || (GET_MODE_SIZE (rld[j].outmode)
-			     > GET_MODE_SIZE (rld[j].inmode)))
-			? rld[j].outmode : rld[j].inmode);
-
-      reload_nregs[j] = CLASS_MAX_NREGS (rld[j].class, reload_mode[j]);
-
-      if (reload_nregs[j] > 1)
+      if (rld[j].nregs > 1)
 	{
-	  max_group_size = MAX (reload_nregs[j], max_group_size);
+	  max_group_size = MAX (rld[j].nregs, max_group_size);
 	  group_class = reg_class_superunion[(int)rld[j].class][(int)group_class];
 	}
 
       save_reload_reg_rtx[j] = rld[j].reg_rtx;
-      /* If we have already decided to use a certain register,
-	 don't use it in another way.  */
-      if (rld[j].reg_rtx)
-	mark_reload_reg_in_use (REGNO (rld[j].reg_rtx), rld[j].opnum,
-				rld[j].when_needed, reload_mode[j]);
     }
 
   if (n_reloads > 1)
     qsort (reload_order, n_reloads, sizeof (short), reload_reg_class_lower);
 
-  bcopy (reload_inherited, save_reload_inherited, sizeof reload_inherited);
-  bcopy ((char *) reload_inheritance_insn,
-	 (char *) save_reload_inheritance_insn,
-	 sizeof reload_inheritance_insn);
-  bcopy ((char *) reload_override_in, (char *) save_reload_override_in,
-	 sizeof reload_override_in);
-  bcopy ((char *) reload_spill_index, (char *) save_reload_spill_index,
-	 sizeof reload_spill_index);
-  COPY_HARD_REG_SET (save_reload_reg_used, reload_reg_used);
-  COPY_HARD_REG_SET (save_reload_reg_used_at_all, reload_reg_used_at_all);
-  COPY_HARD_REG_SET (save_reload_reg_used_in_op_addr,
-		     reload_reg_used_in_op_addr);
-
-  COPY_HARD_REG_SET (save_reload_reg_used_in_op_addr_reload,
-		     reload_reg_used_in_op_addr_reload);
-
-  COPY_HARD_REG_SET (save_reload_reg_used_in_insn,
-		     reload_reg_used_in_insn);
-  COPY_HARD_REG_SET (save_reload_reg_used_in_other_addr,
-		     reload_reg_used_in_other_addr);
-
-  for (i = 0; i < reload_n_operands; i++)
-    {
-      COPY_HARD_REG_SET (save_reload_reg_used_in_output[i],
-			 reload_reg_used_in_output[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_input[i],
-			 reload_reg_used_in_input[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_input_addr[i],
-			 reload_reg_used_in_input_addr[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_inpaddr_addr[i],
-			 reload_reg_used_in_inpaddr_addr[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_output_addr[i],
-			 reload_reg_used_in_output_addr[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_outaddr_addr[i],
-			 reload_reg_used_in_outaddr_addr[i]);
-    }
-
   /* If -O, try first with inheritance, then turning it off.
      If not -O, don't do inheritance.
      Using inheritance when not optimizing leads to paradoxes
      with fp on the 68k: fp numbers (not NaNs) fail to be equal to themselves
      because one side of the comparison might be inherited.  */
+  win = 0;
 
-  for (inheritance = optimize > 0; inheritance >= 0; inheritance--)
+  if (optimize > 0)
     {
       /* Process the reloads in order of preference just found.
 	 Beyond this point, subregs can be found in reload_reg_rtx.
@@ -5825,7 +5142,7 @@ choose_reload_regs (chain)
 		   || rld[reload_order[i]].secondary_p)
 		  && ! rld[reload_order[i]].optional
 		  && rld[reload_order[i]].reg_rtx == 0)
-		allocate_reload_reg (chain, reload_order[i], 0, inheritance);
+		allocate_reload_reg (chain, reload_order[i], 0, 1);
 #endif
 
 	  /* First see if this pseudo is already available as reloaded
@@ -5842,191 +5159,189 @@ choose_reload_regs (chain)
 	     register be allocated here.  In `emit_reload_insns' we suppress
 	     one of the loads in the case described above.  */
 
-	  if (inheritance)
-	    {
-	      int word = 0;
-	      register int regno = -1;
-	      enum machine_mode mode = VOIDmode;
-
-	      if (rld[r].in == 0)
-		;
-	      else if (GET_CODE (rld[r].in) == REG)
-		{
-		  regno = REGNO (rld[r].in);
-		  mode = GET_MODE (rld[r].in);
-		}
-	      else if (GET_CODE (rld[r].in_reg) == REG)
-		{
-		  regno = REGNO (rld[r].in_reg);
-		  mode = GET_MODE (rld[r].in_reg);
-		}
-	      else if (GET_CODE (rld[r].in_reg) == SUBREG
-		       && GET_CODE (SUBREG_REG (rld[r].in_reg)) == REG)
-		{
-		  word = SUBREG_WORD (rld[r].in_reg);
-		  regno = REGNO (SUBREG_REG (rld[r].in_reg));
-		  if (regno < FIRST_PSEUDO_REGISTER)
-		    regno += word;
-		  mode = GET_MODE (rld[r].in_reg);
-		}
+	  {
+	    int word = 0;
+	    register int regno = -1;
+	    enum machine_mode mode = VOIDmode;
+
+	    if (rld[r].in == 0)
+	      ;
+	    else if (GET_CODE (rld[r].in) == REG)
+	      {
+		regno = REGNO (rld[r].in);
+		mode = GET_MODE (rld[r].in);
+	      }
+	    else if (GET_CODE (rld[r].in_reg) == REG)
+	      {
+		regno = REGNO (rld[r].in_reg);
+		mode = GET_MODE (rld[r].in_reg);
+	      }
+	    else if (GET_CODE (rld[r].in_reg) == SUBREG
+		     && GET_CODE (SUBREG_REG (rld[r].in_reg)) == REG)
+	      {
+		word = SUBREG_WORD (rld[r].in_reg);
+		regno = REGNO (SUBREG_REG (rld[r].in_reg));
+		if (regno < FIRST_PSEUDO_REGISTER)
+		  regno += word;
+		mode = GET_MODE (rld[r].in_reg);
+	      }
 #ifdef AUTO_INC_DEC
-	      else if ((GET_CODE (rld[r].in_reg) == PRE_INC
-			|| GET_CODE (rld[r].in_reg) == PRE_DEC
-			|| GET_CODE (rld[r].in_reg) == POST_INC
-			|| GET_CODE (rld[r].in_reg) == POST_DEC)
-		       && GET_CODE (XEXP (rld[r].in_reg, 0)) == REG)
-		{
-		  regno = REGNO (XEXP (rld[r].in_reg, 0));
-		  mode = GET_MODE (XEXP (rld[r].in_reg, 0));
-		  rld[r].out = rld[r].in;
-		}
+	    else if ((GET_CODE (rld[r].in_reg) == PRE_INC
+		      || GET_CODE (rld[r].in_reg) == PRE_DEC
+		      || GET_CODE (rld[r].in_reg) == POST_INC
+		      || GET_CODE (rld[r].in_reg) == POST_DEC)
+		     && GET_CODE (XEXP (rld[r].in_reg, 0)) == REG)
+	      {
+		regno = REGNO (XEXP (rld[r].in_reg, 0));
+		mode = GET_MODE (XEXP (rld[r].in_reg, 0));
+		rld[r].out = rld[r].in;
+	      }
 #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
-		 that can invalidate an inherited reload of part of a pseudoreg.  */
-	      else if (GET_CODE (rld[r].in) == SUBREG
-		       && GET_CODE (SUBREG_REG (rld[r].in)) == REG)
-		regno = REGNO (SUBREG_REG (rld[r].in)) + SUBREG_WORD (rld[r].in);
+	    /* 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
+	       that can invalidate an inherited reload of part of a pseudoreg.  */
+	    else if (GET_CODE (rld[r].in) == SUBREG
+		     && GET_CODE (SUBREG_REG (rld[r].in)) == REG)
+	      regno = REGNO (SUBREG_REG (rld[r].in)) + SUBREG_WORD (rld[r].in);
 #endif
 
-	      if (regno >= 0 && reg_last_reload_reg[regno] != 0)
-		{
-		  enum reg_class class = rld[r].class, last_class;
-		  rtx last_reg = reg_last_reload_reg[regno];
+	    if (regno >= 0 && reg_last_reload_reg[regno] != 0)
+	      {
+		enum reg_class class = rld[r].class, 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)
-		      && HARD_REGNO_MODE_OK (i, reload_mode[r])
-		      && (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))
+		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)
+		    && HARD_REGNO_MODE_OK (i, rld[r].mode)
+		    && (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)
+			    && (SECONDARY_INPUT_RELOAD_CLASS (class, mode,
+							      last_reg)
+				== NO_REGS)
 #endif
 #ifdef SECONDARY_MEMORY_NEEDED
-			      && ! SECONDARY_MEMORY_NEEDED (last_class, class,
-							    mode)
+			    && ! 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_for_value_p (i, rld[r].opnum,
-						      rld[r].when_needed,
-						      rld[r].in,
-						      const0_rtx, r, 1))
-		    {
-		      /* If a group is needed, verify that all the subsequent
-			 registers still have their values intact.  */
-		      int nr
-			= HARD_REGNO_NREGS (i, reload_mode[r]);
-		      int k;
+			    ))
 
-		      for (k = 1; k < nr; k++)
-			if (reg_reloaded_contents[i + k] != regno
-			    || ! TEST_HARD_REG_BIT (reg_reloaded_valid, i + k))
-			  break;
+		    && (rld[r].nregs == max_group_size
+			|| ! TEST_HARD_REG_BIT (reg_class_contents[(int) group_class],
+						i))
+		    && reload_reg_free_for_value_p (i, rld[r].opnum,
+						    rld[r].when_needed,
+						    rld[r].in,
+						    const0_rtx, r, 1))
+		  {
+		    /* If a group is needed, verify that all the subsequent
+		       registers still have their values intact.  */
+		    int nr
+		      = HARD_REGNO_NREGS (i, rld[r].mode);
+		    int k;
+
+		    for (k = 1; k < nr; k++)
+		      if (reg_reloaded_contents[i + k] != regno
+			  || ! TEST_HARD_REG_BIT (reg_reloaded_valid, i + k))
+			break;
 
-		      if (k == nr)
-			{
-			  int i1;
+		    if (k == nr)
+		      {
+			int i1;
 
-			  last_reg = (GET_MODE (last_reg) == mode
-				      ? last_reg : gen_rtx_REG (mode, i));
+			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
-			     current insn, just mark it as a place to
-			     reload from since we can't use it as the
-			     reload register itself.  */
-
-			  for (i1 = 0; i1 < n_earlyclobbers; i1++)
-			    if (reg_overlap_mentioned_for_reload_p
-				(reg_last_reload_reg[regno],
-				 reload_earlyclobbers[i1]))
-			      break;
+			/* We found a register that contains the
+			   value we need.  If this register is the
+			   same as an `earlyclobber' operand of the
+			   current insn, just mark it as a place to
+			   reload from since we can't use it as the
+			   reload register itself.  */
+
+			for (i1 = 0; i1 < n_earlyclobbers; i1++)
+			  if (reg_overlap_mentioned_for_reload_p
+			      (reg_last_reload_reg[regno],
+			       reload_earlyclobbers[i1]))
+			    break;
 
-			  if (i1 != n_earlyclobbers
-			      || ! (reload_reg_free_for_value_p
-				    (i, rld[r].opnum, rld[r].when_needed,
-				     rld[r].in, rld[r].out, r, 1))
-			      /* Don't use it if we'd clobber a pseudo reg.  */
-			      || (TEST_HARD_REG_BIT (reg_used_in_insn, i)
-				  && rld[r].out
-				  && ! TEST_HARD_REG_BIT (reg_reloaded_dead, i))
-			      /* Don't clobber the frame pointer.  */
-			      || (i == HARD_FRAME_POINTER_REGNUM
-				  && rld[r].out)
-			      /* 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))
-			      || ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].class],
-						      i)
-
-			      /* If find_reloads chose reload_out as reload
-				 register, stay with it - that leaves the
-				 inherited register for subsequent reloads.  */
-			      || (rld[r].out && rld[r].reg_rtx
-				  && rtx_equal_p (rld[r].out,
-						  rld[r].reg_rtx)))
-			    {
-			      reload_override_in[r] = last_reg;
-			      reload_inheritance_insn[r]
-				= reg_reloaded_insn[i];
-			    }
-			  else
-			    {
-			      int k;
-			      /* We can use this as a reload reg.  */
-			      /* Mark the register as in use for this part of
-				 the insn.  */
-			      mark_reload_reg_in_use (i,
-						      rld[r].opnum,
-						      rld[r].when_needed,
-						      reload_mode[r]);
-			      rld[r].reg_rtx = last_reg;
-			      reload_inherited[r] = 1;
-			      reload_inheritance_insn[r]
-				= reg_reloaded_insn[i];
-			      reload_spill_index[r] = i;
-			      for (k = 0; k < nr; k++)
-				SET_HARD_REG_BIT (reload_reg_used_for_inherit,
-						  i + k);
-			    }
-			}
-		    }
-		}
-	    }
+			if (i1 != n_earlyclobbers
+			    || ! (reload_reg_free_for_value_p
+				  (i, rld[r].opnum, rld[r].when_needed,
+				   rld[r].in, rld[r].out, r, 1))
+			    /* Don't use it if we'd clobber a pseudo reg.  */
+			    || (TEST_HARD_REG_BIT (reg_used_in_insn, i)
+				&& rld[r].out
+				&& ! TEST_HARD_REG_BIT (reg_reloaded_dead, i))
+			    /* Don't clobber the frame pointer.  */
+			    || (i == HARD_FRAME_POINTER_REGNUM
+				&& rld[r].out)
+			    /* Don't really use the inherited spill reg
+			       if we need it wider than we've got it.  */
+			    || (GET_MODE_SIZE (rld[r].mode)
+				> GET_MODE_SIZE (mode))
+			    || ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].class],
+						    i)
+
+			    /* If find_reloads chose reload_out as reload
+			       register, stay with it - that leaves the
+			       inherited register for subsequent reloads.  */
+			    || (rld[r].out && rld[r].reg_rtx
+				&& rtx_equal_p (rld[r].out,
+						rld[r].reg_rtx)))
+			  {
+			    reload_override_in[r] = last_reg;
+			    reload_inheritance_insn[r]
+			      = reg_reloaded_insn[i];
+			  }
+			else
+			  {
+			    int k;
+			    /* We can use this as a reload reg.  */
+			    /* Mark the register as in use for this part of
+			       the insn.  */
+			    mark_reload_reg_in_use (i,
+						    rld[r].opnum,
+						    rld[r].when_needed,
+						    rld[r].mode);
+			    rld[r].reg_rtx = last_reg;
+			    reload_inherited[r] = 1;
+			    reload_inheritance_insn[r]
+			      = reg_reloaded_insn[i];
+			    reload_spill_index[r] = i;
+			    for (k = 0; k < nr; k++)
+			      SET_HARD_REG_BIT (reload_reg_used_for_inherit,
+						i + k);
+			  }
+		      }
+		  }
+	      }
+	  }
 
 	  /* Here's another way to see if the value is already lying around.  */
-	  if (inheritance
-	      && rld[r].in != 0
+	  if (rld[r].in != 0
 	      && ! reload_inherited[r]
 	      && rld[r].out == 0
 	      && (CONSTANT_P (rld[r].in)
 		  || GET_CODE (rld[r].in) == PLUS
 		  || GET_CODE (rld[r].in) == REG
 		  || GET_CODE (rld[r].in) == MEM)
-	      && (reload_nregs[r] == max_group_size
+	      && (rld[r].nregs == max_group_size
 		  || ! reg_classes_intersect_p (rld[r].class, group_class)))
 	    search_equiv = rld[r].in;
 	  /* If this is an output reload from a simple move insn, look
 	     if an equivalence for the input is available.  */
-	  else if (inheritance && rld[r].in == 0 && rld[r].out != 0)
+	  else if (rld[r].in == 0 && rld[r].out != 0)
 	    {
 	      rtx set = single_set (insn);
 
@@ -6040,7 +5355,7 @@ choose_reload_regs (chain)
 	    {
 	      register rtx equiv
 		= find_equiv_reg (search_equiv, insn, rld[r].class,
-				  -1, NULL_PTR, 0, reload_mode[r]);
+				  -1, NULL_PTR, 0, rld[r].mode);
 	      int regno;
 
 	      if (equiv != 0)
@@ -6054,7 +5369,7 @@ choose_reload_regs (chain)
 			 address and not all machines support SUBREGs
 			 there.  */
 		      regno = REGNO (SUBREG_REG (equiv)) + SUBREG_WORD (equiv);
-		      equiv = gen_rtx_REG (reload_mode[r], regno);
+		      equiv = gen_rtx_REG (rld[r].mode, regno);
 		    }
 		  else
 		    abort ();
@@ -6072,7 +5387,7 @@ choose_reload_regs (chain)
 					      regno)))
 		equiv = 0;
 
-	      if (equiv != 0 && ! HARD_REGNO_MODE_OK (regno, reload_mode[r]))
+	      if (equiv != 0 && ! HARD_REGNO_MODE_OK (regno, rld[r].mode))
 		equiv = 0;
 
 	      /* We found a register that contains the value we need.
@@ -6120,7 +5435,7 @@ choose_reload_regs (chain)
 		 to load it, and use it as our reload reg.  */
 	      if (equiv != 0 && regno != HARD_FRAME_POINTER_REGNUM)
 		{
-		  int nr = HARD_REGNO_NREGS (regno, reload_mode[r]);
+		  int nr = HARD_REGNO_NREGS (regno, rld[r].mode);
 		  int k;
 		  rld[r].reg_rtx = equiv;
 		  reload_inherited[r] = 1;
@@ -6140,7 +5455,7 @@ choose_reload_regs (chain)
 			{
 			  mark_reload_reg_in_use (regno, rld[r].opnum,
 						  rld[r].when_needed,
-						  reload_mode[r]);
+						  rld[r].mode);
 			  SET_HARD_REG_BIT (reload_reg_used_for_inherit,
 					    regno + k);
 			}
@@ -6177,7 +5492,7 @@ choose_reload_regs (chain)
 	      if ((rld[s].class != rld[r].class
 		   && reg_classes_intersect_p (rld[r].class,
 					       rld[s].class))
-		  || reload_nregs[s] < reload_nregs[r])
+		  || rld[s].nregs < rld[r].nregs)
 		break;
 	    }
 
@@ -6203,53 +5518,35 @@ choose_reload_regs (chain)
 	  if (rld[r].reg_rtx != 0 || rld[r].optional)
 	    continue;
 
-	  if (! allocate_reload_reg (chain, r, j == n_reloads - 1, inheritance))
-	    break;
+	  if (! allocate_reload_reg (chain, r, j == n_reloads - 1, 1))
+	    {
+	      win = 0;
+	      break;
+	    }
 	}
-
-      /* If that loop got all the way, we have won.  */
-      if (j == n_reloads)
-	break;
+    }
 
-      /* Loop around and try without any inheritance.  */
+  if (! win)
+    {
       /* First undo everything done by the failed attempt
 	 to allocate with inheritance.  */
       for (i = 0; i < n_reloads; i++)
 	rld[i].reg_rtx = save_reload_reg_rtx[i];
-      bcopy ((char *) save_reload_inherited, (char *) reload_inherited,
-	     sizeof reload_inherited);
-      bcopy ((char *) save_reload_inheritance_insn,
-	     (char *) reload_inheritance_insn,
-	     sizeof reload_inheritance_insn);
-      bcopy ((char *) save_reload_override_in, (char *) reload_override_in,
-	     sizeof reload_override_in);
-      bcopy ((char *) save_reload_spill_index, (char *) reload_spill_index,
-	     sizeof reload_spill_index);
-      COPY_HARD_REG_SET (reload_reg_used, save_reload_reg_used);
-      COPY_HARD_REG_SET (reload_reg_used_at_all, save_reload_reg_used_at_all);
-      COPY_HARD_REG_SET (reload_reg_used_in_op_addr,
-			 save_reload_reg_used_in_op_addr);
-      COPY_HARD_REG_SET (reload_reg_used_in_op_addr_reload,
-			 save_reload_reg_used_in_op_addr_reload);
-      COPY_HARD_REG_SET (reload_reg_used_in_insn,
-			 save_reload_reg_used_in_insn);
-      COPY_HARD_REG_SET (reload_reg_used_in_other_addr,
-			 save_reload_reg_used_in_other_addr);
+      choose_reload_regs_init (chain);
 
-      for (i = 0; i < reload_n_operands; i++)
+      if (chain->n_reloads != n_reloads)
+	abort ();
+
+      for (i = 0; i < n_reloads; i++)
 	{
-	  COPY_HARD_REG_SET (reload_reg_used_in_input[i],
-			     save_reload_reg_used_in_input[i]);
-	  COPY_HARD_REG_SET (reload_reg_used_in_output[i],
-			     save_reload_reg_used_in_output[i]);
-	  COPY_HARD_REG_SET (reload_reg_used_in_input_addr[i],
-			     save_reload_reg_used_in_input_addr[i]);
-	  COPY_HARD_REG_SET (reload_reg_used_in_inpaddr_addr[i],
-			     save_reload_reg_used_in_inpaddr_addr[i]);
-	  COPY_HARD_REG_SET (reload_reg_used_in_output_addr[i],
-			     save_reload_reg_used_in_output_addr[i]);
-	  COPY_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i],
-			     save_reload_reg_used_in_outaddr_addr[i]);
+	  if (chain->rld[i].regno < 0 || chain->rld[i].reg_rtx != 0)
+	    continue;
+	  if (chain->rld[i].when_needed != rld[i].when_needed)
+	    abort ();
+	  for (j = 0; j < n_spills; j++)
+	    if (spill_regs[j] == chain->rld[i].regno)
+	      if (! set_reload_reg (j, i))
+		failed_reload (chain->insn, i);
 	}
     }
 
@@ -6326,7 +5623,7 @@ choose_reload_regs (chain)
 
 	if (spill_reg_order[regno] >= 0)
 	  clear_reload_reg_in_use (regno, rld[j].opnum,
-				   rld[j].when_needed, reload_mode[j]);
+				   rld[j].when_needed, rld[j].mode);
 	rld[j].reg_rtx = 0;
       }
 
@@ -6347,14 +5644,14 @@ choose_reload_regs (chain)
 	  int nr = 1;
 
 	  if (nregno < FIRST_PSEUDO_REGISTER)
-	    nr = HARD_REGNO_NREGS (nregno, reload_mode[r]);
+	    nr = HARD_REGNO_NREGS (nregno, rld[r].mode);
 
 	  while (--nr >= 0)
 	    reg_has_output_reload[nregno + nr] = 1;
 
 	  if (i >= 0)
 	    {
-	      nr = HARD_REGNO_NREGS (i, reload_mode[r]);
+	      nr = HARD_REGNO_NREGS (i, rld[r].mode);
 	      while (--nr >= 0)
 		SET_HARD_REG_BIT (reg_is_output_reload, i + nr);
 	    }
@@ -6381,7 +5678,7 @@ deallocate_reload_reg (r)
   rld[r].reg_rtx = 0;
   if (spill_reg_order[regno] >= 0)
     clear_reload_reg_in_use (regno, rld[r].opnum, rld[r].when_needed,
-			     reload_mode[r]);
+			     rld[r].mode);
   reload_spill_index[r] = -1;
 }
 
@@ -7659,7 +6956,7 @@ emit_reload_insns (chain)
 		  && REGNO (src_reg) < FIRST_PSEUDO_REGISTER)
 		{
 		  int src_regno = REGNO (src_reg);
-		  int nr = HARD_REGNO_NREGS (src_regno, reload_mode[r]);
+		  int nr = HARD_REGNO_NREGS (src_regno, rld[r].mode);
 		  /* 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]