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]

Reload patch version 3


Here is an updated version of the reload patch I sent in about a year ago.
Yesterday I updated it so that it patches cleanly into egcs-980816.

Remarks:
This patch changes the register allocators, global and stupid, to build a
chain of "insn_chain" structures that describes all instructions that reload
will have to look at. The insn_chain structure contains information about the
lifetime of pseudo and hard registers, and it is utilized by reload to be
more selective about spilling registers. Without this patch, reload selects
hard registers to be spilled globally, and throws out all pseudos that are
allocated to these. With the patch, it only spills pseudos that are live
during an insn that needs additional reload registers. The amount of spilling
is much reduced on a register-starved machine like the i386, which leads both
to better code quality and smaller stack frames.

It is now possible to safely spill hard registers that are explicitly used,
both on SMALL_REGISTER_CLASSES and non-SMALL_REGISTER_CLASSES machines. On
S_R_C machines it no longer risks silently generating incorrect code for
either regparam calls or for incorrect asm statements. In fact, it is _very_
unforgiving about incorrect asm: it will always bomb out with a spill failure
if one is found that tries to clobber a register that it also uses as an
operand. You won't get very far trying to compile a kernel with this... at
least unless you apply the patch which I'm going to send to linux-kernel
later.

The patch also throws out two kludges found in reload: the avoid_return_reg
and reload_address_base_reg_class hacks. They are no longer necessary.

Possible problems:
 - I threw out the code in local-alloc.c to handle SCRATCHes. I no longer
   remember exactly why - most likely I found that it would have caused
   some additional effort in reload. Since reload can handle SCRATCHes without
   the help of local-alloc, I don't quite see the point of having two pieces
   of code that do the same thing. If someone has a compelling reason I'll
   look at that again.
 - I deleted the code that handles the case when a caller-save would require
   a spill register. I don't see an easy way to handle that case in the new
   situation, and instead I disable caller-saves when such a situation would
   occur. I don't know whether this causes suboptimal code to be generated on
   some machines - feedback is appreciated here.
 - Likewise, reorg.c makes an assumption that is now invalid: that all spill
   registers are dead at basic block boundaries. This is no longer true, and
   I commented out the relevant piece of code.
 - While the new reload pass improves code on the i386 compared to the old
   one, I think the heuristics for selecting which registers to spill are by
   no means optimal yet.
 - The fact that it is unforgiving about illegal asm statements leads to
   problems for one class of asms: those which access the i387 register stack.
   Please read the comment at the top of reg-stack.c, it _tells_ you to write
   incorrect asm statements. I've put in a gross hack to try and avoid the
   problem, but most likely this isn't correct yet (reg-stack could stand
   a rewrite as well). The only problems I've noticed with the patch so far
   is a maths test that failed in a glibc-2.0.95 build.
 - Unfortunately I had to disable the unwind information in i386.h. While
   building libgcc2.a, there is one function in which some builtin eh magic
   is exercised, and it causes flow.c to build incorrect hard register life
   information (it thinks ecx is live throughout most of the function, and
   aborts because it can't reload a variable count shift instruction). That
   probably needs some fixes to flow.c.
 - Reload has become rather slow, but there is probably room for optimization.
   I have so far concentrated on trying to get it to generate correct code.
 - I think REG_NO_CONFLICT blocks aren't handled properly.

Test results (i586-linux; glibc-2.0.95):
 - No comparison failures while bootstrapping. 
 - No regressions in the test suite; gcc.dg/clobbers.c is fixed now.
 - glibc-2.0.95 builds, and mostly passes make check, only one maths test
   fails.
(actually, the glibc tests were done with a slightly different patch - this
one has an additional fix in stupid.c. I hope that this fix didn't break
anything.)

Changes:

	* reload.h (struct needs, struct insn_chain): New structures.
	(reload_insn_chain): Declare variable.
	(new_insn_chain): Declare function.
	* stupid.c: Include insn-config.h and reload.h
	(reg_where_dead_chain, reg_where_born_exact, reg_where_born_clobber):
	New variables.
	(find_clobbered_regs): New function.
	(stupid_life_analysis): While processing the insns, build
	the reload_insn_chain with information about register lifetimes.
	(stupid_mark_refs): Change second arg to be of type struct insn_chain.
	Compute and information about birth and death of pseudo registers in
	reg_where_dead_chain, reg_where_born_exact and reg_where_born_clobber.
	* global.c (regno_becomes_live, reg_becomes_live, reg_dies,
	build_insn_chain): New functions.
	(global_alloc): Call build_insn_chain before reload.
	Delete code to handle the scratch_list.
	* local-alloc.c (qty_scratch_rtx, scratch_block, scratch_list,
	scratch_list_length, scratch_index, alloc_qty_for_scratch): Delete.
	(local_alloc): Delete code to handle scratches.
	(block_alloc): Likewise.

	* reload1.c (reg_old_renumber, pseudo_forbidden_regs, failure,
	spilled_pseudos, reload_startobj, reload_insn_chain): New variables.
	(forbidden_regs): Make static.
	(counted_for_groups, counted_for_nongroups, basic_block_needs): Delete.
	(new_insn_chain): New function.
	(find_reload_regs): New function, mostly broken out of reload.c.
	(find_tworeg_group): Likewise.
	(find_group): Likewise.
	(possible_group_p): Accept a struct insn_chain, and use the information
	recorded in it instead of global variables.
	(count_possible_groups): Likewise.
	(init_reload): Initialize reload_startobj, not reload_firstobj.
	Delete code to deal with reload_address_{base,index}_reg_class.
	(reload): Initialize reload_firstobj here. Initialize failure to 0.
	Allocate and initialize reg_old_renumber and pseudo_forbidden_regs.
	Delete code to keep track of basic_block_needs.
	Delete code to keep track of previously allocated SCRATCHes.
	Delete code to deal with caller saves that need spill registers.
	Delete avoid_return_reg code.
	Delete code to calculate the maximum needs for all instructions; we
	now spill every instruction separately.
	Walk reload_insn_chain instead of the normal rtx insn chain. After
	calling find_reloads, record the need for eliminations and for reloads
	in the chain, not in the insn's mode.
	Use group_size and group_mode in the insn_chain structure instead of
	local variables.
	Call find_reload_regs instead of doing everything in-line.
	(reload_as_needed): Walk the reload_insn_chain instead of the rtx
	structure.
	Make sure finish_spills is called after spill_hard_reg in all cases.
	Delete avoid_return_reg code.
	Delete basic_block_needs code.
	(new_spill_reg): Accept a struct insn_chain argument. Delete max_needs
	and max_nongroups arguments, take a single integer argument nongroup
	instead.
	When running out of regs, don't abort; call spill_failure, set failure
	to 1 and return.
	Don't test against fixed_regs and forbidden_regs; bad_spill_regs now
	contains all registers that may not be spilled for a given instruction.
	Don't use max_needs and max_nongroups variables, instead use the
	information found in the insn_chain structure for the current
	instruction.
	(spill_hard_reg): Delete GLOBAL argument.
	Delete basic_block_needs code.
	Record the affected pseudos in the variable spilled_pseudos.
	(spill_caller_saved_regs): New function
	(finish_spills): New function. This walks the registers marked in
	spilled_pseudos, throws them out of their hard registers, and tries
	to reallocate them by calling retry_global_alloc. Then, it updates
	the register life information in reload_insn_chain.
	(allocate_reload_reg): Accept a struct insn_chain instead of an rtx.
	Use the information found within instead of global variables.
	(choose_reload_regs): Accept a struct insn_chain instead of an rtx.
	Delete avoid_return_reg code.
	(order_regs_for_reload): Accept an additional struct insn_chain
	parameter. Calculate an order appropriate for reloading a single
	insn; fill potential_reload_regs with hard register numbers in order
	of decreasing desirability. Record hard registers that are unsuitable
	for spilling in bad_spill_registers.
	(hard_reg_use_compare): Take bad_spill_regs into account.

	* caller_save.c (save_call_clobbered_regs): Change parameter to be
	of type int.
	Rework this function to walk the reload_insn_chain instead of using
	the list of instructions directly.
	(restore_referenced_regs): Change parameters: now accepts a struct
	insn_chain instead of an rtx, and an integer to indicate whether
	elimination is needed.
	(insert_save_restore): Likewise.
	Make a new insn_chain structure for added instructions.
	* reorg.c (find_dead_or_set_registers): Comment out code that assumes
	all spill registers are dead at code labels.

	* Makefile.in (stupid.o, global.o): Update dependencies.
	* i386/i386.h: Disable unwind information for now, so that the compiler
	bootstraps.

Index: Makefile.in
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/Makefile.in,v
retrieving revision 1.1.1.56
diff -u -r1.1.1.56 Makefile.in
--- Makefile.in	1998/08/05 11:57:06	1.1.1.56
+++ Makefile.in	1998/08/24 16:12:37
@@ -1431,7 +1431,7 @@
    insn-config.h insn-flags.h $(RECOG_H) $(EXPR_H) real.h except.h \
    toplev.h
 stupid.o : stupid.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h \
-   flags.h toplev.h
+   flags.h toplev.h reload.h
 
 cse.o : cse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
    real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h
@@ -1457,7 +1457,7 @@
    insn-attr.h toplev.h
 bitmap.o : bitmap.c $(CONFIG_H) system.h $(RTL_H) flags.h $(BASIC_BLOCK_H) \
    $(REGS_H)
-global.o : global.c $(CONFIG_H) system.h $(RTL_H) flags.h  \
+global.o : global.c $(CONFIG_H) system.h $(RTL_H) flags.h reload.h \
    $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h toplev.h
 varray.o : varray.c $(CONFIG_H) system.h varray.h $(RTL_H) $(TREE_H) bitmap.h
 
Index: caller-save.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/caller-save.c,v
retrieving revision 1.1.1.12
diff -u -r1.1.1.12 caller-save.c
--- caller-save.c	1998/06/24 11:24:31	1.1.1.12
+++ caller-save.c	1998/08/24 15:56:16
@@ -82,9 +82,10 @@
 
 static void set_reg_live		PROTO((rtx, rtx));
 static void clear_reg_live		PROTO((rtx));
-static void restore_referenced_regs	PROTO((rtx, rtx, enum machine_mode));
-static int insert_save_restore		PROTO((rtx, int, int,
-					       enum machine_mode, int));
+static void restore_referenced_regs	PROTO((rtx, struct insn_chain *,
+					       int));
+static int insert_save_restore		PROTO((struct insn_chain *, int, int,
+					       int, int));
 
 /* Initialize for caller-save.
 
@@ -344,158 +345,152 @@
 
 /* Find the places where hard regs are live across calls and save them.
 
-   INSN_MODE is the mode to assign to any insns that we add.  This is used
+   NEED_ELIM is the mode to assign to any insns that we add.  This is used
    by reload to determine whether or not reloads or register eliminations
    need be done on these insns.  */
 
 void
-save_call_clobbered_regs (insn_mode)
-     enum machine_mode insn_mode;
+save_call_clobbered_regs (need_elim)
+     int need_elim;
 {
-  rtx insn;
+  rtx prev_block_last;
+  struct insn_chain *chain;
   int b;
 
-  for (b = 0; b < n_basic_blocks; b++)
-    {
-      regset regs_live = basic_block_live_at_start[b];
-      rtx prev_block_last = PREV_INSN (basic_block_head[b]);
+  /* Now scan the insns in each block, keeping track of what hard
+     regs are live as we go.  When we see a call, save the live
+     call-clobbered hard regs.  */
+
+  b = -1;
+  for (chain = reload_insn_chain; chain; chain = chain->next)
+    {      
       int i, j;
       int regno;
+      rtx insn = chain->insn;
+      enum rtx_code code = GET_CODE (insn);
+      
+      if (chain->block > b)
+	{
+	  b = chain->block;
+	  prev_block_last = PREV_INSN (basic_block_head[b]);
 
-      /* Compute hard regs live at start of block -- this is the
-	 real hard regs marked live, plus live pseudo regs that
-	 have been renumbered to hard regs.  No registers have yet been
-	 saved because we restore all of them before the end of the basic
-	 block.  */
-
-      REG_SET_TO_HARD_REG_SET (hard_regs_live, regs_live);
-      CLEAR_HARD_REG_SET (hard_regs_saved);
-      CLEAR_HARD_REG_SET (hard_regs_need_restore);
-      n_regs_saved = 0;
-
-      EXECUTE_IF_SET_IN_REG_SET (regs_live, 0, i,
-				 {
-				   if ((regno = reg_renumber[i]) >= 0)
-				     for (j = regno;
-					  j < regno + HARD_REGNO_NREGS (regno,
-									PSEUDO_REGNO_MODE (i));
-					  j++)
-				       SET_HARD_REG_BIT (hard_regs_live, j);
-				 });
-
-      /* Now scan the insns in the block, keeping track of what hard
-	 regs are live as we go.  When we see a call, save the live
-	 call-clobbered hard regs.  */
+	  /* Compute hard regs live at start of block.  This information is
+	     available in the insn chain.  */
+
+	  CLEAR_HARD_REG_SET (hard_regs_live);
+	  CLEAR_HARD_REG_SET (hard_regs_saved);
+	  CLEAR_HARD_REG_SET (hard_regs_need_restore);
+	  n_regs_saved = 0;
+	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	    if (chain->inverse_renum_before[i] != 0)
+	      SET_HARD_REG_BIT (hard_regs_live, i);
+	}
 
-      for (insn = basic_block_head[b]; ; insn = NEXT_INSN (insn))
+      if (GET_RTX_CLASS (code) == 'i')
 	{
-	  RTX_CODE code = GET_CODE (insn);
+	  rtx link;
 
-	  if (GET_RTX_CLASS (code) == 'i')
-	    {
-	      rtx link;
+	  /* If some registers have been saved, see if INSN references
+	     any of them.  We must restore them before the insn if so.  */
 
-	      /* If some registers have been saved, see if INSN references
-		 any of them.  We must restore them before the insn if so.  */
+	  if (n_regs_saved)
+	    restore_referenced_regs (PATTERN (insn), chain, need_elim);
 
-	      if (n_regs_saved)
-		restore_referenced_regs (PATTERN (insn), insn, insn_mode);
+	  /* NB: the normal procedure is to first enliven any
+	     registers set by insn, then deaden any registers that
+	     had their last use at insn.  This is incorrect now,
+	     since multiple pseudos may have been mapped to the
+	     same hard reg, and the death notes are ambiguous.  So
+	     it must be done in the other, safe, order.  */
+
+	  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+	    if (REG_NOTE_KIND (link) == REG_DEAD)
+	      clear_reg_live (XEXP (link, 0));
+
+	  /* When we reach a call, we need to save all registers that are
+	     live, call-used, not fixed, and not already saved.  We must
+	     test at this point because registers that die in a CALL_INSN
+	     are not live across the call and likewise for registers that
+	     are born in the CALL_INSN.
+
+	     If registers are filled with parameters for this function,
+	     and some of these are also being set by this function, then
+	     they will not appear to die (no REG_DEAD note for them),
+	     to check if in fact they do, collect the set registers in
+	     hard_regs_live first.  */
 
-	      /* NB: the normal procedure is to first enliven any
-		 registers set by insn, then deaden any registers that
-		 had their last use at insn.  This is incorrect now,
-		 since multiple pseudos may have been mapped to the
-		 same hard reg, and the death notes are ambiguous.  So
-		 it must be done in the other, safe, order.  */
+	  if (code == CALL_INSN)
+	    {
+	      HARD_REG_SET this_call_sets;
+	      {
+		HARD_REG_SET old_hard_regs_live;
 
-	      for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
-		if (REG_NOTE_KIND (link) == REG_DEAD)
-		  clear_reg_live (XEXP (link, 0));
+		/* Save the hard_regs_live information.  */
+		COPY_HARD_REG_SET (old_hard_regs_live, hard_regs_live);
 
-	      /* When we reach a call, we need to save all registers that are
-		 live, call-used, not fixed, and not already saved.  We must
-		 test at this point because registers that die in a CALL_INSN
-		 are not live across the call and likewise for registers that
-		 are born in the CALL_INSN.
-		 
-		 If registers are filled with parameters for this function,
-		 and some of these are also being set by this function, then
-		 they will not appear to die (no REG_DEAD note for them),
-		 to check if in fact they do, collect the set registers in
-		 hard_regs_live first.  */
+		/* Now calculate hard_regs_live for this CALL_INSN
+		   only.  */
+		CLEAR_HARD_REG_SET (hard_regs_live);
+		note_stores (PATTERN (insn), set_reg_live);
+		COPY_HARD_REG_SET (this_call_sets, hard_regs_live);
 
-	      if (code == CALL_INSN)
-		{
-		  HARD_REG_SET this_call_sets;
-		  {
-		    HARD_REG_SET old_hard_regs_live;
-
-		    /* Save the hard_regs_live information.  */
-		    COPY_HARD_REG_SET (old_hard_regs_live, hard_regs_live);
-
-		    /* Now calculate hard_regs_live for this CALL_INSN
-		       only.  */
-		    CLEAR_HARD_REG_SET (hard_regs_live);
-		    note_stores (PATTERN (insn), set_reg_live);
-		    COPY_HARD_REG_SET (this_call_sets, hard_regs_live);
-
-		    /* Restore the hard_regs_live information.  */
-		    COPY_HARD_REG_SET (hard_regs_live, old_hard_regs_live);
-		  }
-
-		  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-		    if (call_used_regs[regno] && ! call_fixed_regs[regno]
-		        && TEST_HARD_REG_BIT (hard_regs_live, regno)
-			/* It must not be set by this instruction.  */
-		        && ! TEST_HARD_REG_BIT (this_call_sets, regno)
-		        && ! TEST_HARD_REG_BIT (hard_regs_saved, regno))
-		      regno += insert_save_restore (insn, 1, regno, 
-						    insn_mode, 0);
-
-		  /* Put the information for this CALL_INSN on top of what
-		     we already had.  */
-		  IOR_HARD_REG_SET (hard_regs_live, this_call_sets);
-		  COPY_HARD_REG_SET (hard_regs_need_restore, hard_regs_saved);
-
-		  /* Must recompute n_regs_saved.  */
-		  n_regs_saved = 0;
-		  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-		    if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
-		      n_regs_saved++;
-		}
-	      else
-		{
-		  note_stores (PATTERN (insn), set_reg_live);
-#ifdef AUTO_INC_DEC
-		  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
-		    if (REG_NOTE_KIND (link) == REG_INC)
-		      set_reg_live (XEXP (link, 0), NULL_RTX);
-#endif
-		}
+		/* Restore the hard_regs_live information.  */
+		COPY_HARD_REG_SET (hard_regs_live, old_hard_regs_live);
+	      }
 
+	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+		if (call_used_regs[regno] && ! call_fixed_regs[regno]
+		    && TEST_HARD_REG_BIT (hard_regs_live, regno)
+		    /* It must not be set by this instruction.  */
+		    && ! TEST_HARD_REG_BIT (this_call_sets, regno)
+		    && ! TEST_HARD_REG_BIT (hard_regs_saved, regno))
+		  regno += insert_save_restore (chain, 1, regno, 
+						need_elim, 0);
+
+	      /* Put the information for this CALL_INSN on top of what
+		 we already had.  */
+	      IOR_HARD_REG_SET (hard_regs_live, this_call_sets);
+	      COPY_HARD_REG_SET (hard_regs_need_restore, hard_regs_saved);
+
+	      /* Must recompute n_regs_saved.  */
+	      n_regs_saved = 0;
+	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+		if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
+		  n_regs_saved++;
+	    }
+	  else
+	    {
+	      note_stores (PATTERN (insn), set_reg_live);
+#ifdef AUTO_INC_DEC
 	      for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
-		if (REG_NOTE_KIND (link) == REG_UNUSED)
-		  clear_reg_live (XEXP (link, 0));
+		if (REG_NOTE_KIND (link) == REG_INC)
+		  set_reg_live (XEXP (link, 0), NULL_RTX);
+#endif
 	    }
-
-	  if (insn == basic_block_end[b])
-	    break;
+	  
+	  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+	    if (REG_NOTE_KIND (link) == REG_UNUSED)
+	      clear_reg_live (XEXP (link, 0));
 	}
 
-      /* At the end of the basic block, we must restore any registers that
-	 remain saved.  If the last insn in the block is a JUMP_INSN, put
-	 the restore before the insn, otherwise, put it after the insn.  */
-
-      if (n_regs_saved)
-	for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-	  if (TEST_HARD_REG_BIT (hard_regs_need_restore, regno))
-	    regno += insert_save_restore ((GET_CODE (insn) == JUMP_INSN
-				  ? insn : NEXT_INSN (insn)), 0,
-				  regno, insn_mode, MOVE_MAX / UNITS_PER_WORD);
-
-      /* If we added any insns at the start of the block, update the start
-	 of the block to point at those insns.  */
-      basic_block_head[b] = NEXT_INSN (prev_block_last);
+      if (chain->next == 0 || chain->next->block > b)
+	{
+	  /* At the end of the basic block, we must restore any registers that
+	     remain saved.  If the last insn in the block is a JUMP_INSN, put
+	     the restore before the insn, otherwise, put it after the insn.  */
+
+	  if (n_regs_saved)
+	    for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+	      if (TEST_HARD_REG_BIT (hard_regs_need_restore, regno))
+		regno += insert_save_restore ((GET_CODE (insn) == JUMP_INSN
+					       ? chain : chain->next), 0,
+					      regno, need_elim,
+					      MOVE_MAX / UNITS_PER_WORD);
+
+	  /* If we added any insns at the start of the block, update the start
+	     of the block to point at those insns.  */
+	  basic_block_head[b] = NEXT_INSN (prev_block_last);
+	}
     }
 }
 
@@ -559,13 +554,13 @@
 
 /* If any register currently residing in the save area is referenced in X,
    which is part of INSN, emit code to restore the register in front of INSN.
-   INSN_MODE is the mode to assign to any insns that we add.  */
+   NEED_ELIM is the mode to assign to any insns that we add.  */
 
 static void
-restore_referenced_regs (x, insn, insn_mode)
+restore_referenced_regs (x, chain, need_elim)
      rtx x;
-     rtx insn;
-     enum machine_mode insn_mode;
+     struct insn_chain *chain;
+     int need_elim;
 {
   enum rtx_code code = GET_CODE (x);
   char *fmt;
@@ -584,11 +579,11 @@
       if (regno >= FIRST_PSEUDO_REGISTER
 	  && reg_equiv_mem[regno] != 0)
 	restore_referenced_regs (XEXP (reg_equiv_mem[regno], 0),
-				 insn, insn_mode);
+				 chain, need_elim);
       else if (regno >= FIRST_PSEUDO_REGISTER
 	       && reg_equiv_address[regno] != 0)
 	restore_referenced_regs (reg_equiv_address[regno],
-				 insn, insn_mode);
+				 chain, need_elim);
 
       /* Otherwise if this is a hard register, restore any piece of it that
 	 is currently saved.  */
@@ -603,7 +598,7 @@
 
 	  for (i = regno; i < endregno; i++)
 	    if (TEST_HARD_REG_BIT (hard_regs_need_restore, i))
-	      i += insert_save_restore (insn, 0, i, insn_mode, saveregs);
+	      i += insert_save_restore (chain, 0, i, need_elim, saveregs);
 	}
 
       return;
@@ -613,15 +608,15 @@
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e')
-	restore_referenced_regs (XEXP (x, i), insn, insn_mode);
+	restore_referenced_regs (XEXP (x, i), chain, need_elim);
       else if (fmt[i] == 'E')
 	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-	  restore_referenced_regs (XVECEXP (x, i, j), insn, insn_mode);
+	  restore_referenced_regs (XVECEXP (x, i, j), chain, need_elim);
     }
 }
 
 /* Insert a sequence of insns to save or restore, SAVE_P says which,
-   REGNO.  Place these insns in front of INSN.  INSN_MODE is the mode
+   REGNO.  Place these insns in front of INSN.  NEED_ELIM is the mode
    to assign to these insns.   MAXRESTORE is the maximum number of registers
    which should be restored during this call (when SAVE_P == 0).  It should
    never be less than 1 since we only work with entire registers.
@@ -635,14 +630,16 @@
    Return the extra number of registers saved.  */
 
 static int
-insert_save_restore (insn, save_p, regno, insn_mode, maxrestore)
-     rtx insn;
+insert_save_restore (chain, save_p, regno, need_elim, maxrestore)
+     struct insn_chain *chain;
      int save_p;
      int regno;
-     enum machine_mode insn_mode;
+     int need_elim;
      int maxrestore;
 {
+  struct insn_chain *new;
   rtx pat = NULL_RTX;
+  rtx insn = chain->insn;
   enum insn_code code = CODE_FOR_nothing;
   int numregs = 0;
 
@@ -665,7 +662,7 @@
 
   if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
       && reg_referenced_p (cc0_rtx, PATTERN (insn)))
-    insn = prev_nonnote_insn (insn);
+    chain = chain->prev, insn = chain->insn;
 #endif
 
   /* Get the pattern to emit and update our status.  */
@@ -753,10 +750,16 @@
         }
     }
   /* Emit the insn and set the code and mode.  */
-
-  insn = emit_insn_before (pat, insn);
-  PUT_MODE (insn, insn_mode);
-  INSN_CODE (insn) = code;
+  
+  new = new_insn_chain ();
+  new->prev = chain->prev;
+  new->prev->next = new;
+  chain->prev = new;
+  new->next = chain;
+  new->insn = emit_insn_before (pat, insn);
+  new->block = chain->block;
+  new->need_reload = 0;
+  new->need_elim = need_elim;
 
   /* Tell our callers how many extra registers we saved/restored */
   return numregs - 1;
Index: configure
Index: global.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/global.c,v
retrieving revision 1.1.1.12
diff -u -r1.1.1.12 global.c
--- global.c	1998/06/29 18:05:17	1.1.1.12
+++ global.c	1998/08/24 15:56:28
@@ -29,6 +29,7 @@
 #include "basic-block.h"
 #include "regs.h"
 #include "insn-config.h"
+#include "reload.h"
 #include "output.h"
 #include "toplev.h"
 
@@ -268,6 +269,10 @@
 static void mark_reg_live_nc	PROTO((int, enum machine_mode));
 static void set_preference	PROTO((rtx, rtx));
 static void dump_conflicts	PROTO((FILE *));
+static void regno_becomes_live	PROTO((int, enum machine_mode));
+static void reg_becomes_live	PROTO((rtx, rtx));
+static void reg_dies		PROTO((int, enum machine_mode));
+static void build_insn_chain	PROTO((rtx));
 
 /* Perform allocation of pseudo-registers not allocated by local_alloc.
    FILE is a file to output debugging information on,
@@ -451,18 +456,6 @@
     if (regs_ever_live[i])
       local_reg_n_refs[i] = 0;
 
-  /* Likewise for regs used in a SCRATCH.  */
-  for (i = 0; i < scratch_list_length; i++)
-    if (scratch_list[i])
-      {
-	int regno = REGNO (scratch_list[i]);
-	int lim = regno + HARD_REGNO_NREGS (regno, GET_MODE (scratch_list[i]));
-	int j;
-
-	for (j = regno; j < lim; j++)
-	  local_reg_n_refs[j] = 0;
-      }
-	
   /* Allocate the space for the conflict and preference tables and
      initialize them.  */
 
@@ -584,7 +577,10 @@
 	 for the sake of debugging information.  */
   if (n_basic_blocks > 0)
 #endif
-    retval = reload (get_insns (), 1, file);
+    {
+      build_insn_chain (get_insns ());
+      retval = reload (get_insns (), 1, file);
+    }
 
   free (conflicts);
   return retval;
@@ -1650,6 +1646,164 @@
 	CLEAR_REGNO_REG_SET (basic_block_live_at_start[i], from);
 	SET_REGNO_REG_SET (basic_block_live_at_start[i], to);
       }
+}
+
+/* Used for communication between the following functions.  Holds the
+   current life information.  */
+static int inverse_renumber[FIRST_PSEUDO_REGISTER];
+
+/* Record in inverse_renumber that register REGNO became live.  */
+static void
+regno_becomes_live (regno, mode)
+     int regno;
+     enum machine_mode mode;
+{
+  int hardregno, nregs;
+  if (regno < FIRST_PSEUDO_REGISTER)
+    {
+      hardregno = regno;
+      if (mode == VOIDmode)
+	nregs = 1;
+      else
+	nregs = HARD_REGNO_NREGS (regno, mode);
+      regno = -1;
+    }
+  else
+    {
+      hardregno = reg_renumber[regno];
+      if (hardregno < 0)
+	return;
+      nregs = HARD_REGNO_NREGS (hardregno, PSEUDO_REGNO_MODE (regno));
+    }
+
+  while (nregs--)
+    inverse_renumber[hardregno++] = regno;
+}
+
+/* Record in inverse_renumber that register REG became live.  This
+   is called via note_stores.  */
+static void
+reg_becomes_live (reg, setter)
+     rtx reg, setter;
+{
+  if (GET_CODE (reg) == REG)
+    regno_becomes_live (REGNO (reg), GET_MODE (reg));
+  else if (GET_CODE (reg) == SUBREG)
+    {
+      rtx reg2 = SUBREG_REG (reg);
+      if (GET_CODE (reg2) == REG)
+	{
+	  warning ("Subreg here");
+
+	  if (REGNO (reg2) < FIRST_PSEUDO_REGISTER)
+	    regno_becomes_live (REGNO (reg2) + SUBREG_WORD (reg),
+				GET_MODE (reg));
+	  else
+	    regno_becomes_live (REGNO (reg2), GET_MODE (reg2));
+	}
+    }
+}
+
+/* Record in inverse_renumber that register REGNO died.  */
+static void
+reg_dies (regno, mode)
+     int regno;
+     enum machine_mode mode;
+{
+  int hardregno, nregs;
+  if (regno < FIRST_PSEUDO_REGISTER)
+    {
+      hardregno = regno;
+      nregs = HARD_REGNO_NREGS (regno, mode);
+    }
+  else
+    {
+      hardregno = reg_renumber[regno];
+      if (hardregno < 0)
+	return;
+      nregs = HARD_REGNO_NREGS (hardregno, PSEUDO_REGNO_MODE (regno));
+    }
+
+  while (nregs--)
+    inverse_renumber[hardregno++] = 0;
+}
+
+/* Walk the insns of the current function and build reload_insn_chain,
+   and record register life information if it is available.  */
+static void
+build_insn_chain (first)
+     rtx first;
+{
+  struct insn_chain **p = &reload_insn_chain;
+  struct insn_chain *prev = 0;
+  int b = 0;
+
+  bzero ((char *)inverse_renumber, sizeof inverse_renumber);
+
+  for (; first; first = NEXT_INSN (first))
+    {
+      struct insn_chain *c;
+
+      if (GET_CODE (first) != NOTE && GET_CODE (first) != BARRIER)
+	{
+	  c = new_insn_chain ();
+	  c->prev = prev;
+	  prev = c;
+	  *p = c;
+	  p = &c->next;
+	  c->insn = first;
+	  c->block = b;
+
+	  if (first == basic_block_head[b])
+	    {
+	      int regno;
+	      bzero ((char *)inverse_renumber, sizeof inverse_renumber);
+	      EXECUTE_IF_SET_IN_REG_SET (basic_block_live_at_start[b],
+					 0, regno,
+					  {
+					    regno_becomes_live (regno, VOIDmode);
+					  });
+	    }
+
+	  bcopy (inverse_renumber, c->inverse_renum_before, sizeof inverse_renumber);
+
+	  if (GET_RTX_CLASS (GET_CODE (first)) == 'i')
+	    {
+	      rtx link;
+
+	      /* Mark the death of everything that dies in this instruction.  */
+
+	      for (link = REG_NOTES (first); link; link = XEXP (link, 1))
+		if (REG_NOTE_KIND (link) == REG_DEAD
+		    && GET_CODE (XEXP (link, 0)) == REG)
+		  reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)));
+
+	      /* Mark everything born in this instruction as live.  */
+
+	      note_stores (PATTERN (first), reg_becomes_live);
+	    }
+
+	  /* Remember which registers are live at the end of the insn, before
+	     killing those with REG_UNUSED notes.  */
+	  bcopy (inverse_renumber, c->inverse_renum_after, sizeof inverse_renumber);
+
+	  if (GET_RTX_CLASS (GET_CODE (first)) == 'i')
+	    {
+	      rtx link;
+
+	      /* Mark anything that is set in this insn and then unused as dying.  */
+
+	      for (link = REG_NOTES (first); link; link = XEXP (link, 1))
+		if (REG_NOTE_KIND (link) == REG_UNUSED
+		    && GET_CODE (XEXP (link, 0)) == REG)
+		  reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)));
+	    }
+	}
+
+      if (first == basic_block_end[b])
+	b++;
+    }
+  *p = 0;
 }
 
 /* Print debugging trace information if -greg switch is given,
Index: local-alloc.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/local-alloc.c,v
retrieving revision 1.1.1.18
diff -u -r1.1.1.18 local-alloc.c
--- local-alloc.c	1998/06/29 18:05:26	1.1.1.18
+++ local-alloc.c	1998/08/24 15:56:30
@@ -156,11 +156,6 @@
 
 static enum reg_class *qty_alternate_class;
 
-/* Element Q is the SCRATCH expression for which this quantity is being
-   allocated or 0 if this quantity is allocating registers.  */
-
-static rtx *qty_scratch_rtx;
-
 /* Element Q is nonzero if this quantity has been used in a SUBREG
    that changes its size.  */
 
@@ -227,11 +222,6 @@
 
 static HARD_REG_SET *regs_live_at;
 
-int *scratch_block;
-rtx *scratch_list;
-int scratch_list_length;
-static int scratch_index;
-
 /* Communicate local vars `insn_number' and `insn'
    from `block_alloc' to `reg_is_set', `wipe_dead_reg', and `alloc_qty'.  */
 static int this_insn_number;
@@ -297,96 +287,6 @@
   qty_changes_size[qty] = REG_CHANGES_SIZE (regno);
 }
 
-/* Similar to `alloc_qty', but allocates a quantity for a SCRATCH rtx
-   used as operand N in INSN.  We assume here that the SCRATCH is used in
-   a CLOBBER.  */
-
-static void
-alloc_qty_for_scratch (scratch, n, insn, insn_code_num, insn_number)
-     rtx scratch;
-     int n;
-     rtx insn;
-     int insn_code_num, insn_number;
-{
-  register int qty;
-  enum reg_class class;
-  char *p, c;
-  int i;
-
-#ifdef REGISTER_CONSTRAINTS
-  /* If we haven't yet computed which alternative will be used, do so now.
-     Then set P to the constraints for that alternative.  */
-  if (which_alternative == -1)
-    if (! constrain_operands (insn_code_num, 0))
-      return;
-
-  for (p = insn_operand_constraint[insn_code_num][n], i = 0;
-       *p && i < which_alternative; p++)
-    if (*p == ',')
-      i++;
-
-  /* Compute the class required for this SCRATCH.  If we don't need a
-     register, the class will remain NO_REGS.  If we guessed the alternative
-     number incorrectly, reload will fix things up for us.  */
-
-  class = NO_REGS;
-  while ((c = *p++) != '\0' && c != ',')
-    switch (c)
-      {
-      case '=':  case '+':  case '?':
-      case '#':  case '&':  case '!':
-      case '*':  case '%':  
-      case '0':  case '1':  case '2':  case '3':  case '4':
-      case 'm':  case '<':  case '>':  case 'V':  case 'o':
-      case 'E':  case 'F':  case 'G':  case 'H':
-      case 's':  case 'i':  case 'n':
-      case 'I':  case 'J':  case 'K':  case 'L':
-      case 'M':  case 'N':  case 'O':  case 'P':
-#ifdef EXTRA_CONSTRAINT
-      case 'Q':  case 'R':  case 'S':  case 'T':  case 'U':
-#endif
-      case 'p':
-	/* These don't say anything we care about.  */
-	break;
-
-      case 'X':
-	/* We don't need to allocate this SCRATCH.  */
-	return;
-
-      case 'g': case 'r':
-	class = reg_class_subunion[(int) class][(int) GENERAL_REGS];
-	break;
-
-      default:
-	class
-	  = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER (c)];
-	break;
-      }
-
-  if (class == NO_REGS)
-    return;
-
-#else /* REGISTER_CONSTRAINTS */
-
-  class = GENERAL_REGS;
-#endif
-  
-
-  qty = next_qty++;
-
-  qty_first_reg[qty] = -1;
-  qty_scratch_rtx[qty] = scratch;
-  qty_size[qty] = GET_MODE_SIZE (GET_MODE (scratch));
-  qty_mode[qty] = GET_MODE (scratch);
-  qty_birth[qty] = 2 * insn_number - 1;
-  qty_death[qty] = 2 * insn_number + 1;
-  qty_n_calls_crossed[qty] = 0;
-  qty_min_class[qty] = class;
-  qty_alternate_class[qty] = NO_REGS;
-  qty_n_refs[qty] = 1;
-  qty_changes_size[qty] = 0;
-}
-
 /* Main entry point of this file.  */
 
 void
@@ -415,18 +315,6 @@
      See the declarations of these variables, above,
      for what they mean.  */
 
-  /* There can be up to MAX_SCRATCH * N_BASIC_BLOCKS SCRATCHes to allocate.
-     Instead of allocating this much memory from now until the end of
-     reload, only allocate space for MAX_QTY SCRATCHes.  If there are more
-     reload will allocate them.  */
-
-  scratch_list_length = max_qty;
-  scratch_list = (rtx *) xmalloc (scratch_list_length * sizeof (rtx));
-  bzero ((char *) scratch_list, scratch_list_length * sizeof (rtx));
-  scratch_block = (int *) xmalloc (scratch_list_length * sizeof (int));
-  bzero ((char *) scratch_block, scratch_list_length * sizeof (int));
-  scratch_index = 0;
-
   qty_phys_reg = (short *) alloca (max_qty * sizeof (short));
   qty_phys_copy_sugg
     = (HARD_REG_SET *) alloca (max_qty * sizeof (HARD_REG_SET));
@@ -435,7 +323,6 @@
   qty_phys_num_sugg = (short *) alloca (max_qty * sizeof (short));
   qty_birth = (int *) alloca (max_qty * sizeof (int));
   qty_death = (int *) alloca (max_qty * sizeof (int));
-  qty_scratch_rtx = (rtx *) alloca (max_qty * sizeof (rtx));
   qty_first_reg = (int *) alloca (max_qty * sizeof (int));
   qty_size = (int *) alloca (max_qty * sizeof (int));
   qty_mode
@@ -493,7 +380,6 @@
 	{
 	  for (i = 0; i < next_qty; i++)
 	    {
-	      qty_scratch_rtx[i] = 0;
 	      CLEAR_HARD_REG_SET (qty_phys_copy_sugg[i]);
 	      qty_phys_num_copy_sugg[i] = 0;
 	      CLEAR_HARD_REG_SET (qty_phys_sugg[i]);
@@ -505,7 +391,6 @@
 #define CLEAR(vector)  \
 	  bzero ((char *) (vector), (sizeof (*(vector))) * next_qty);
 
-	  CLEAR (qty_scratch_rtx);
 	  CLEAR (qty_phys_copy_sugg);
 	  CLEAR (qty_phys_num_copy_sugg);
 	  CLEAR (qty_phys_sugg);
@@ -1029,9 +914,6 @@
   int max_uid = get_max_uid ();
   int *qty_order;
   int no_conflict_combined_regno = -1;
-  /* Counter to prevent allocating more SCRATCHes than can be stored
-     in SCRATCH_LIST.  */
-  int scratches_allocated = scratch_index;
 
   /* Count the instructions in the basic block.  */
 
@@ -1285,15 +1167,6 @@
 		&& GET_CODE (XEXP (link, 0)) == REG)
 	      wipe_dead_reg (XEXP (link, 0), 1);
 
-	  /* Allocate quantities for any SCRATCH operands of this insn.  */
-
-	  if (insn_code_number >= 0)
-	    for (i = 0; i < insn_n_operands[insn_code_number]; i++)
-	      if (GET_CODE (recog_operand[i]) == SCRATCH
-		  && scratches_allocated++ < scratch_list_length)
-		alloc_qty_for_scratch (recog_operand[i], i, insn,
-				       insn_code_number, insn_number);
-
 	  /* If this is an insn that has a REG_RETVAL note pointing at a 
 	     CLOBBER insn, we have reached the end of a REG_NO_CONFLICT
 	     block, so clear any register number that combined within it.  */
@@ -1492,16 +1365,6 @@
       {
 	for (i = qty_first_reg[q]; i >= 0; i = reg_next_in_qty[i])
 	  reg_renumber[i] = qty_phys_reg[q] + reg_offset[i];
-	if (qty_scratch_rtx[q])
-	  {
-	    if (GET_CODE (qty_scratch_rtx[q]) == REG)
-	      abort ();
-	    qty_scratch_rtx[q] = gen_rtx_REG (GET_MODE (qty_scratch_rtx[q]),
-					      qty_phys_reg[q]);
-	    scratch_block[scratch_index] = b;
-	    scratch_list[scratch_index++] = qty_scratch_rtx[q];
-
-	  }
       }
 }
 
Index: reload.h
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/reload.h,v
retrieving revision 1.1.1.9
diff -u -r1.1.1.9 reload.h
--- reload.h	1998/05/22 12:00:49	1.1.1.9
+++ reload.h	1998/08/24 15:15:38
@@ -142,6 +142,73 @@
 extern enum insn_code reload_out_optab[];
 #endif
 
+struct needs
+{
+  /* [0] is normal, [1] is nongroup.  */
+  short regs[2][N_REG_CLASSES];
+  short groups[N_REG_CLASSES];
+};
+
+#ifdef SET_HARD_REG_BIT
+/* This structure describes instructions which are relevant for reload.  */
+struct insn_chain 
+{
+  struct insn_chain *next, *prev;
+
+  /* The basic block this insn is in.  */
+  int block;
+  /* The rtx of the insn.  */
+  rtx insn;
+  /* Register life information: For each hard register, contains either
+     -1 if the hard register is live, 0 if it is not live, or a pseudo
+     register number if a pseudo that has been allocated to this hard
+     reg is live.  This information is recorded for the point immediately
+     before the insn (in inverse_renum_before), and for the point within
+     the insn at which all outputs have just been written to (in
+     inverse_renum_after).  */
+  int inverse_renum_before[FIRST_PSEUDO_REGISTER];
+  int inverse_renum_after[FIRST_PSEUDO_REGISTER];
+
+  /* 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;
+
+  /* Indicates which registers have already been used for spills.  */
+  HARD_REG_SET used_spill_regs;
+
+  /* Describe the needs for reload registers of this insn.  */
+  struct needs need;
+
+  /* Nonzero if find_reloads said the insn requires reloading.  */
+  unsigned int need_reload:1;
+  /* Nonzero if eliminate_regs_in_insn said it requires eliminations.  */
+  unsigned int need_elim:1;
+};
+
+/* A chain of insn_chain structures to describe all non-note insns in
+   a function.  */
+extern struct insn_chain *reload_insn_chain;
+
+/* Allocate a new insn_chain structure.  */
+extern struct insn_chain *new_insn_chain PROTO((void));
+#endif
+
 /* Functions from reload.c:  */
 
 /* Return a memory location that will be used to copy X in mode MODE.  
@@ -255,4 +322,4 @@
 extern int setup_save_areas PROTO((int *));
 
 /* Find the places where hard regs are live across calls and save them.  */
-extern void save_call_clobbered_regs PROTO((enum machine_mode));
+extern void save_call_clobbered_regs PROTO((int));
Index: reload1.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/reload1.c,v
retrieving revision 1.1.1.35
diff -u -r1.1.1.35 reload1.c
--- reload1.c	1998/08/17 14:49:23	1.1.1.35
+++ reload1.c	1998/08/24 16:12:47
@@ -60,6 +60,8 @@
    available hard regs can be found.  Spilling can invalidate more
    insns, requiring additional need for reloads, so we must keep checking
    until the process stabilizes.
+   If we have register life information, it is often possible to avoid
+   spilling all the pseudos allocated to a reload register.
 
    For machines with different classes of registers, we must keep track
    of the register class needed for each reload, and make sure that
@@ -117,6 +119,9 @@
    constant or memory slot.  */
 static rtx *reg_equiv_init;
 
+/* Vector to remember old contents of reg_renumber before spilling.  */
+static short *reg_old_renumber;
+
 /* During reload_as_needed, element N contains the last pseudo regno reloaded
   into hard register N.  If that pseudo reg occupied more than one register,
    reg_reloaded_contents points to that pseudo for each spill register in
@@ -157,7 +162,12 @@
 /* This reg set indicates registers that may not be used for retrying global
    allocation.  The registers that may not be used include all spill registers
    and the frame pointer (if we are using one).  */
-HARD_REG_SET forbidden_regs;
+static HARD_REG_SET forbidden_regs;
+
+/* This vector of reg sets indicates, for each pseudo, which hard registers may
+   not be used for retrying global allocation, additionally to those in
+   forbidden_regs.  */
+static HARD_REG_SET *pseudo_forbidden_regs;
 
 /* This reg set indicates registers that are not good for spill registers.
    They will not be used to complete groups of spill registers.  This includes
@@ -176,7 +186,8 @@
 /* This reg set indicates those registers that have been used a spill
    registers.  This information is used in reorg.c, to help figure out
    what registers are live at any point.  It is assumed that all spill_regs
-   are dead at every CODE_LABEL.  */
+   are dead at every CODE_LABEL.  
+   @@@ That's a bug!  */
 
 HARD_REG_SET used_spill_regs;
 
@@ -185,28 +196,11 @@
 
 static int last_spill_reg;
 
-/* Describes order of preference for putting regs into spill_regs.
-   Contains the numbers of all the hard regs, in order most preferred first.
-   This order is different for each function.
-   It is set up by order_regs_for_reload.
-   Empty elements at the end contain -1.  */
-static short potential_reload_regs[FIRST_PSEUDO_REGISTER];
-
 /* 1 for a hard register that appears explicitly in the rtl
    (for example, function value registers, special registers
    used by insns, structure value pointer registers).  */
 static char regs_explicitly_used[FIRST_PSEUDO_REGISTER];
 
-/* Indicates if a register was counted against the need for
-   groups.  0 means it can count against max_nongroup instead.  */
-static HARD_REG_SET counted_for_groups;
-
-/* Indicates if a register was counted against the need for
-   non-groups.  0 means it can become part of a new group.
-   During choose_reload_regs, 1 here means don't use this reg
-   as part of a group, even if it seems to be otherwise ok.  */
-static HARD_REG_SET counted_for_nongroups;
-
 /* Nonzero if indirect addressing is supported on the machine; this means
    that spilling (REG n) does not require reloading it into a register in
    order to do (MEM (REG n)) or (MEM (PLUS (REG n) (CONST_INT c))).  The
@@ -234,12 +228,9 @@
 
 static int spill_stack_slot_width[FIRST_PSEUDO_REGISTER];
 
-/* Indexed by register class and basic block number, nonzero if there is
-   any need for a spill register of that class in that basic block.
-   The pointer is 0 if we did stupid allocation and don't know
-   the structure of basic blocks.  */
+/* Record which pseudos needed to be spilled.  */
 
-char *basic_block_needs[N_REG_CLASSES];
+static regset spilled_pseudos;
 
 /* First uid used by insns created by reload in this function.
    Used in find_equiv_reg.  */
@@ -267,6 +258,10 @@
 
 int reload_in_progress = 0;
 
+/* Nonzero means we couldn't get enough spill regs.  */
+static int failure;
+
+
 /* These arrays record the insn_code of insns that may be needed to
    perform input and output reloads of special objects.  They provide a
    place to pass a scratch register.  */
@@ -280,6 +275,7 @@
 
 struct obstack reload_obstack;
 char *reload_firstobj;
+char *reload_startobj;
 
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
@@ -289,6 +285,8 @@
 
 /* Allocation number table from global register allocation.  */
 extern int *reg_allocno;
+
+struct insn_chain *reload_insn_chain;
 
 /* This structure is used to record information about register eliminations.
    Each array entry describes one possible way of eliminating a register
@@ -349,28 +347,28 @@
 
 static int num_labels;
 
-struct hard_reg_n_uses { int regno; int uses; };
 
-static int possible_group_p		PROTO((int, int *));
-static void count_possible_groups	PROTO((int *, enum machine_mode *,
-					       int *, int));
+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 spill_failure		PROTO((rtx));
-static int new_spill_reg		PROTO((int, int, int *, int *, int,
+static void new_spill_reg		PROTO((struct insn_chain *, int, int,
+					       int, FILE *));
+static void find_reload_regs		PROTO((struct insn_chain *chain, int,
 					       FILE *));
+static int finish_spills		PROTO((int, FILE *));
+static void spill_caller_saved_regs	PROTO((void));
 static void delete_dead_insn		PROTO((rtx));
 static void alter_reg  			PROTO((int, int));
-static void mark_scratch_live		PROTO((rtx));
 static void set_label_offsets		PROTO((rtx, rtx, int));
 static int eliminate_regs_in_insn	PROTO((rtx, int));
 static void mark_not_eliminable		PROTO((rtx, rtx));
-static int spill_hard_reg		PROTO((int, int, FILE *, int));
+static void spill_hard_reg		PROTO((int, FILE *, int));
 static void scan_paradoxical_subregs	PROTO((rtx));
 static int hard_reg_use_compare		PROTO((const GENERIC_PTR, const GENERIC_PTR));
-static void order_regs_for_reload	PROTO((int));
-static int compare_spill_regs		PROTO((const GENERIC_PTR, const GENERIC_PTR));
+static void order_regs_for_reload	PROTO((struct insn_chain *, int));
 static void reload_as_needed		PROTO((rtx, int));
 static void forget_old_reloads_1	PROTO((rtx, rtx));
 static int reload_reg_class_lower	PROTO((const GENERIC_PTR, const GENERIC_PTR));
@@ -382,8 +380,9 @@
 static int reload_reg_free_before_p	PROTO((int, int, enum reload_type));
 static int reload_reg_free_for_value_p	PROTO((int, int, enum reload_type, rtx, rtx, int));
 static int reload_reg_reaches_end_p	PROTO((int, int, enum reload_type));
-static int allocate_reload_reg		PROTO((int, rtx, int, int));
-static void choose_reload_regs		PROTO((rtx, rtx));
+static int allocate_reload_reg		PROTO((struct insn_chain *, int, int,
+					       int));
+static void choose_reload_regs		PROTO((struct insn_chain *, int));
 static void merge_assigned_reloads	PROTO((rtx));
 static void emit_reload_insns		PROTO((rtx));
 static void delete_output_reload	PROTO((rtx, int, rtx));
@@ -450,65 +449,23 @@
 
   /* Initialize obstack for our rtl allocation.  */
   gcc_obstack_init (&reload_obstack);
-  reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+  reload_startobj = (char *) obstack_alloc (&reload_obstack, 0);
 
-  /* Decide which register class should be used when reloading
-     addresses.  If we are using SMALL_REGISTER_CLASSES, and any
-     parameters are passed in registers, then we do not want to use
-     those registers when reloading an address.  Otherwise, if a
-     function argument needs a reload, we may wind up clobbering
-     another argument to the function which was already computed.  If
-     we find a subset class which simply avoids those registers, we
-     use it instead.  ??? It would be better to only use the
-     restricted class when we actually are loading function arguments,
-     but that is hard to determine.  */
   reload_address_base_reg_class = BASE_REG_CLASS;
   reload_address_index_reg_class = INDEX_REG_CLASS;
-  if (SMALL_REGISTER_CLASSES)
-    {
-      int regno;
-      HARD_REG_SET base, index;
-      enum reg_class *p;
+}
 
-      COPY_HARD_REG_SET (base, reg_class_contents[BASE_REG_CLASS]);
-      COPY_HARD_REG_SET (index, reg_class_contents[INDEX_REG_CLASS]);
-      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-	{
-	  if (FUNCTION_ARG_REGNO_P (regno))
-	    {
-	      CLEAR_HARD_REG_BIT (base, regno);
-	      CLEAR_HARD_REG_BIT (index, regno);
-	    }
-	}
-      
-      GO_IF_HARD_REG_EQUAL (base, reg_class_contents[BASE_REG_CLASS],
-			    baseok);
-      for (p = reg_class_subclasses[BASE_REG_CLASS];
-	   *p != LIM_REG_CLASSES;
-	   p++)
-	{
-	  GO_IF_HARD_REG_EQUAL (base, reg_class_contents[*p], usebase);
-	  continue;
-	usebase:
-	  reload_address_base_reg_class = *p;
-	  break;
-	}
-    baseok:;
+/* Allocate an empty insn_chain structure.  */
+struct insn_chain *
+new_insn_chain ()
+{
+  struct insn_chain *c;
 
-      GO_IF_HARD_REG_EQUAL (index, reg_class_contents[INDEX_REG_CLASS],
-			    indexok);
-      for (p = reg_class_subclasses[INDEX_REG_CLASS];
-	   *p != LIM_REG_CLASSES;
-	   p++)
-	{
-	  GO_IF_HARD_REG_EQUAL (index, reg_class_contents[*p], useindex);
-	  continue;
-	useindex:
-	  reload_address_index_reg_class = *p;
-	  break;
-	}
-    indexok:;
-    }
+  c = obstack_alloc (&reload_obstack, sizeof (struct insn_chain));
+  reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+  c->need_reload = 0;
+  c->need_elim = 0;
+  return c;
 }
 
 /* Main entry point for the reload pass.
@@ -548,25 +505,19 @@
   int something_changed;
   int something_needs_reloads;
   int something_needs_elimination;
-  int new_basic_block_needs;
-  enum reg_class caller_save_spill_class = NO_REGS;
-  int caller_save_group_size = 1;
-
-  /* Nonzero means we couldn't get enough spill regs.  */
-  int failure = 0;
 
-  /* The basic block number currently being processed for INSN.  */
-  int this_block;
-
   /* Make sure even insns with volatile mem refs are recognizable.  */
   init_recog ();
 
+  reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+
+  spilled_pseudos = ALLOCA_REG_SET ();
+
   /* Enable find_equiv_reg to distinguish insns made by reload.  */
   reload_first_uid = get_max_uid ();
 
-  for (i = 0; i < N_REG_CLASSES; i++)
-    basic_block_needs[i] = 0;
-
+  failure = 0;
+  
 #ifdef SECONDARY_MEMORY_NEEDED
   /* Initialize the secondary memory table.  */
   clear_secondary_mem ();
@@ -601,10 +552,6 @@
 	  regs_ever_live[i] = 1;
       }
 
-  for (i = 0; i < scratch_list_length; i++)
-    if (scratch_list[i])
-      mark_scratch_live (scratch_list[i]);
-
   /* Make sure that the last insn in the chain
      is not something that needs reloading.  */
   emit_note (NULL_PTR, NOTE_INSN_DELETED);
@@ -631,6 +578,10 @@
   bzero ((char *) reg_equiv_address, max_regno * sizeof (rtx));
   reg_max_ref_width = (int *) alloca (max_regno * sizeof (int));
   bzero ((char *) reg_max_ref_width, max_regno * sizeof (int));
+  reg_old_renumber = (short *) alloca (max_regno * sizeof (short));
+  bcopy (reg_renumber, reg_old_renumber, max_regno * sizeof (short));
+  pseudo_forbidden_regs
+    = (HARD_REG_SET *) alloca (max_regno * sizeof (HARD_REG_SET));
 
   if (SMALL_REGISTER_CLASSES)
     CLEAR_HARD_REG_SET (forbidden_regs);
@@ -803,43 +754,21 @@
     }
 #endif
 
-  /* Compute the order of preference for hard registers to spill.
-     Store them by decreasing preference in potential_reload_regs.  */
-
-  order_regs_for_reload (global);
-
-  /* So far, no hard regs have been spilled.  */
-  n_spills = 0;
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    spill_reg_order[i] = -1;
-
   /* Initialize to -1, which means take the first spill register.  */
   last_spill_reg = -1;
 
-  /* On most machines, we can't use any register explicitly used in the
-     rtl as a spill register.  But on some, we have to.  Those will have
-     taken care to keep the life of hard regs as short as possible.  */
-
-  if (! SMALL_REGISTER_CLASSES)
-    COPY_HARD_REG_SET (forbidden_regs, bad_spill_regs);
-
   /* Spill any hard regs that we know we can't eliminate.  */
+  CLEAR_HARD_REG_SET (used_spill_regs);
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     if (! ep->can_eliminate)
-      spill_hard_reg (ep->from, global, dumpfile, 1);
+      spill_hard_reg (ep->from, dumpfile, 1);
 
 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
   if (frame_pointer_needed)
-    spill_hard_reg (HARD_FRAME_POINTER_REGNUM, global, dumpfile, 1);
+    spill_hard_reg (HARD_FRAME_POINTER_REGNUM, dumpfile, 1);
 #endif
+  finish_spills (global, dumpfile);
 
-  if (global)
-    for (i = 0; i < N_REG_CLASSES; i++)
-      {
-	basic_block_needs[i] = (char *) alloca (n_basic_blocks);
-	bzero (basic_block_needs[i], n_basic_blocks);
-      }
-
   /* From now on, we need to emit any moves without making new pseudos.  */
   reload_in_progress = 1;
 
@@ -858,31 +787,8 @@
   something_needs_elimination = 0;
   while (something_changed)
     {
-      rtx after_call = 0;
+      struct insn_chain *chain;
 
-      /* For each class, number of reload regs needed in that class.
-	 This is the maximum over all insns of the needs in that class
-	 of the individual insn.  */
-      int max_needs[N_REG_CLASSES];
-      /* For each class, size of group of consecutive regs
-	 that is needed for the reloads of this class.  */
-      int group_size[N_REG_CLASSES];
-      /* For each class, max number of consecutive groups needed.
-	 (Each group contains group_size[CLASS] consecutive registers.)  */
-      int max_groups[N_REG_CLASSES];
-      /* For each class, max number needed of regs that don't belong
-	 to any of the groups.  */
-      int max_nongroups[N_REG_CLASSES];
-      /* For each class, the machine mode which requires consecutive
-	 groups of regs of that class.
-	 If two different modes ever require groups of one class,
-	 they must be the same size and equally restrictive for that class,
-	 otherwise we can't handle the complexity.  */
-      enum machine_mode group_mode[N_REG_CLASSES];
-      /* Record the insn where each maximum need is first found.  */
-      rtx max_needs_insn[N_REG_CLASSES];
-      rtx max_groups_insn[N_REG_CLASSES];
-      rtx max_nongroups_insn[N_REG_CLASSES];
       rtx x;
       HOST_WIDE_INT starting_frame_size;
 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
@@ -891,22 +797,6 @@
       static char *reg_class_names[] = REG_CLASS_NAMES;
 
       something_changed = 0;
-      bzero ((char *) max_needs, sizeof max_needs);
-      bzero ((char *) max_groups, sizeof max_groups);
-      bzero ((char *) max_nongroups, sizeof max_nongroups);
-      bzero ((char *) max_needs_insn, sizeof max_needs_insn);
-      bzero ((char *) max_groups_insn, sizeof max_groups_insn);
-      bzero ((char *) max_nongroups_insn, sizeof max_nongroups_insn);
-      bzero ((char *) group_size, sizeof group_size);
-      for (i = 0; i < N_REG_CLASSES; i++)
-	group_mode[i] = VOIDmode;
-
-      /* Keep track of which basic blocks are needing the reloads.  */
-      this_block = 0;
-
-      /* Remember whether any element of basic_block_needs
-	 changes from 0 to 1 in this pass.  */
-      new_basic_block_needs = 0;
 
       /* Round size of stack frame to BIGGEST_ALIGNMENT.  This must be done
 	 here because the stack size may be a part of the offset computation
@@ -1010,23 +900,13 @@
       if (something_changed)
 	continue;
 
-      /* If caller-saves needs a group, initialize the group to include
-	 the size and mode required for caller-saves.  */
-
-      if (caller_save_group_size > 1)
-	{
-	  group_mode[(int) caller_save_spill_class] = Pmode;
-	  group_size[(int) caller_save_spill_class] = caller_save_group_size;
-	}
-
       /* Compute the most additional registers needed by any instruction.
 	 Collect information separately for each class of regs.  */
 
-      for (insn = first; insn; insn = NEXT_INSN (insn))
+      for (chain = reload_insn_chain; chain; chain = chain->next)
 	{
-	  if (global && this_block + 1 < n_basic_blocks
-	      && insn == basic_block_head[this_block+1])
-	    ++this_block;
+	  rtx insn = chain->insn;
+	  int this_block = chain->block;
 
 	  /* If this is a label, a JUMP_INSN, or has REG_NOTES (which
 	     might include REG_LABEL), we need to see what effects this
@@ -1039,10 +919,6 @@
 
 	  if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
 	    {
-	      /* Nonzero means don't use a reload reg that overlaps
-		 the place where a function value can be returned.  */
-	      rtx avoid_return_reg = 0;
-
 	      rtx old_body = PATTERN (insn);
 	      int old_code = INSN_CODE (insn);
  	      rtx old_notes = REG_NOTES (insn);
@@ -1066,13 +942,6 @@
 		 The total number of registers needed is the maximum of the
 		 inputs and outputs.  */
 
-	      struct needs
-		{
-		  /* [0] is normal, [1] is nongroup.  */
-		  int regs[2][N_REG_CLASSES];
-		  int groups[N_REG_CLASSES];
-		};
-
 	      /* Each `struct needs' corresponds to one RELOAD_... type.  */
 	      struct {
 		struct needs other;
@@ -1092,51 +961,15 @@
 	      if (num_eliminable)
 		did_elimination = eliminate_regs_in_insn (insn, 0);
 
-	      /* Set avoid_return_reg if this is an insn
-		 that might use the value of a function call.  */
-	      if (SMALL_REGISTER_CLASSES && GET_CODE (insn) == CALL_INSN)
-		{
-		  if (GET_CODE (PATTERN (insn)) == SET)
-		    after_call = SET_DEST (PATTERN (insn));
-		  else if (GET_CODE (PATTERN (insn)) == PARALLEL
-			   && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
-		    after_call = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
-		  else
-		    after_call = 0;
-		}
-	      else if (SMALL_REGISTER_CLASSES && after_call != 0
-		       && !(GET_CODE (PATTERN (insn)) == SET
-			    && SET_DEST (PATTERN (insn)) == stack_pointer_rtx)
-		       && GET_CODE (PATTERN (insn)) != USE)
-		{
-		  if (reg_referenced_p (after_call, PATTERN (insn)))
-		    avoid_return_reg = after_call;
-		  after_call = 0;
-		}
-
 	      /* Analyze the instruction.  */
 	      find_reloads (insn, 0, spill_indirect_levels, global,
 			    spill_reg_order);
 
 	      /* Remember for later shortcuts which insns had any reloads or
-		 register eliminations.
+		 register eliminations.  */
+	      chain->need_elim = did_elimination;
+	      chain->need_reload = n_reloads > 0;
 
-		 One might think that it would be worthwhile to mark insns
-		 that need register replacements but not reloads, but this is
-		 not safe because find_reloads may do some manipulation of
-		 the insn (such as swapping commutative operands), which would
-		 be lost when we restore the old pattern after register
-		 replacement.  So the actions of find_reloads must be redone in
-		 subsequent passes or in reload_as_needed.
-
-		 However, it is safe to mark insns that need reloads
-		 but not register replacement.  */
-
-	      PUT_MODE (insn, (did_elimination ? QImode
-			       : n_reloads ? HImode
-			       : GET_MODE (insn) == DImode ? DImode
-			       : VOIDmode));
-
 	      /* Discard any register replacements done.  */
 	      if (did_elimination)
 		{
@@ -1147,16 +980,15 @@
 		  something_needs_elimination = 1;
 		}
 
-	      /* If this insn has no reloads, we need not do anything except
-		 in the case of a CALL_INSN when we have caller-saves and
-		 caller-save needs reloads.  */
-
-	      if (n_reloads == 0
-		  && ! (GET_CODE (insn) == CALL_INSN
-			&& caller_save_spill_class != NO_REGS))
+	      /* If this insn has no reloads, we need not do anything.  */
+	      if (n_reloads == 0)
 		continue;
 
 	      something_needs_reloads = 1;
+
+	      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
@@ -1180,16 +1012,6 @@
 			  && ! reload_secondary_p[i]))
   		    continue;
 
-		  /* Show that a reload register of this class is needed
-		     in this basic block.  We do not use insn_needs and
-		     insn_groups because they are overly conservative for
-		     this purpose.  */
-		  if (global && ! basic_block_needs[(int) class][this_block])
-		    {
-		      basic_block_needs[(int) class][this_block] = 1;
-		      new_basic_block_needs = 1;
-		    }
-
 		  mode = reload_inmode[i];
 		  if (GET_MODE_SIZE (reload_outmode[i]) > GET_MODE_SIZE (mode))
 		    mode = reload_outmode[i];
@@ -1247,18 +1069,18 @@
 		      /* Record size and mode of a group of this class.  */
 		      /* If more than one size group is needed,
 			 make all groups the largest needed size.  */
-		      if (group_size[(int) class] < size)
+		      if (chain->group_size[(int) class] < size)
 			{
-			  other_mode = group_mode[(int) class];
+			  other_mode = chain->group_mode[(int) class];
 			  allocate_mode = mode;
 
-			  group_size[(int) class] = size;
-			  group_mode[(int) class] = mode;
+			  chain->group_size[(int) class] = size;
+			  chain->group_mode[(int) class] = mode;
 			}
 		      else
 			{
 			  other_mode = mode;
-			  allocate_mode = group_mode[(int) class];
+			  allocate_mode = chain->group_mode[(int) class];
 			}
 
 		      /* Crash if two dissimilar machine modes both need
@@ -1363,164 +1185,9 @@
 				 insn_needs.output.groups[i]),
 			    insn_needs.other_addr.groups[i]);
 		}
-
-	      /* If this is a CALL_INSN and caller-saves will need
-		 a spill register, act as if the spill register is
-		 needed for this insn.   However, the spill register
-		 can be used by any reload of this insn, so we only
-		 need do something if no need for that class has
-		 been recorded.
-
-		 The assumption that every CALL_INSN will trigger a
-		 caller-save is highly conservative, however, the number
-		 of cases where caller-saves will need a spill register but
-		 a block containing a CALL_INSN won't need a spill register
-		 of that class should be quite rare.
 
-		 If a group is needed, the size and mode of the group will
-		 have been set up at the beginning of this loop.  */
-
-	      if (GET_CODE (insn) == CALL_INSN
-		  && caller_save_spill_class != NO_REGS)
-		{
-		  /* See if this register would conflict with any reload that
-		     needs a group or any reload that needs a nongroup.  */
-		  int nongroup_need = 0;
-		  int *caller_save_needs;
-
-		  for (j = 0; j < n_reloads; j++)
-		    if (reg_classes_intersect_p (caller_save_spill_class,
-						 reload_reg_class[j])
-			&& ((CLASS_MAX_NREGS
-			     (reload_reg_class[j],
-			      (GET_MODE_SIZE (reload_outmode[j])
-			       > GET_MODE_SIZE (reload_inmode[j]))
-			      ? reload_outmode[j] : reload_inmode[j])
-			     > 1)
-			    || reload_nongroup[j]))
-		      {
-			nongroup_need = 1;
-			break;
-		      }
-
-		  caller_save_needs 
-		    = (caller_save_group_size > 1
-		       ? insn_needs.other.groups
-		       : insn_needs.other.regs[nongroup_need]); 
-
-		  if (caller_save_needs[(int) caller_save_spill_class] == 0)
-		    {
-		      register enum reg_class *p
-			= reg_class_superclasses[(int) caller_save_spill_class];
-
-		      caller_save_needs[(int) caller_save_spill_class]++;
-
-		      while (*p != LIM_REG_CLASSES)
-			caller_save_needs[(int) *p++] += 1;
-		    }
-
-		  /* Show that this basic block will need a register of
-                   this class.  */
-
-		  if (global
-		      && ! (basic_block_needs[(int) caller_save_spill_class]
-			    [this_block]))
-		    {
-		      basic_block_needs[(int) caller_save_spill_class]
-			[this_block] = 1;
-		      new_basic_block_needs = 1;
-		    }
-		}
-
-	      /* If this insn stores the value of a function call,
-		 and that value is in a register that has been spilled,
-		 and if the insn needs a reload in a class
-		 that might use that register as the reload register,
-		 then add an extra need in that class.
-		 This makes sure we have a register available that does
-		 not overlap the return value.  */
-
-	      if (SMALL_REGISTER_CLASSES && avoid_return_reg)
-		{
-		  int regno = REGNO (avoid_return_reg);
-		  int nregs
-		    = HARD_REGNO_NREGS (regno, GET_MODE (avoid_return_reg));
-		  int r;
-		  int basic_needs[N_REG_CLASSES], basic_groups[N_REG_CLASSES];
-
-		  /* First compute the "basic needs", which counts a
-		     need only in the smallest class in which it
-		     is required.  */
-
-		  bcopy ((char *) insn_needs.other.regs[0],
-			 (char *) basic_needs, sizeof basic_needs);
-		  bcopy ((char *) insn_needs.other.groups,
-			 (char *) basic_groups, sizeof basic_groups);
-
-		  for (i = 0; i < N_REG_CLASSES; i++)
-		    {
-		      enum reg_class *p;
-
-		      if (basic_needs[i] >= 0)
-			for (p = reg_class_superclasses[i];
-			     *p != LIM_REG_CLASSES; p++)
-			  basic_needs[(int) *p] -= basic_needs[i];
-
-		      if (basic_groups[i] >= 0)
-			for (p = reg_class_superclasses[i];
-			     *p != LIM_REG_CLASSES; p++)
-			  basic_groups[(int) *p] -= basic_groups[i];
-		    }
-
-		  /* Now count extra regs if there might be a conflict with
-		     the return value register.  */
-
-		  for (r = regno; r < regno + nregs; r++)
-		    if (spill_reg_order[r] >= 0)
-		      for (i = 0; i < N_REG_CLASSES; i++)
-			if (TEST_HARD_REG_BIT (reg_class_contents[i], r))
-			  {
-			    if (basic_needs[i] > 0)
-			      {
-				enum reg_class *p;
-
-				insn_needs.other.regs[0][i]++;
-				p = reg_class_superclasses[i];
-				while (*p != LIM_REG_CLASSES)
-				  insn_needs.other.regs[0][(int) *p++]++;
-			      }
-			    if (basic_groups[i] > 0)
-			      {
-				enum reg_class *p;
-
-				insn_needs.other.groups[i]++;
-				p = reg_class_superclasses[i];
-				while (*p != LIM_REG_CLASSES)
-				  insn_needs.other.groups[(int) *p++]++;
-			      }
-			  }
-		}
-
-	      /* For each class, collect maximum need of any insn.  */
-
-	      for (i = 0; i < N_REG_CLASSES; i++)
-		{
-		  if (max_needs[i] < insn_needs.other.regs[0][i])
-		    {
-		      max_needs[i] = insn_needs.other.regs[0][i];
-		      max_needs_insn[i] = insn;
-		    }
-		  if (max_groups[i] < insn_needs.other.groups[i])
-		    {
-		      max_groups[i] = insn_needs.other.groups[i];
-		      max_groups_insn[i] = insn;
-		    }
-		  if (max_nongroups[i] < insn_needs.other.regs[1][i])
-		    {
-		      max_nongroups[i] = insn_needs.other.regs[1][i];
-		      max_nongroups_insn[i] = insn;
-		    }
-		}
+	      /* Record the needs for later.  */
+	      chain->need = insn_needs.other;
 	    }
 	  /* Note that there is a continue statement above.  */
 	}
@@ -1530,27 +1197,6 @@
       if (starting_frame_size != get_frame_size ())
 	something_changed = 1;
 
-      if (dumpfile)
-	for (i = 0; i < N_REG_CLASSES; i++)
-	  {
-	    if (max_needs[i] > 0)
-	      fprintf (dumpfile,
-			 ";; Need %d reg%s of class %s (for insn %d).\n",
-		       max_needs[i], max_needs[i] == 1 ? "" : "s",
-		       reg_class_names[i], INSN_UID (max_needs_insn[i]));
-	    if (max_nongroups[i] > 0)
-	      fprintf (dumpfile,
-		       ";; Need %d nongroup reg%s of class %s (for insn %d).\n",
-		       max_nongroups[i], max_nongroups[i] == 1 ? "" : "s",
-		       reg_class_names[i], INSN_UID (max_nongroups_insn[i]));
-	    if (max_groups[i] > 0)
-	      fprintf (dumpfile,
-		       ";; Need %d group%s (%smode) of class %s (for insn %d).\n",
-		       max_groups[i], max_groups[i] == 1 ? "" : "s",
-		       mode_name[(int) group_mode[i]],
-		       reg_class_names[i], INSN_UID (max_groups_insn[i]));
-	  }
-			 
       /* If we have caller-saves, set up the save areas and see if caller-save
 	 will need a spill register.  */
 
@@ -1561,18 +1207,11 @@
 	       ep++)
 	    ep->previous_offset = ep->max_offset;
 
-	  if ( ! setup_save_areas (&something_changed)
-	      && caller_save_spill_class  == NO_REGS)
+	  if (! setup_save_areas (&something_changed))
 	    {
-	      /* The class we will need depends on whether the machine
-		 supports the sum of two registers for an address; see
-	      find_address_reloads for details.  */
-
-	      caller_save_spill_class
-		= double_reg_address_ok ? INDEX_REG_CLASS : BASE_REG_CLASS;
-	      caller_save_group_size
-		= CLASS_MAX_NREGS (caller_save_spill_class, Pmode);
+	      spill_caller_saved_regs ();
 	      something_changed = 1;
+	      caller_save_needed = 0;
 	    }
 	}
 
@@ -1629,6 +1268,7 @@
 	 registers and see if the frame pointer is needed; it is if there is
 	 no elimination of the frame pointer that we can perform.  */
 
+      CLEAR_REG_SET (spilled_pseudos);
       frame_pointer_needed = 1;
       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
 	{
@@ -1639,7 +1279,7 @@
 	  if (! ep->can_eliminate && ep->can_eliminate_previous)
 	    {
 	      ep->can_eliminate_previous = 0;
-	      spill_hard_reg (ep->from, global, dumpfile, 1);
+	      spill_hard_reg (ep->from, dumpfile, 1);
 	      something_changed = 1;
 	      num_eliminable--;
 	    }
@@ -1650,357 +1290,25 @@
 	 the hard frame pointer.  */
       if (frame_pointer_needed && ! previous_frame_pointer_needed)
 	{
-	  spill_hard_reg (HARD_FRAME_POINTER_REGNUM, global, dumpfile, 1);
+	  spill_hard_reg (HARD_FRAME_POINTER_REGNUM, dumpfile, 1);
 	  something_changed = 1;
 	}
 #endif
-
-      /* If all needs are met, we win.  */
 
-      for (i = 0; i < N_REG_CLASSES; i++)
-	if (max_needs[i] > 0 || max_groups[i] > 0 || max_nongroups[i] > 0)
-	  break;
-      if (i == N_REG_CLASSES && !new_basic_block_needs && ! something_changed)
+      /* Short cut for functions that don't need reloading.  */
+      if (! something_changed && ! something_needs_reloads)
 	break;
-
-      /* Not all needs are met; must spill some hard regs.  */
-
-      /* Put all registers spilled so far back in potential_reload_regs, but
-	 put them at the front, since we've already spilled most of the
-	 pseudos in them (we might have left some pseudos unspilled if they
-	 were in a block that didn't need any spill registers of a conflicting
-	 class.  We used to try to mark off the need for those registers,
-	 but doing so properly is very complex and reallocating them is the
-	 simpler approach.  First, "pack" potential_reload_regs by pushing 
-	 any nonnegative entries towards the end.  That will leave room 
-	 for the registers we already spilled.
-
-	 Also, undo the marking of the spill registers from the last time
-	 around in FORBIDDEN_REGS since we will be probably be allocating
-	 them again below.
-
-	 ??? It is theoretically possible that we might end up not using one
-	 of our previously-spilled registers in this allocation, even though
-	 they are at the head of the list.  It's not clear what to do about
-	 this, but it was no better before, when we marked off the needs met
-	 by the previously-spilled registers.  With the current code, globals
-	 can be allocated into these registers, but locals cannot.  */
-
-      if (n_spills)
-	{
-	  for (i = j = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
-	    if (potential_reload_regs[i] != -1)
-	      potential_reload_regs[j--] = potential_reload_regs[i];
-
-	  for (i = 0; i < n_spills; i++)
-	    {
-	      potential_reload_regs[i] = spill_regs[i];
-	      spill_reg_order[spill_regs[i]] = -1;
-	      CLEAR_HARD_REG_BIT (forbidden_regs, spill_regs[i]);
-	    }
-
-	  n_spills = 0;
-	}
-
-      /* Now find more reload regs to satisfy the remaining need
-	 Do it by ascending class number, since otherwise a reg
-	 might be spilled for a big class and might fail to count
-	 for a smaller class even though it belongs to that class.
-
-	 Count spilled regs in `spills', and add entries to
-	 `spill_regs' and `spill_reg_order'.
-
-	 ??? 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.  */
-
-      CLEAR_HARD_REG_SET (counted_for_groups);
-      CLEAR_HARD_REG_SET (counted_for_nongroups);
-
-      for (class = 0; class < N_REG_CLASSES; class++)
-	{
-	  /* First get the groups of registers.
-	     If we got single registers first, we might fragment
-	     possible groups.  */
-	  while (max_groups[class] > 0)
-	    {
-	      /* If any single spilled regs happen to form groups,
-		 count them now.  Maybe we don't really need
-		 to spill another group.  */
-	      count_possible_groups (group_size, group_mode, max_groups,
-				     class);
-
-	      if (max_groups[class] <= 0)
-		break;
-
-	      /* Groups of size 2 (the only groups used on most machines)
-		 are treated specially.  */
-	      if (group_size[class] == 2)
-		{
-		  /* First, look for a register that will complete a group.  */
-		  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-		    {
-		      int other;
-
-		      j = potential_reload_regs[i];
-		      if (j >= 0 && ! TEST_HARD_REG_BIT (bad_spill_regs, j)
-			  &&
-			  ((j > 0 && (other = j - 1, spill_reg_order[other] >= 0)
-			    && TEST_HARD_REG_BIT (reg_class_contents[class], j)
-			    && TEST_HARD_REG_BIT (reg_class_contents[class], other)
-			    && HARD_REGNO_MODE_OK (other, group_mode[class])
-			    && ! TEST_HARD_REG_BIT (counted_for_nongroups,
-						    other)
-			    /* We don't want one part of another group.
-			       We could get "two groups" that overlap!  */
-			    && ! TEST_HARD_REG_BIT (counted_for_groups, other))
-			   ||
-			   (j < FIRST_PSEUDO_REGISTER - 1
-			    && (other = j + 1, spill_reg_order[other] >= 0)
-			    && TEST_HARD_REG_BIT (reg_class_contents[class], j)
-			    && TEST_HARD_REG_BIT (reg_class_contents[class], other)
-			    && HARD_REGNO_MODE_OK (j, group_mode[class])
-			    && ! TEST_HARD_REG_BIT (counted_for_nongroups,
-						    other)
-			    && ! TEST_HARD_REG_BIT (counted_for_groups,
-						    other))))
-			{
-			  register enum reg_class *p;
-
-			  /* We have found one that will complete a group,
-			     so count off one group as provided.  */
-			  max_groups[class]--;
-			  p = reg_class_superclasses[class];
-			  while (*p != LIM_REG_CLASSES)
-			    {
-			      if (group_size [(int) *p] <= group_size [class])
-				max_groups[(int) *p]--;
-			      p++;
-			    }
-
-			  /* Indicate both these regs are part of a group.  */
-			  SET_HARD_REG_BIT (counted_for_groups, j);
-			  SET_HARD_REG_BIT (counted_for_groups, other);
-			  break;
-			}
-		    }
-		  /* We can't complete a group, so start one.  */
-		  /* Look for a pair neither of which is explicitly used.  */
-		  if (SMALL_REGISTER_CLASSES && i == FIRST_PSEUDO_REGISTER)
-		    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-		      {
-			int k;
-			j = potential_reload_regs[i];
-			/* Verify that J+1 is a potential reload reg.  */
-			for (k = 0; k < FIRST_PSEUDO_REGISTER; k++)
-			  if (potential_reload_regs[k] == j + 1)
-			    break;
-			if (j >= 0 && j + 1 < FIRST_PSEUDO_REGISTER
-			    && k < FIRST_PSEUDO_REGISTER
-			    && spill_reg_order[j] < 0 && spill_reg_order[j + 1] < 0
-			    && TEST_HARD_REG_BIT (reg_class_contents[class], j)
-			    && TEST_HARD_REG_BIT (reg_class_contents[class], j + 1)
-			    && HARD_REGNO_MODE_OK (j, group_mode[class])
-			    && ! TEST_HARD_REG_BIT (counted_for_nongroups,
-						    j + 1)
-			    && ! TEST_HARD_REG_BIT (bad_spill_regs, j + 1)
-			    /* Reject J at this stage
-			       if J+1 was explicitly used.  */
-			    && ! regs_explicitly_used[j + 1])
-			  break;
-		      }
-		  /* Now try any group at all
-		     whose registers are not in bad_spill_regs.  */
-		  if (i == FIRST_PSEUDO_REGISTER)
-		    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-		      {
-			int k;
-			j = potential_reload_regs[i];
-			/* Verify that J+1 is a potential reload reg.  */
-			for (k = 0; k < FIRST_PSEUDO_REGISTER; k++)
-			  if (potential_reload_regs[k] == j + 1)
-			    break;
-			if (j >= 0 && j + 1 < FIRST_PSEUDO_REGISTER
-			    && k < FIRST_PSEUDO_REGISTER
-			    && spill_reg_order[j] < 0 && spill_reg_order[j + 1] < 0
-			    && TEST_HARD_REG_BIT (reg_class_contents[class], j)
-			    && TEST_HARD_REG_BIT (reg_class_contents[class], j + 1)
-			    && HARD_REGNO_MODE_OK (j, group_mode[class])
-			    && ! TEST_HARD_REG_BIT (counted_for_nongroups,
-						    j + 1)
-			    && ! TEST_HARD_REG_BIT (bad_spill_regs, j + 1))
-			  break;
-		      }
-
-		  /* I should be the index in potential_reload_regs
-		     of the new reload reg we have found.  */
-
-		  if (i >= FIRST_PSEUDO_REGISTER)
-		    {
-		      /* There are no groups left to spill.  */
-		      spill_failure (max_groups_insn[class]);
-		      failure = 1;
-		      goto failed;
-		    }
-		  else
-		    something_changed
-		      |= new_spill_reg (i, class, max_needs, NULL_PTR,
-					global, dumpfile);
-		}
-	      else
-		{
-		  /* For groups of more than 2 registers,
-		     look for a sufficient sequence of unspilled registers,
-		     and spill them all at once.  */
-		  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-		    {
-		      int k;
 
-		      j = potential_reload_regs[i];
-		      if (j >= 0
-			  && j + group_size[class] <= FIRST_PSEUDO_REGISTER
-			  && HARD_REGNO_MODE_OK (j, group_mode[class]))
-			{
-			  /* Check each reg in the sequence.  */
-			  for (k = 0; k < group_size[class]; k++)
-			    if (! (spill_reg_order[j + k] < 0
-				   && ! TEST_HARD_REG_BIT (bad_spill_regs, j + k)
-				   && TEST_HARD_REG_BIT (reg_class_contents[class], j + k)))
-			      break;
-			  /* We got a full sequence, so spill them all.  */
-			  if (k == group_size[class])
-			    {
-			      register enum reg_class *p;
-			      for (k = 0; k < group_size[class]; k++)
-				{
-				  int idx;
-				  SET_HARD_REG_BIT (counted_for_groups, j + k);
-				  for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
-				    if (potential_reload_regs[idx] == j + k)
-				      break;
-				  something_changed
-				    |= new_spill_reg (idx, class,
-						      max_needs, NULL_PTR,
-						      global, dumpfile);
-				}
-
-			      /* We have found one that will complete a group,
-				 so count off one group as provided.  */
-			      max_groups[class]--;
-			      p = reg_class_superclasses[class];
-			      while (*p != LIM_REG_CLASSES)
-				{
-				  if (group_size [(int) *p]
-				      <= group_size [class])
-				    max_groups[(int) *p]--;
-				  p++;
-				}
-			      break;
-			    }
-			}
-		    }
-		  /* We couldn't find any registers for this reload.
-		     Avoid going into an infinite loop.  */
-		  if (i >= FIRST_PSEUDO_REGISTER)
-		    {
-		      /* There are no groups left.  */
-		      spill_failure (max_groups_insn[class]);
-		      failure = 1;
-		      goto failed;
-		    }
-		}
-	    }
-
-	  /* Now similarly satisfy all need for single registers.  */
-
-	  while (max_needs[class] > 0 || max_nongroups[class] > 0)
-	    {
-	      /* If we spilled enough regs, but they weren't counted
-		 against the non-group need, see if we can count them now.
-		 If so, we can avoid some actual spilling.  */
-	      if (max_needs[class] <= 0 && max_nongroups[class] > 0)
-		for (i = 0; i < n_spills; i++)
-		  if (TEST_HARD_REG_BIT (reg_class_contents[class],
-					 spill_regs[i])
-		      && !TEST_HARD_REG_BIT (counted_for_groups,
-					     spill_regs[i])
-		      && !TEST_HARD_REG_BIT (counted_for_nongroups,
-					     spill_regs[i])
-		      && max_nongroups[class] > 0)
-		    {
-		      register enum reg_class *p;
-
-		      SET_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]);
-		      max_nongroups[class]--;
-		      p = reg_class_superclasses[class];
-		      while (*p != LIM_REG_CLASSES)
-			max_nongroups[(int) *p++]--;
-		    }
-	      if (max_needs[class] <= 0 && max_nongroups[class] <= 0)
-		break;
-
-	      /* Consider the potential reload regs that aren't
-		 yet in use as reload regs, in order of preference.
-		 Find the most preferred one that's in this class.  */
-
-	      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-		if (potential_reload_regs[i] >= 0
-		    && TEST_HARD_REG_BIT (reg_class_contents[class],
-					  potential_reload_regs[i])
-		    /* If this reg will not be available for groups,
-		       pick one that does not foreclose possible groups.
-		       This is a kludge, and not very general,
-		       but it should be sufficient to make the 386 work,
-		       and the problem should not occur on machines with
-		       more registers.  */
-		    && (max_nongroups[class] == 0
-			|| possible_group_p (potential_reload_regs[i], max_groups)))
-		  break;
+      CLEAR_HARD_REG_SET (used_spill_regs);
+      /* Try to satisfy the needs for each insn.  */
+      for (chain = reload_insn_chain; chain; chain = chain->next)
+	if (chain->need_reload)
+	  find_reload_regs (chain, global, dumpfile);
 
-	      /* If we couldn't get a register, try to get one even if we
-		 might foreclose possible groups.  This may cause problems
-		 later, but that's better than aborting now, since it is
-		 possible that we will, in fact, be able to form the needed
-		 group even with this allocation.  */
-
-	      if (i >= FIRST_PSEUDO_REGISTER
-		  && (asm_noperands (max_needs[class] > 0
-				     ? max_needs_insn[class]
-				     : max_nongroups_insn[class])
-		      < 0))
-		for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-		  if (potential_reload_regs[i] >= 0
-		      && TEST_HARD_REG_BIT (reg_class_contents[class],
-					    potential_reload_regs[i]))
-		    break;
-
-	      /* I should be the index in potential_reload_regs
-		 of the new reload reg we have found.  */
+      if (failure)
+	goto failed;
 
-	      if (i >= FIRST_PSEUDO_REGISTER)
-		{
-		  /* There are no possible registers left to spill.  */
-		  spill_failure (max_needs[class] > 0 ? max_needs_insn[class]
-				 : max_nongroups_insn[class]);
-		  failure = 1;
-		  goto failed;
-		}
-	      else
-		something_changed
-		  |= new_spill_reg (i, class, max_needs, max_nongroups,
-				    global, dumpfile);
-	    }
-	}
+      something_changed |= finish_spills (global, dumpfile);
     }
 
   /* If global-alloc was run, notify it of any register eliminations we have
@@ -2011,13 +1319,10 @@
 	mark_elimination (ep->from, ep->to);
 
   /* Insert code to save and restore call-clobbered hard regs
-     around calls.  Tell if what mode to use so that we will process
-     those insns in reload_as_needed if we have to.  */
+     around calls.  */
 
   if (caller_save_needed)
-    save_call_clobbered_regs (num_eliminable ? QImode
-			      : caller_save_spill_class != NO_REGS ? HImode
-			      : VOIDmode);
+    save_call_clobbered_regs (num_eliminable != 0);
 
   /* If a pseudo has no hard reg, delete the insns that made the equivalence.
      If that insn didn't set the register (i.e., it copied the register to
@@ -2045,8 +1350,7 @@
      values into or out of the reload registers.  */
 
   if (something_needs_reloads || something_needs_elimination
-      || (caller_save_needed && num_eliminable)
-      || caller_save_spill_class != NO_REGS)
+      || (caller_save_needed && num_eliminable))
     reload_as_needed (first, global);
 
   /* If we were able to eliminate the frame pointer, show that it is no
@@ -2169,33 +1473,199 @@
   if (real_at_ptr)
     free (real_at_ptr);
 
-  if (scratch_list)
-    free (scratch_list);
-  scratch_list = 0;
-  if (scratch_block)
-    free (scratch_block);
-  scratch_block = 0;
+  FREE_REG_SET (spilled_pseudos);
 
-  CLEAR_HARD_REG_SET (used_spill_regs);
-  for (i = 0; i < n_spills; i++)
-    SET_HARD_REG_BIT (used_spill_regs, spill_regs[i]);
-
+  obstack_free (&reload_obstack, reload_startobj);
   return failure;
 }
 
+/* Describes order of preference for putting regs into spill_regs.
+   Contains the numbers of all the hard regs, in order most preferred first.
+   This order is different for each function.
+   It is set up by order_regs_for_reload.
+   Empty elements at the end contain -1.  */
+static short potential_reload_regs[FIRST_PSEUDO_REGISTER];
+
+struct hard_reg_n_uses
+{
+  int regno;
+  unsigned int uses;
+};
+
+static int
+hard_reg_use_compare (p1p, p2p)
+  const GENERIC_PTR p1p;
+  const GENERIC_PTR p2p;
+{
+  struct hard_reg_n_uses *p1 = (struct hard_reg_n_uses *)p1p,
+			 *p2 = (struct hard_reg_n_uses *)p2p;
+  int 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;
+}
+
+/* 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, global)
+     struct insn_chain *chain;
+     int global;
+{
+  register int i;
+  register int o = 0;
+
+  struct hard_reg_n_uses hard_reg_n_uses[FIRST_PSEUDO_REGISTER];
+
+  CLEAR_HARD_REG_SET (bad_spill_regs);
+
+  /* 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++)
+    {
+      int regno;
+
+      hard_reg_n_uses[i].regno = i;
+      hard_reg_n_uses[i].uses = 0;
+
+      if (fixed_regs[i] || i == HARD_FRAME_POINTER_REGNUM)
+	{
+	  /* The frame pointer is a special case.  If we know we are going
+	     to eliminate it, it is not necessary to mark it as a bad spill
+	     reg.  Note that the code below would do the wrong thing, since
+	     the flow information always represents the frame pointer as
+	     being in use.  */
+	  if (i != HARD_FRAME_POINTER_REGNUM || frame_pointer_needed)
+	    SET_HARD_REG_BIT (bad_spill_regs, i);
+	  continue;
+	}
+
+      regno = chain->inverse_renum_before[i];
+      if (regno < 0)
+	SET_HARD_REG_BIT (bad_spill_regs, i);
+      else if (regno > 0 && ! REGNO_REG_SET_P (spilled_pseudos, regno))
+	{
+	  /* If allocated by local-alloc, show more uses since
+	     we're not going to be able to reallocate it, but
+	     we might if allocated by global alloc.  */
+	  if (global && reg_allocno[regno] < 0)
+	    hard_reg_n_uses[i].uses += (REG_N_REFS (regno) + 1) / 2;
+
+	  hard_reg_n_uses[i].uses += REG_N_REFS (regno);
+	}
+
+      regno = chain->inverse_renum_after[i];
+      if (regno < 0)
+	SET_HARD_REG_BIT (bad_spill_regs, i);
+      else if (regno > 0 && ! REGNO_REG_SET_P (spilled_pseudos, regno)
+	       && regno != chain->inverse_renum_before[i])
+	{
+	  if (global && reg_allocno[regno] < 0)
+	    hard_reg_n_uses[i].uses += (REG_N_REFS (regno) + 1) / 2;
+
+	  hard_reg_n_uses[i].uses += REG_N_REFS (regno);
+	}
+    }
+
+#ifdef STACK_REGS
+  /* Yet another special case.  Unfortunately, reg-stack forces people to
+     write incorrect clobbers in asm statements.  These clobbers must not
+     cause the register to appear in bad_spill_regs, otherwise we'll call
+     fatal_insn later. 
+     The whole thing is rather sick, I'm afraid.  */
+  if (asm_noperands (PATTERN (chain->insn)) >= 0) 
+    {
+      rtx pat = PATTERN (chain->insn);
+      if (GET_CODE (pat) == PARALLEL)
+	for (i = 0; i < XVECLEN (pat, 0); i++)
+	  {
+	    rtx t = XVECEXP (pat, 0, i);
+	    if (GET_CODE (t) == CLOBBER && STACK_REG_P (XEXP (t, 0)))
+	      CLEAR_HARD_REG_BIT (bad_spill_regs, REGNO (XEXP (t, 0)));
+	  }
+    }
+#endif
+
+  /* Let's try without this, I can't see a reason for doing this.  */
+#if defined ELIMINABLE_REGS && 0
+  /* If registers other than the frame pointer are eliminable, mark them as
+     poor choices.  */
+  for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
+    SET_HARD_REG_BIT (bad_spill_regs, reg_eliminate[i].from);
+
+#endif
+
+  /* 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;
+}
+
 /* Nonzero if, after spilling reg REGNO for non-groups,
    it will still be possible to find a group if we still need one.  */
 
 static int
-possible_group_p (regno, max_groups)
+possible_group_p (chain, regno)
+     struct insn_chain *chain;
      int regno;
-     int *max_groups;
 {
   int i;
   int class = (int) NO_REGS;
 
   for (i = 0; i < (int) N_REG_CLASSES; i++)
-    if (max_groups[i] > 0)
+    if (chain->need.groups[i] > 0)
       {
 	class = i;
 	break;
@@ -2230,28 +1700,26 @@
       if (spill_reg_order[i] < 0
 	  && ! TEST_HARD_REG_BIT (bad_spill_regs, i)
 	  && spill_reg_order[i + 1] >= 0
-	  && ! TEST_HARD_REG_BIT (counted_for_groups, i + 1)
-	  && ! TEST_HARD_REG_BIT (counted_for_nongroups, i + 1))
+	  && ! TEST_HARD_REG_BIT (chain->counted_for_groups, i + 1)
+	  && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, i + 1))
 	return 1;
       if (spill_reg_order[i + 1] < 0
 	  && ! TEST_HARD_REG_BIT (bad_spill_regs, i + 1)
 	  && spill_reg_order[i] >= 0
-	  && ! TEST_HARD_REG_BIT (counted_for_groups, i)
-	  && ! TEST_HARD_REG_BIT (counted_for_nongroups, i))
+	  && ! TEST_HARD_REG_BIT (chain->counted_for_groups, i)
+	  && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, i))
 	return 1;
     }
 
   return 0;
 }
-
+
 /* Count any groups of CLASS that can be formed from the registers recently
    spilled.  */
 
 static void
-count_possible_groups (group_size, group_mode, max_groups, class)
-     int *group_size;
-     enum machine_mode *group_mode;
-     int *max_groups;
+count_possible_groups (chain, class)
+     struct insn_chain *chain;
      int class;
 {
   HARD_REG_SET new;
@@ -2261,46 +1729,50 @@
      and mark each group off against the need for such groups.
      But don't count them against ordinary need, yet.  */
 
-  if (group_size[class] == 0)
+  if (chain->group_size[class] == 0)
     return;
 
   CLEAR_HARD_REG_SET (new);
 
   /* Make a mask of all the regs that are spill regs in class I.  */
   for (i = 0; i < n_spills; i++)
-    if (TEST_HARD_REG_BIT (reg_class_contents[class], spill_regs[i])
-	&& ! TEST_HARD_REG_BIT (counted_for_groups, spill_regs[i])
-	&& ! TEST_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]))
-      SET_HARD_REG_BIT (new, spill_regs[i]);
+    {
+      int regno = spill_regs[i];
 
+      if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+	  && ! TEST_HARD_REG_BIT (chain->counted_for_groups, regno)
+	  && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, regno))
+	SET_HARD_REG_BIT (new, regno);
+    }
+
   /* Find each consecutive group of them.  */
-  for (i = 0; i < FIRST_PSEUDO_REGISTER && max_groups[class] > 0; i++)
+  for (i = 0; i < FIRST_PSEUDO_REGISTER && chain->need.groups[class] > 0; i++)
     if (TEST_HARD_REG_BIT (new, i)
-	&& i + group_size[class] <= FIRST_PSEUDO_REGISTER
-	&& HARD_REGNO_MODE_OK (i, group_mode[class]))
+	&& i + chain->group_size[class] <= FIRST_PSEUDO_REGISTER
+	&& HARD_REGNO_MODE_OK (i, chain->group_mode[class]))
       {
-	for (j = 1; j < group_size[class]; j++)
+	for (j = 1; j < chain->group_size[class]; j++)
 	  if (! TEST_HARD_REG_BIT (new, i + j))
 	    break;
 
-	if (j == group_size[class])
+	if (j == chain->group_size[class])
 	  {
 	    /* We found a group.  Mark it off against this class's need for
 	       groups, and against each superclass too.  */
 	    register enum reg_class *p;
 
-	    max_groups[class]--;
+	    chain->need.groups[class]--;
 	    p = reg_class_superclasses[class];
 	    while (*p != LIM_REG_CLASSES)
 	      {
-		if (group_size [(int) *p] <= group_size [class])
-		  max_groups[(int) *p]--;
+		if (chain->group_size [(int) *p] <= chain->group_size [class])
+		  chain->need.groups[(int) *p]--;
 		p++;
 	      }
 
 	    /* Don't count these registers again.  */
-	    for (j = 0; j < group_size[class]; j++)
-	      SET_HARD_REG_BIT (counted_for_groups, i + j);
+	    for (j = 0; j < chain->group_size[class]; j++)
+	      SET_HARD_REG_BIT (chain->counted_for_groups, i + j);
 	  }
 
 	/* Skip to the last reg in this group.  When i is incremented above,
@@ -2308,34 +1780,6 @@
 	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.  */
@@ -2350,32 +1794,33 @@
     fatal_insn ("Unable to find a register to spill.", insn);
 }
 
-/* Add a new register to the tables of available spill-registers
-    (as well as spilling all pseudos allocated to the register).
+/* Add a new register to the tables of available spill-registers.
+   CHAIN is the insn for which the register will be used; we decrease the
+   needs of that insn.
    I is the index of this register in potential_reload_regs.
    CLASS is the regclass whose need is being satisfied.
-   MAX_NEEDS and MAX_NONGROUPS are the vectors of needs,
-    so that this register can count off against them.
-    MAX_NONGROUPS is 0 if this register is part of a group.
-   GLOBAL and DUMPFILE are the same as the args that `reload' got.  */
+   NONGROUP is 0 if this register is part of a group.
+   DUMPFILE is the same as the one that `reload' got.  */
 
-static int
-new_spill_reg (i, class, max_needs, max_nongroups, global, dumpfile)
+static void
+new_spill_reg (chain, i, class, nongroup, dumpfile)
+     struct insn_chain *chain;
      int i;
      int class;
-     int *max_needs;
-     int *max_nongroups;
-     int global;
+     int nongroup;
      FILE *dumpfile;
 {
   register enum reg_class *p;
-  int val;
   int regno = potential_reload_regs[i];
 
   if (i >= FIRST_PSEUDO_REGISTER)
-    abort ();	/* Caller failed to find any register.  */
+    {
+      spill_failure (chain->insn);
+      failure = 1;
+      return;
+    }
 
-  if (fixed_regs[regno] || TEST_HARD_REG_BIT (forbidden_regs, regno))
+  if (TEST_HARD_REG_BIT (bad_spill_regs, regno))
     {
       static char *reg_class_names[] = REG_CLASS_NAMES;
       fatal ("fixed or forbidden register %d (%s) was spilled for class %s.\n\
@@ -2389,49 +1834,355 @@
   spill_regs[n_spills] = regno;
   spill_reg_order[regno] = n_spills;
   if (dumpfile)
-    fprintf (dumpfile, "Spilling reg %d.\n", spill_regs[n_spills]);
+    fprintf (dumpfile, "Spilling reg %d.\n", regno);
+  SET_HARD_REG_BIT (chain->used_spill_regs, regno);
 
   /* Clear off the needs we just satisfied.  */
 
-  max_needs[class]--;
+  chain->need.regs[0][class]--;
   p = reg_class_superclasses[class];
   while (*p != LIM_REG_CLASSES)
-    max_needs[(int) *p++]--;
+    chain->need.regs[0][(int) *p++]--;
 
-  if (max_nongroups && max_nongroups[class] > 0)
+  if (nongroup && chain->need.regs[1][class] > 0)
     {
-      SET_HARD_REG_BIT (counted_for_nongroups, regno);
-      max_nongroups[class]--;
+      SET_HARD_REG_BIT (chain->counted_for_nongroups, regno);
+      chain->need.regs[1][class]--;
       p = reg_class_superclasses[class];
       while (*p != LIM_REG_CLASSES)
-	max_nongroups[(int) *p++]--;
+	chain->need.regs[1][(int) *p++]--;
     }
 
-  /* Spill every pseudo reg that was allocated to this reg
-     or to something that overlaps this reg.  */
+  n_spills++;
+}
 
-  val = spill_hard_reg (spill_regs[n_spills], global, dumpfile, 0);
+static void
+find_tworeg_group (chain, class, dumpfile)
+     struct insn_chain *chain;
+     int class;
+     FILE *dumpfile;
+{
+  int i;
+  /* First, look for a register that will complete a group.  */
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      int j, other;
 
-  /* If there are some registers still to eliminate and this register
-     wasn't ever used before, additional stack space may have to be
-     allocated to store this register.  Thus, we may have changed the offset
-     between the stack and frame pointers, so mark that something has changed.
-     (If new pseudos were spilled, thus requiring more space, VAL would have
-     been set non-zero by the call to spill_hard_reg above since additional
-     reloads may be needed in that case.
+      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;
+	}
+    }
+  /* We can't complete a group, so start one.  */
+  if (i == FIRST_PSEUDO_REGISTER)
+    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+      {
+	int k, j;
+	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);
+}
+
+static void
+find_group (chain, class, dumpfile)
+     struct insn_chain *chain;
+     int class;
+     FILE *dumpfile;
+{
+  int i;
+
+  /* For groups of more than 2 registers,
+     look for a sufficient sequence of unspilled registers,
+     and spill them all at once.  */
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      int j = potential_reload_regs[i];
+
+      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);
+		}
+
+	      /* 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;
+}
+
+/* For an insn, given by CHAIN, for which the needs have been calculated,
+   select a set of registers to use for reloading.  */
+static void
+find_reload_regs (chain, global, dumpfile)
+     struct insn_chain *chain;
+     int global;
+     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, global);
+
+  /* So far, no hard regs have been spilled.  */
+  n_spills = 0;
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    spill_reg_order[i] = -1;
+
+  /* Choose regs 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 `n_spills', and add entries to
+     `spill_regs' and `spill_reg_order'.
+
+     ??? 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.  */
+
+  CLEAR_HARD_REG_SET (chain->used_spill_regs);
+  CLEAR_HARD_REG_SET (chain->counted_for_groups);
+  CLEAR_HARD_REG_SET (chain->counted_for_nongroups);
+
+  for (class = 0; class < N_REG_CLASSES; class++)
+    {
+      /* First get the groups of registers.
+	 If we got single registers first, we might fragment
+	 possible groups.  */
+      while (group_needs[class] > 0)
+	{
+	  /* If any single spilled regs happen to form groups,
+	     count them now.  Maybe we don't really need
+	     to spill another group.  */
+	  count_possible_groups (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;
+	}
+
+      /* Now similarly satisfy all need for single registers.  */
+
+      while (simple_needs[class] > 0 || nongroup_needs[class] > 0)
+	{
+	  /* If we spilled enough regs, but they weren't counted
+	     against the non-group need, see if we can count them now.
+	     If so, we can avoid some actual spilling.  */
+	  if (simple_needs[class] <= 0 && nongroup_needs[class] > 0)
+	    for (i = 0; i < n_spills; i++)
+	      {
+		int regno = spill_regs[i];
+		if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+		    && !TEST_HARD_REG_BIT (chain->counted_for_groups, regno)
+		    && !TEST_HARD_REG_BIT (chain->counted_for_nongroups, regno)
+		    && nongroup_needs[class] > 0)
+		  {
+		    register enum reg_class *p;
+
+		    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 (simple_needs[class] <= 0 && nongroup_needs[class] <= 0)
+	    break;
+
+	  /* 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;
+	    }
+
+	  /* 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;
+
+	  /* I should be the index in potential_reload_regs
+	     of the new reload reg we have found.  */
+
+	  new_spill_reg (chain, i, class, 1, dumpfile);
+	  if (failure)
+	    return;
+	}
+    }
+  
+  /* We know which hard regs to use, now mark the pseudos that live in them
+     as needing to be kicked out.  */
+  for (i = 0; i < n_spills; i++)
+    {
+      int regno = chain->inverse_renum_before[spill_regs[i]];
+      if (regno > 0)
+	SET_REGNO_REG_SET (spilled_pseudos, regno);
+      regno = chain->inverse_renum_after[spill_regs[i]];
+      if (regno > 0)
+	SET_REGNO_REG_SET (spilled_pseudos, regno);
+    }
+
+  IOR_HARD_REG_SET (used_spill_regs, chain->used_spill_regs);
+}
 
-     One might think that we need only set VAL to 1 if this is a call-used
-     register.  However, the set of registers that must be saved by the
-     prologue is not identical to the call-used set.  For example, the
-     register used by the call insn for the return PC is a call-used register,
-     but must be saved by the prologue.  */
-  if (num_eliminable && ! regs_ever_live[spill_regs[n_spills]])
-    val = 1;
+
+/* 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.
 
-  regs_ever_live[spill_regs[n_spills]] = 1;
-  n_spills++;
+   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.  */
 
-  return val;
+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;
 }
 
 /* Delete an unneeded INSN and any previous insns who sole purpose is loading
@@ -2604,20 +2355,6 @@
   while (i < lim)
     regs_ever_live[i++] = 1;
 }
-
-/* Mark the registers used in SCRATCH as being live.  */
-
-static void
-mark_scratch_live (scratch)
-     rtx scratch;
-{
-  register int i;
-  int regno = REGNO (scratch);
-  int lim = regno + HARD_REGNO_NREGS (regno, GET_MODE (scratch));
-
-  for (i = regno; i < lim; i++)
-    regs_ever_live[i] = 1;
-}
 
 /* This function handles the tracking of elimination offsets around branches.
 
@@ -3665,7 +3402,6 @@
 }
 
 /* Kick all pseudos out of hard register REGNO.
-   If GLOBAL is nonzero, try to find someplace else to put them.
    If DUMPFILE is nonzero, log actions taken on that file.
 
    If CANT_ELIMINATE is nonzero, it means that we are doing this spill
@@ -3676,21 +3412,20 @@
 
    Return nonzero if any pseudos needed to be kicked out.  */
 
-static int
-spill_hard_reg (regno, global, dumpfile, cant_eliminate)
+static void
+spill_hard_reg (regno, dumpfile, cant_eliminate)
      register int regno;
-     int global;
      FILE *dumpfile;
      int cant_eliminate;
 {
   enum reg_class class = REGNO_REG_CLASS (regno);
-  int something_changed = 0;
   register int i;
 
-  SET_HARD_REG_BIT (forbidden_regs, regno);
-
   if (cant_eliminate)
-    regs_ever_live[regno] = 1;
+    {
+      SET_HARD_REG_BIT (forbidden_regs, regno);
+      regs_ever_live[regno] = 1;
+    }
 
   /* Spill every pseudo reg that was allocated to this reg
      or to something that overlaps this reg.  */
@@ -3702,75 +3437,199 @@
 	    + HARD_REGNO_NREGS (reg_renumber[i],
 				PSEUDO_REGNO_MODE (i))
 	    > regno))
-      {
-	/* If this register belongs solely to a basic block which needed no
-	   spilling of any class that this register is contained in,
-	   leave it be, unless we are spilling this register because
-	   it was a hard register that can't be eliminated.   */
-
-	if (! cant_eliminate
-	    && basic_block_needs[0]
-	    && REG_BASIC_BLOCK (i) >= 0
-	    && basic_block_needs[(int) class][REG_BASIC_BLOCK (i)] == 0)
-	  {
-	    enum reg_class *p;
+      SET_REGNO_REG_SET (spilled_pseudos, i);
+}
 
-	    for (p = reg_class_superclasses[(int) class];
-		 *p != LIM_REG_CLASSES; p++)
-	      if (basic_block_needs[(int) *p][REG_BASIC_BLOCK (i)] > 0)
-		break;
+/* When we notice that caller-saves would need a spill register, kick out all
+   pseudos which are in caller-saved hard registers and live across calls.  */
+static void
+spill_caller_saved_regs ()
+{
+  int i;
 
-	    if (*p == LIM_REG_CLASSES)
-	      continue;
-	  }
+  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+    {
+      int regno = reg_renumber[i];
+      int nregs;
+      if (regno < 0 || REG_N_CALLS_CROSSED (i) > 0)
+	continue;
+      nregs = HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
+      while (nregs-- > 0)
+	if (call_used_regs[regno++])
+	  SET_REGNO_REG_SET (spilled_pseudos, i);
+    }
+  /* We no longer want caller-saves if retry_global_alloc is run.  */
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (call_used_regs[i])
+      SET_HARD_REG_BIT (losing_caller_save_reg_set, i);
+}
+
+/* After choose_reload_regs has been run for all insn that need reloads,
+   and/or spill_hard_regs was called, this function is used to actually
+   spill pseudo registers and try to reallocate them.  It also sets up the
+   spill_regs array for use by choose_reload_regs.  */
+
+static int
+finish_spills (global, dumpfile)
+     int global;
+     FILE *dumpfile;
+{
+  struct insn_chain *chain;
+  int something_changed = 0;
+  int i;
+
+  /* Build the spill_regs array for the function.  */
+  /* If there are some registers still to eliminate and one of the spill regs
+     wasn't ever used before, additional stack space may have to be
+     allocated to store this register.  Thus, we may have changed the offset
+     between the stack and frame pointers, so mark that something has changed.
+
+     One might think that we need only set VAL to 1 if this is a call-used
+     register.  However, the set of registers that must be saved by the
+     prologue is not identical to the call-used set.  For example, the
+     register used by the call insn for the return PC is a call-used register,
+     but must be saved by the prologue.  */
 
+  n_spills = 0;
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (TEST_HARD_REG_BIT (used_spill_regs, i))
+      {
+	spill_reg_order[i] = n_spills;
+	spill_regs[n_spills++] = i;
+	if (num_eliminable && ! regs_ever_live[i])
+	  something_changed = 1;
+	regs_ever_live[i] = 1;
+      }
+    else
+      spill_reg_order[i] = -1;
+
+  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+    if (REGNO_REG_SET_P (spilled_pseudos, i))
+      {
 	/* Mark it as no longer having a hard register home.  */
 	reg_renumber[i] = -1;
 	/* We will need to scan everything again.  */
 	something_changed = 1;
-	if (global)
-	  retry_global_alloc (i, forbidden_regs);
+      }
+
+  if (global)
+    {
+      /* For every insn that needs reloads, set the registers used as spill
+	 regs in pseudo_forbidden_regs for every pseudo live across the
+	 insn.  */
+      bzero ((char *) pseudo_forbidden_regs, max_regno * sizeof (HARD_REG_SET));
+      for (chain = reload_insn_chain; chain; chain = chain->next)
+	{
+	  rtx insn = chain->insn;
+	  if (! chain->need_reload)
+	    continue;
+	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	    {
+	      int regno = chain->inverse_renum_before[i];
+	      if (regno > 0)
+		IOR_HARD_REG_SET (pseudo_forbidden_regs[regno],
+				  chain->used_spill_regs);
+
+	      regno = chain->inverse_renum_after[i];
+	      if (regno > 0)
+		IOR_HARD_REG_SET (pseudo_forbidden_regs[regno],
+				  chain->used_spill_regs);
+	    }
+	}
 
-	alter_reg (i, regno);
-	if (dumpfile)
+      /* Retry allocating the spilled pseudos.  */
+      for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+	if (reg_old_renumber[i] != reg_renumber[i])
 	  {
-	    if (reg_renumber[i] == -1)
-	      fprintf (dumpfile, " Register %d now on stack.\n\n", i);
-	    else
-	      fprintf (dumpfile, " Register %d now in %d.\n\n",
-		       i, reg_renumber[i]);
+	    HARD_REG_SET forbidden;
+	    COPY_HARD_REG_SET (forbidden, forbidden_regs);
+	    IOR_HARD_REG_SET (forbidden, pseudo_forbidden_regs[i]);
+	    retry_global_alloc (i, forbidden);
 	  }
-      }
-  for (i = 0; i < scratch_list_length; i++)
+    }
+
+  /* Fix up the register information in the insn chain.  */
+  for (chain = reload_insn_chain; chain; chain = chain->next)
     {
-     if (scratch_list[i] 
-          && regno >= REGNO (scratch_list[i]) 
-          && regno <  REGNO (scratch_list[i]) 
-                      + HARD_REGNO_NREGS (REGNO (scratch_list[i]),
-                                          GET_MODE (scratch_list[i])))
+      regset live_before = ALLOCA_REG_SET();
+      regset live_after = ALLOCA_REG_SET();
+
+      /* Figure out which off the spilled pseudos are live before and
+	 after the insn.  Delete the old mappings in the inverse_renum
+	 arrays.  */
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
 	{
-	  if (! cant_eliminate && basic_block_needs[0]
-	      && ! basic_block_needs[(int) class][scratch_block[i]])
+	  int regno = chain->inverse_renum_after[i];
+	  if (regno >= FIRST_PSEUDO_REGISTER
+	      && REGNO_REG_SET_P (spilled_pseudos, regno))
 	    {
-	      enum reg_class *p;
-
-	      for (p = reg_class_superclasses[(int) class];
-		   *p != LIM_REG_CLASSES; p++)
-		if (basic_block_needs[(int) *p][scratch_block[i]] > 0)
-		  break;
+	      chain->inverse_renum_after[i] = 0;
+	      SET_REGNO_REG_SET (live_after, regno);
+	    }
 
-	      if (*p == LIM_REG_CLASSES)
-		continue;
+	  regno = chain->inverse_renum_before[i];
+	  if (regno >= FIRST_PSEUDO_REGISTER
+	      && REGNO_REG_SET_P (spilled_pseudos, regno))
+	    {
+	      chain->inverse_renum_before[i] = 0;
+	      SET_REGNO_REG_SET (live_before, regno);
 	    }
-	  PUT_CODE (scratch_list[i], SCRATCH);
-	  scratch_list[i] = 0;
-	  something_changed = 1;
-	  continue;
+	}
+      /* Now set up the new mappings in inverse_renum.  */
+      for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+	{
+	  int regno = reg_renumber[i];
+	  if (regno < 0)
+	    continue;
+	  if (REGNO_REG_SET_P (live_before, i))
+	    {
+	      int nregs = HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
+	      while (nregs-- > 0)
+		chain->inverse_renum_before[regno++] = i;
+	    }
+	  regno = reg_renumber[i];
+	  if (REGNO_REG_SET_P (live_after, i))
+	    {
+	      int nregs = HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
+	      while (nregs-- > 0)
+		chain->inverse_renum_after[regno++] = i;
+	    }
+	}
+
+      /* Mark any unallocated hard regs as available for spills.  That
+	 makes inheritance work somewhat better.  */
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	if (TEST_HARD_REG_BIT (used_spill_regs, i)
+	    && chain->inverse_renum_before[i] == 0
+	    && chain->inverse_renum_after[i] == 0)
+	  SET_HARD_REG_BIT (chain->used_spill_regs, i);
+
+      FREE_REG_SET (live_before);
+      FREE_REG_SET (live_after);
+    }
+
+  /* Let alter_reg modify the reg rtx's for the modified pseudos.  */
+  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+    {
+      int regno = reg_renumber[i];
+      if (reg_old_renumber[i] == regno)
+	continue;
+      
+      alter_reg (i, reg_old_renumber[i]);
+      reg_old_renumber[i] = regno;
+      if (dumpfile)
+	{
+	  if (regno == -1)
+	    fprintf (dumpfile, " Register %d now on stack.\n\n", i);
+	  else
+	    fprintf (dumpfile, " Register %d now in %d.\n\n",
+		     i, reg_renumber[i]);
 	}
     }
 
   return something_changed;
 }
+
 
 /* Find all paradoxical subregs within X and update reg_max_ref_width. 
    Also mark any hard registers used to store user variables as
@@ -3828,141 +3687,6 @@
     }
 }
 
-static int
-hard_reg_use_compare (p1p, p2p)
-  const GENERIC_PTR p1p;
-  const GENERIC_PTR p2p;
-{
-  struct hard_reg_n_uses *p1 = (struct hard_reg_n_uses *)p1p,
-			 *p2 = (struct hard_reg_n_uses *)p2p;
-  int tem = p1->uses - p2->uses;
-  if (tem != 0) return tem;
-  /* If regs are equally good, sort by regno,
-     so that the results of qsort leave nothing to chance.  */
-  return p1->regno - p2->regno;
-}
-
-/* Choose the order to consider regs for use as reload registers
-   based on how much trouble would be caused by spilling one.
-   Store them in order of decreasing preference in potential_reload_regs.  */
-
-static void
-order_regs_for_reload (global)
-     int global;
-{
-  register int i;
-  register int o = 0;
-  int large = 0;
-
-  struct hard_reg_n_uses hard_reg_n_uses[FIRST_PSEUDO_REGISTER];
-
-  CLEAR_HARD_REG_SET (bad_spill_regs);
-
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    potential_reload_regs[i] = -1;
-
-  /* Count number of uses of each hard reg by pseudo regs allocated to it
-     and then order them by decreasing use.  */
-
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    {
-      hard_reg_n_uses[i].uses = 0;
-      hard_reg_n_uses[i].regno = i;
-    }
-
-  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-    {
-      int regno = reg_renumber[i];
-      if (regno >= 0)
-	{
-	  int lim = regno + HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
-	  while (regno < lim)
-	    {
-	      /* If allocated by local-alloc, show more uses since
-		 we're not going to be able to reallocate it, but
-		 we might if allocated by global alloc.  */
-	      if (global && reg_allocno[i] < 0)
-		hard_reg_n_uses[regno].uses += (REG_N_REFS (i) + 1) / 2;
-
-	      hard_reg_n_uses[regno++].uses += REG_N_REFS (i);
-	    }
-	}
-      large += REG_N_REFS (i);
-    }
-
-  /* Now fixed registers (which cannot safely be used for reloading)
-     get a very high use count so they will be considered least desirable.
-     Registers used explicitly in the rtl code are almost as bad.  */
-
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    {
-      if (fixed_regs[i])
-	{
-	  hard_reg_n_uses[i].uses += 2 * large + 2;
-	  SET_HARD_REG_BIT (bad_spill_regs, i);
-	}
-      else if (regs_explicitly_used[i])
-	{
-	  hard_reg_n_uses[i].uses += large + 1;
-	  if (! SMALL_REGISTER_CLASSES)
-	    /* ??? We are doing this here because of the potential
-	     that bad code may be generated if a register explicitly
-	     used in an insn was used as a spill register for that
-	     insn.  But not using these are spill registers may lose
-	     on some machine.  We'll have to see how this works out.  */
-	    SET_HARD_REG_BIT (bad_spill_regs, i);
-	}
-    }
-  hard_reg_n_uses[HARD_FRAME_POINTER_REGNUM].uses += 2 * large + 2;
-  SET_HARD_REG_BIT (bad_spill_regs, HARD_FRAME_POINTER_REGNUM);
-
-#ifdef ELIMINABLE_REGS
-  /* If registers other than the frame pointer are eliminable, mark them as
-     poor choices.  */
-  for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
-    {
-      hard_reg_n_uses[reg_eliminate[i].from].uses += 2 * large + 2;
-      SET_HARD_REG_BIT (bad_spill_regs, reg_eliminate[i].from);
-    }
-#endif
-
-  /* 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)
-	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])
-	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])
-	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)
-      potential_reload_regs[o++] = hard_reg_n_uses[i].regno;
-}
-
 /* Used in reload_as_needed to sort the spilled regs.  */
 
 static int
@@ -3988,11 +3712,9 @@
      rtx first;
      int live_known;
 {
-  register rtx insn;
+  struct insn_chain *chain;
   register int i;
-  int this_block = 0;
   rtx x;
-  rtx after_call = 0;
 
   bzero ((char *) spill_reg_rtx, sizeof spill_reg_rtx);
   bzero ((char *) spill_reg_store, sizeof spill_reg_store);
@@ -4017,25 +3739,13 @@
 #endif
 
   num_not_at_initial_offset = 0;
-
-  /* Order the spilled regs, so that allocate_reload_regs can guarantee to
-     pack registers with group needs.  */
-  if (n_spills > 1)
-    {
-      qsort (spill_regs, n_spills, sizeof (short), compare_spill_regs);
-      for (i = 0; i < n_spills; i++)
-	spill_reg_order[spill_regs[i]] = i;
-    }
 
-  for (insn = first; insn;)
+  for (chain = reload_insn_chain; chain; chain = chain->next)
     {
-      register rtx next = NEXT_INSN (insn);
+      rtx insn = chain->insn;
+      rtx old_next = NEXT_INSN (insn);
+      int this_block = chain->block;
 
-      /* Notice when we move to a new basic block.  */
-      if (live_known && this_block + 1 < n_basic_blocks
-	  && insn == basic_block_head[this_block+1])
-	++this_block;
-
       /* If we pass a label, copy the offsets from the label information
 	 into the current offsets of each elimination.  */
       if (GET_CODE (insn) == CODE_LABEL)
@@ -4054,31 +3764,8 @@
 
       else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
 	{
-	  rtx avoid_return_reg = 0;
 	  rtx oldpat = PATTERN (insn);
 
-	  /* Set avoid_return_reg if this is an insn
-	     that might use the value of a function call.  */
-	  if (SMALL_REGISTER_CLASSES && GET_CODE (insn) == CALL_INSN)
-	    {
-	      if (GET_CODE (PATTERN (insn)) == SET)
-		after_call = SET_DEST (PATTERN (insn));
-	      else if (GET_CODE (PATTERN (insn)) == PARALLEL
-		       && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
-		after_call = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
-	      else
-		after_call = 0;
-	    }
-	  else if (SMALL_REGISTER_CLASSES && after_call != 0
-		   && !(GET_CODE (PATTERN (insn)) == SET
-			&& SET_DEST (PATTERN (insn)) == stack_pointer_rtx)
-		   && GET_CODE (PATTERN (insn)) != USE)
-	    {
-	      if (reg_referenced_p (after_call, PATTERN (insn)))
-		avoid_return_reg = after_call;
-	      after_call = 0;
-	    }
-
 	  /* If this is a USE and CLOBBER of a MEM, ensure that any
 	     references to eliminable registers have been removed.  */
 
@@ -4092,17 +3779,14 @@
 
 	  /* If we need to do register elimination processing, do so.
 	     This might delete the insn, in which case we are done.  */
-	  if (num_eliminable && GET_MODE (insn) == QImode)
+	  if (num_eliminable && chain->need_elim)
 	    {
 	      eliminate_regs_in_insn (insn, 1);
 	      if (GET_CODE (insn) == NOTE)
-		{
-		  insn = next;
-		  continue;
-		}
+		continue;
 	    }
 
-	  if (GET_MODE (insn) == VOIDmode)
+	  if (! chain->need_elim && ! chain->need_reload)
 	    n_reloads = 0;
 	  /* First find the pseudo regs that must be reloaded for this insn.
 	     This info is returned in the tables reload_... (see reload.h).
@@ -4123,26 +3807,11 @@
 	      rtx p;
 	      int class;
 
-	      /* If this block has not had spilling done for a
-		 particular clas and we have any non-optionals that need a
-		 spill reg in that class, abort.  */
-
-	      for (class = 0; class < N_REG_CLASSES; class++)
-		if (basic_block_needs[class] != 0
-		    && basic_block_needs[class][this_block] == 0)
-		  for (i = 0; i < n_reloads; i++)
-		    if (class == (int) reload_reg_class[i]
-			&& reload_reg_rtx[i] == 0
-			&& ! reload_optional[i]
-			&& (reload_in[i] != 0 || reload_out[i] != 0
-			    || reload_secondary_p[i] != 0))
-		      fatal_insn ("Non-optional registers need a spill register", insn);
-
 	      /* Now compute which reload regs to reload them into.  Perhaps
 		 reusing reload regs from previous insns, or else output
 		 load insns to reload them.  Maybe output store insns too.
 		 Record the choices of reload reg in reload_reg_rtx.  */
-	      choose_reload_regs (insn, avoid_return_reg);
+	      choose_reload_regs (chain, live_known);
 
 	      /* Merge any reloads that we didn't combine for fear of 
 		 increasing the number of spill registers needed but now
@@ -4188,7 +3857,7 @@
 
 	  /* There may have been CLOBBER insns placed after INSN.  So scan
 	     between INSN and NEXT and use them to forget old reloads.  */
-	  for (x = NEXT_INSN (insn); x != next; x = NEXT_INSN (x))
+	  for (x = NEXT_INSN (insn); x != old_next; x = NEXT_INSN (x))
 	    if (GET_CODE (x) == INSN && GET_CODE (PATTERN (x)) == CLOBBER)
 	      note_stores (PATTERN (x), forget_old_reloads_1);
 
@@ -4230,8 +3899,6 @@
 	  CLEAR_HARD_REG_BIT (reg_reloaded_valid, i);
 #endif
 
-      insn = next;
-
 #ifdef USE_C_ALLOCA
       alloca (0);
 #endif
@@ -5138,17 +4805,15 @@
    or 0 if we couldn't find a spill reg and we didn't change anything.  */
 
 static int
-allocate_reload_reg (r, insn, last_reload, noerror)
+allocate_reload_reg (chain, r, last_reload, noerror)
+     struct insn_chain *chain;
      int r;
-     rtx insn;
      int last_reload;
      int noerror;
 {
-  int i;
-  int pass;
-  int count;
+  rtx insn = chain->insn;
+  int i, pass, count, regno;
   rtx new;
-  int regno;
 
   /* If we put this reload ahead, thinking it is a group,
      then insist on finding a group.  Otherwise we can grab a
@@ -5197,32 +4862,36 @@
       for (count = 0; count < n_spills; count++)
 	{
 	  int class = (int) reload_reg_class[r];
+	  int regnum;
 
-	  i = (i + 1) % n_spills;
+	  i++;
+	  if (i >= n_spills)
+	    i -= n_spills;
+	  regnum = spill_regs[i];
 
-	  if ((reload_reg_free_p (spill_regs[i], reload_opnum[r],
+	  if ((reload_reg_free_p (regnum, reload_opnum[r],
 				  reload_when_needed[r])
 	       || (reload_in[r]
 		      /* We check reload_reg_used to make sure we
 			 don't clobber the return register.  */
-		   && ! TEST_HARD_REG_BIT (reload_reg_used, spill_regs[i])
-		   && reload_reg_free_for_value_p (spill_regs[i],
+		   && ! TEST_HARD_REG_BIT (reload_reg_used, regnum)
+		   && reload_reg_free_for_value_p (regnum,
 						  reload_opnum[r],
 						  reload_when_needed[r],
 						  reload_in[r],
 						  reload_out[r], r)))
-	      && TEST_HARD_REG_BIT (reg_class_contents[class], spill_regs[i])
-	      && HARD_REGNO_MODE_OK (spill_regs[i], reload_mode[r])
+	      && TEST_HARD_REG_BIT (reg_class_contents[class], regnum)
+	      && HARD_REGNO_MODE_OK (regnum, reload_mode[r])
 	      /* Look first for regs to share, then for unshared.  But
 		 don't share regs used for inherited reloads; they are
 		 the ones we want to preserve.  */
 	      && (pass
 		  || (TEST_HARD_REG_BIT (reload_reg_used_at_all,
-					 spill_regs[i])
+					 regnum)
 		      && ! TEST_HARD_REG_BIT (reload_reg_used_for_inherit,
-					      spill_regs[i]))))
+					      regnum))))
 	    {
-	      int nr = HARD_REGNO_NREGS (spill_regs[i], reload_mode[r]);
+	      int nr = HARD_REGNO_NREGS (regnum, reload_mode[r]);
 	      /* Avoid the problem where spilling a GENERAL_OR_FP_REG
 		 (on 68000) got us two FP regs.  If NR is 1,
 		 we would reject both of them.  */
@@ -5240,15 +4909,15 @@
 		 are available here.
 		 Also, don't use for a group registers that are
 		 needed for nongroups.  */
-	      if (! TEST_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]))
+	      if (! TEST_HARD_REG_BIT (chain->counted_for_nongroups, regnum))
 		while (nr > 1)
 		  {
-		    regno = spill_regs[i] + nr - 1;
+		    regno = regnum + nr - 1;
 		    if (!(TEST_HARD_REG_BIT (reg_class_contents[class], regno)
 			  && spill_reg_order[regno] >= 0
 			  && reload_reg_free_p (regno, reload_opnum[r],
 						reload_when_needed[r])
-			  && ! TEST_HARD_REG_BIT (counted_for_nongroups,
+			  && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups,
 						  regno)))
 		      break;
 		    nr--;
@@ -5344,14 +5013,15 @@
    finding a reload reg in the proper class.  */
 
 static void
-choose_reload_regs (insn, avoid_return_reg)
-     rtx insn;
-     rtx avoid_return_reg;
+choose_reload_regs (chain, global)
+     struct insn_chain *chain;
+     int global;
 {
   register int i, j;
   int max_group_size = 1;
   enum reg_class group_class = NO_REGS;
   int inheritance;
+  rtx insn = chain->insn;
 
   rtx save_reload_reg_rtx[MAX_RELOADS];
   char save_reload_inherited[MAX_RELOADS];
@@ -5392,29 +5062,8 @@
       CLEAR_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i]);
     }
 
-  /* Don't bother with avoiding the return reg
-     if we have no mandatory reload that could use it.  */
-  if (SMALL_REGISTER_CLASSES && avoid_return_reg)
-    {
-      int do_avoid = 0;
-      int regno = REGNO (avoid_return_reg);
-      int nregs
-	= HARD_REGNO_NREGS (regno, GET_MODE (avoid_return_reg));
-      int r;
-
-      for (r = regno; r < regno + nregs; r++)
-	if (spill_reg_order[r] >= 0)
-	  for (j = 0; j < n_reloads; j++)
-	    if (!reload_optional[j] && reload_reg_rtx[j] == 0
-		&& (reload_in[j] != 0 || reload_out[j] != 0
-		    || reload_secondary_p[j])
-		&&
-		TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[j]], r))
-	      do_avoid = 1;
-      if (!do_avoid)
-	avoid_return_reg = 0;
-    }
-
+  IOR_COMPL_HARD_REG_SET (reload_reg_used, chain->used_spill_regs);
+  
 #if 0  /* Not needed, now that we can always retry without inheritance.  */
   /* See if we have more mandatory reloads than spill regs.
      If so, then we cannot risk optimizations that could prevent
@@ -5424,7 +5073,7 @@
      unless it is equal to reload_in or reload_out, count such reloads.  */
 
   {
-    int tem = SMALL_REGISTER_CLASSES? (avoid_return_reg != 0): 0;
+    int tem = 0;
     for (j = 0; j < n_reloads; j++)
       if (! reload_optional[j]
 	  && (reload_in[j] != 0 || reload_out[j] != 0 || reload_secondary_p[j])
@@ -5437,20 +5086,6 @@
   }
 #endif
 
-  /* Don't use the subroutine call return reg for a reload
-     if we are supposed to avoid it.  */
-  if (SMALL_REGISTER_CLASSES && avoid_return_reg)
-    {
-      int regno = REGNO (avoid_return_reg);
-      int nregs
-	= HARD_REGNO_NREGS (regno, GET_MODE (avoid_return_reg));
-      int r;
-
-      for (r = regno; r < regno + nregs; r++)
-	if (spill_reg_order[r] >= 0)
-	  SET_HARD_REG_BIT (reload_reg_used, r);
-    }
-
   /* In order to be certain of getting the registers we need,
      we must sort the reloads into order of increasing register class.
      Then our grabbing of reload registers will parallel the process
@@ -5587,7 +5222,7 @@
 		   || reload_secondary_p[reload_order[i]])
 		  && ! reload_optional[reload_order[i]]
 		  && reload_reg_rtx[reload_order[i]] == 0)
-		allocate_reload_reg (reload_order[i], insn, 0, inheritance);
+		allocate_reload_reg (chain, reload_order[i], 0, inheritance);
 #endif
 
 	  /* First see if this pseudo is already available as reloaded
@@ -5906,7 +5541,7 @@
 	  if (i == n_reloads)
 	    continue;
 
-	  allocate_reload_reg (r, insn, j == n_reloads - 1, inheritance);
+	  allocate_reload_reg (chain, r, j == n_reloads - 1, inheritance);
 #endif
 	}
 
@@ -5925,7 +5560,7 @@
 	  if (reload_reg_rtx[r] != 0 || reload_optional[r])
 	    continue;
 
-	  if (! allocate_reload_reg (r, insn, j == n_reloads - 1, inheritance))
+	  if (! allocate_reload_reg (chain, r, j == n_reloads - 1, inheritance))
 	    break;
 	}
 
Index: reorg.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/reorg.c,v
retrieving revision 1.1.1.19
diff -u -r1.1.1.19 reorg.c
--- reorg.c	1998/07/12 18:35:45	1.1.1.19
+++ reorg.c	1998/08/24 16:05:14
@@ -2526,6 +2526,7 @@
 	  AND_COMPL_HARD_REG_SET (res->regs, pending_dead_regs);
 	  CLEAR_HARD_REG_SET (pending_dead_regs);
 
+#if 0 /* @@@ This no longer works now that reload is more clever.  */
 	  if (CODE_LABEL_NUMBER (insn) < max_label_num_after_reload)
 	    {
 	      /* All spill registers are dead at a label, so kill all of the
@@ -2534,6 +2535,7 @@
 	      AND_COMPL_HARD_REG_SET (scratch, needed.regs);
 	      AND_COMPL_HARD_REG_SET (res->regs, scratch);
 	    }
+#endif
 	  continue;
 
 	case BARRIER:
Index: stupid.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/stupid.c,v
retrieving revision 1.1.1.11
diff -u -r1.1.1.11 stupid.c
--- stupid.c	1998/06/24 11:25:23	1.1.1.11
+++ stupid.c	1998/08/25 10:07:22
@@ -48,6 +48,8 @@
 #include "rtl.h"
 #include "hard-reg-set.h"
 #include "regs.h"
+#include "insn-config.h"
+#include "reload.h"
 #include "flags.h"
 #include "toplev.h"
 
@@ -81,6 +83,14 @@
 
 static int *reg_where_born;
 
+/* Likewise, but point to the insn_chain structure of the insn at which
+   the reg dies.  */
+static struct insn_chain **reg_where_dead_chain;
+
+/* More precise versions of the above vectors.  @@@ merge these.  */
+static int *reg_where_born_exact;
+static int *reg_where_born_clobber;
+
 /* Numbers of pseudo-regs to be allocated, highest priority first.  */
 
 static int *reg_order;
@@ -111,8 +121,35 @@
 static int stupid_reg_compare	PROTO((const GENERIC_PTR,const GENERIC_PTR));
 static int stupid_find_reg	PROTO((int, enum reg_class, enum machine_mode,
 				       int, int, int));
-static void stupid_mark_refs	PROTO((rtx, rtx));
+static void stupid_mark_refs	PROTO((rtx, struct insn_chain *));
 
+/* For communication between stupid_life_analysis and find_clobbered_regs.  */
+static struct insn_chain *current_chain;
+
+static void
+find_clobbered_regs (reg, setter)
+     rtx reg, setter;
+{
+  int regno, nregs;
+  if (setter == 0 || GET_CODE (setter) != CLOBBER || GET_CODE (reg) != REG)
+    return;
+  regno = REGNO (reg);
+  if (regno >= FIRST_PSEUDO_REGISTER)
+    return;
+
+  if (GET_MODE (reg) == VOIDmode)
+    nregs = 1;
+  else
+    nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+  while (nregs-- > 0)
+    {
+      if (current_chain->inverse_renum_after[regno + nregs] != 0)
+	abort ();
+      current_chain->inverse_renum_after[regno + nregs] = -1;
+    }
+}
+
+
 /* Stupid life analysis is for the case where only variables declared
    `register' go in registers.  For this case, we mark all
    pseudo-registers that belong to register variables as
@@ -171,6 +208,15 @@
   reg_where_dead = (int *) alloca (nregs * sizeof (int));
   bzero ((char *) reg_where_dead, nregs * sizeof (int));
 
+  reg_where_born_exact = (int *) alloca (nregs * sizeof (int));
+  bzero ((char *) reg_where_born_exact, nregs * sizeof (int));
+
+  reg_where_born_clobber = (int *) alloca (nregs * sizeof (int));
+  bzero ((char *) reg_where_born_clobber, nregs * sizeof (int));
+
+  reg_where_dead_chain = (struct insn_chain **) alloca (nregs * sizeof (struct insn_chain *));
+  bzero ((char *) reg_where_dead_chain, nregs * sizeof (struct insn_chain *));
+
   reg_where_born = (int *) alloca (nregs * sizeof (int));
   bzero ((char *) reg_where_born, nregs * sizeof (int));
 
@@ -210,11 +256,15 @@
      Also find where each hard register is live
      and record that info in after_insn_hard_regs.
      regs_live[I] is 1 if hard reg I is live
-     at the current point in the scan.  */
+     at the current point in the scan.  
+   
+     Build reload_insn_chain while we're walking the insns.  */
 
+  reload_insn_chain = 0;
   for (insn = last; insn; insn = PREV_INSN (insn))
     {
       register HARD_REG_SET *p = after_insn_hard_regs + INSN_SUID (insn);
+      struct insn_chain *chain;
 
       /* Copy the info in regs_live into the element of after_insn_hard_regs
 	 for the current position in the rtl code.  */
@@ -223,12 +273,30 @@
 	if (regs_live[i])
 	  SET_HARD_REG_BIT (*p, i);
 
+      if (GET_CODE (insn) != NOTE && GET_CODE (insn) != BARRIER)
+	{
+	  chain = new_insn_chain ();
+	  if (reload_insn_chain)
+	    reload_insn_chain->prev = chain;
+	  chain->next = reload_insn_chain;
+	  chain->prev = 0;
+	  reload_insn_chain = chain;
+	  chain->block = 0;
+	  chain->insn = insn;
+	  bzero ((char *)chain->inverse_renum_after,
+		 sizeof chain->inverse_renum_after);
+	  bzero ((char *)chain->inverse_renum_before,
+		 sizeof chain->inverse_renum_before);
+	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	    chain->inverse_renum_before[i] = regs_live[i] ? -1 : 0;
+	}
+
       /* Update which hard regs are currently live
 	 and also the birth and death suids of pseudo regs
 	 based on the pattern of this insn.  */
 
       if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
-	stupid_mark_refs (PATTERN (insn), insn);
+	stupid_mark_refs (PATTERN (insn), chain);
 
       if (GET_CODE (insn) == NOTE
 	  && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
@@ -266,8 +334,21 @@
 	  /* It is important that this be done after processing the insn's
 	     pattern because we want the function result register to still
 	     be live if it's also used to pass arguments.  */
-	  stupid_mark_refs (CALL_INSN_FUNCTION_USAGE (insn), insn);
+	  stupid_mark_refs (CALL_INSN_FUNCTION_USAGE (insn), chain);
+	}
+
+      if (GET_CODE (insn) != NOTE && GET_CODE (insn) != BARRIER)
+	{	  
+	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	    chain->inverse_renum_after[i] = regs_live[i] ? -1 : 0;
+	  /* The regs_live array doesn't say anything about hard registers
+	     clobbered by this insn.  So we need an extra pass over the
+	     pattern.  */
+	  current_chain = chain;
+	  if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+	    note_stores (PATTERN (insn), find_clobbered_regs);
 	}
+
       if (GET_CODE (insn) == JUMP_INSN && computed_jump_p (insn))
 	current_function_has_computed_jump = 1;
     }
@@ -289,8 +370,10 @@
 
       /* Some regnos disappear from the rtl.  Ignore them to avoid crash. 
 	 Also don't allocate registers that cross a setjmp, or live across
-	 a call if this function receives a nonlocal goto.  */
+	 a call if this function receives a nonlocal goto.
+	 Also ignore registers we didn't see during the scan.  */
       if (regno_reg_rtx[r] == 0 || regs_crosses_setjmp[r]
+	  || (reg_where_born[r] == 0 && reg_where_dead[r] == 0)
 	  || (REG_N_CALLS_CROSSED (r) > 0 
 	      && current_function_has_nonlocal_label))
 	continue;
@@ -314,6 +397,41 @@
 					   regs_change_size[r]);
     }
 
+  /* Fill in the pseudo reg information into the insn chain.  
+     @@@ Fixme, this isn't pretty.  */
+  for (i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++)
+    {
+      struct insn_chain *chain;
+      int regno, nregs;
+      int j;
+
+      regno = reg_renumber[i];
+      if (regno < 0)
+	continue;
+      nregs = HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
+
+      chain = reg_where_dead_chain[i];
+      if (reg_where_dead[i] > INSN_SUID (chain->insn))
+	for (j = 0; j < nregs; j++)
+	  chain->inverse_renum_after[regno + j] = i;
+
+      while (INSN_SUID (chain->insn) > reg_where_born_exact[i])
+	{
+	  for (j = 0; j < nregs; j++)
+	    chain->inverse_renum_before[regno + j] = i;
+	  chain = chain->prev;
+	  if (!chain)
+	    break;
+	  for (j = 0; j < nregs; j++)
+	    chain->inverse_renum_after[regno + j] = i;
+	}
+
+      if (INSN_SUID (chain->insn) == reg_where_born_exact[i]
+	  && reg_where_born_clobber[i])
+	for (j = 0; j < nregs; j++)
+	  chain->inverse_renum_before[regno + j] = i;
+    }
+
   if (file)
     dump_flow_info (file);
 }
@@ -461,12 +579,14 @@
    INSN is the current insn, supplied so we can find its suid.  */
 
 static void
-stupid_mark_refs (x, insn)
-     rtx x, insn;
+stupid_mark_refs (x, chain)
+     rtx x;
+     struct insn_chain *chain;
 {
   register RTX_CODE code;
   register char *fmt;
   register int regno, i;
+  rtx insn = chain->insn;
 
   if (x == 0)
     return;
@@ -523,6 +643,12 @@
 
 	      reg_where_born[regno] = where_born;
 
+	      reg_where_born_exact[regno] = INSN_SUID (insn);
+	      reg_where_born_clobber[regno] = (code == CLOBBER);
+
+	      if (reg_where_dead_chain[regno] == 0)
+		reg_where_dead_chain[regno] = chain;
+
 	      /* The reg must live at least one insn even
 		 in it is never again used--because it has to go
 		 in SOME hard reg.  Mark it as dying after the current
@@ -564,9 +690,9 @@
 	 If setting a SUBREG, we treat the entire reg as *used*.  */
       if (code == SET)
 	{
-	  stupid_mark_refs (SET_SRC (x), insn);
+	  stupid_mark_refs (SET_SRC (x), chain);
 	  if (GET_CODE (SET_DEST (x)) != REG)
-	    stupid_mark_refs (SET_DEST (x), insn);
+	    stupid_mark_refs (SET_DEST (x), chain);
 	}
       return;
     }
@@ -600,11 +726,14 @@
 	  /* Pseudo reg: record first use, last use and number of uses.  */
 
 	  reg_where_born[regno] = INSN_SUID (insn);
+	  reg_where_born_exact[regno] = INSN_SUID (insn);
+	  reg_where_born_clobber[regno] = 0;
 	  REG_N_REFS (regno)++;
 	  if (regs_live[regno] == 0)
 	    {
 	      regs_live[regno] = 1;
 	      reg_where_dead[regno] = INSN_SUID (insn);
+	      reg_where_dead_chain[regno] = chain;
 	    }
 	}
       return;
@@ -616,12 +745,12 @@
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e')
-	stupid_mark_refs (XEXP (x, i), insn);
+	stupid_mark_refs (XEXP (x, i), chain);
       if (fmt[i] == 'E')
 	{
 	  register int j;
 	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-	    stupid_mark_refs (XVECEXP (x, i, j), insn);
+	    stupid_mark_refs (XVECEXP (x, i, j), chain);
 	}
     }
 }
Index: config/i386/i386.h
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/config/i386/i386.h,v
retrieving revision 1.1.1.27
diff -u -r1.1.1.27 i386.h
--- config/i386/i386.h	1998/08/03 10:17:34	1.1.1.27
+++ config/i386/i386.h	1998/08/24 17:16:32
@@ -2454,7 +2453,7 @@
  (n) + 4)
 
 /* Before the prologue, RA is at 0(%esp).  */
-#define INCOMING_RETURN_ADDR_RTX \
+#define INCOMING_RETURN_ADDR_RTX__ \
   gen_rtx_MEM (VOIDmode, gen_rtx_REG (VOIDmode, STACK_POINTER_REGNUM))
 
 /* After the prologue, RA is at -4(AP) in the current frame.  */


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