hard register reload patch

Joern Rennecke amylaar@cygnus.co.uk
Wed Jan 26 18:52:00 GMT 2000


> Did you ever send an updated version of this after the first part went in?
> If so, I missed it.

Here is an updated version:

Fri Nov 26 02:44:08 1999  J"orn Rennecke <amylaar@cygnus.co.uk>

	* flow.c (propagate_block): When deleting a dead insn, preserve
	clobbers for registers that are live.

Thu Jan 27 01:42:37 2000  J"orn Rennecke <amylaar@cygnus.co.uk>

	* reload.c (basic-block.h): #include.
	(reload.h):#include after had-reg-set.h & basic-block.h .
	(n_earlyclobbers, reload_earlyclobbers): Now static.
	(combine_reloads): Deleted.
	(push_hard_reload, note_earlyclobbers): New functions.
	(earlyclobber_overlap_p, mentioned_in_operand): Likewise.
	(find_reloads): First parameter is now of type struct insn_chain*.
	Changed all callers.
	Set used_spill_regs to the set of regsisters that die or are set
	in this insn.  Push hard register reloads for these registers.
	* reload.h (n_earlyclobbers, reload_earlyclobbers): Don't declare.
	(find_reloads): Update declaration.
	(earlyclobber_overlap_p): Declare.
	* reload1.c (reg_reloaded_dead, pseudos_counted): Delete.  Reove all
	sets / uses.
	(spill_pseudo, hard_reload_conflict): New functions.
	(mark_regs_outside_operands): Likewise.
	(reload): Call mark_regs_outside_operands.
	(maybe_fix_stack_asms): Don't clear bits in &chain->dead_or_set.
	(order_regs_for_reload): Remove tests of &chain->dead_or_set.
	(find_reg): Look at all reloads for conflicts.
	Call hard_reload_conflict.  Don't test &chain->dead_or_set.
	(find_reload_regs): Call spill_pseudo.
	Don't overwrite used_spill_regs, ior to it.
	(finish_spills): Don't put regs from &chain->dead_or_set into
	pseudo_forbidden_regs.
	instead of chain->live_before and chain->live_after.
	Don't adjust used_spill_regs.
	(reload_reg_unavailable): Delete.
	(reload_reg_free_p): Check reg_used_in_insn, not reload_reg_unavailable.
	(reload_reg_fre_for_value_p): Don't test reload_reg_unavailable.
	In RELOAD_OTHER case, use earlyclobber_overlap_p for earlyclobber test.
	Test for conflicts with hard reloads.
	(allocate_reload_reg): Check reg_used_in_insn, not reload_reg_used.
	(choose_reload_regs_init): Don't put regs from &chain->dead_or_set
	into reg_used_in_insn.  Mark register usage of hard reloads.
	(choose_reload_regs): Use earlyclobber_overlap_p.
	Use search_equiv as value, and NULL_RTX as out to pass to
	reload_reg_free_for_value_p.
	Make action taken for earlyclobber operands dependent on reload type.
	Don't abort for RELOAD_FOR_OUTPUT_ADDRESS hard reloads.
	(emit_output_reload_insns, emit_reload_insns):
	Remove reg_reloaded_dead / reg_relaoded_died code.

Index: flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.209
diff -p -r1.209 flow.c
*** flow.c	2000/01/26 00:54:44	1.209
--- flow.c	2000/01/27 01:38:04
*************** propagate_block (bb, old, significant, f
*** 3347,3352 ****
--- 3347,3381 ----
  		    }
  		}
  
+ 	      /* If INSN contained a clobber of a reg that is live,
+ 		 we must emit a separate clobber for it; otherwise,
+ 		 the register would become live above INSN.
+ 		 This can happen when a function returns no value,
+ 		 and the return register is used as a scratch in INSN -
+ 		 e.g. gcc.c-torture/compile/920829-1.c on SH4.  */
+ 	      if (GET_CODE (PATTERN (insn)) == PARALLEL)
+ 		{
+ 		  rtx pat = PATTERN (insn);
+ 		  int i = XVECLEN (pat, 0);
+ 
+ 		  while (--i >= 0)
+ 		    {
+ 		      rtx part = XVECEXP (pat, 0, i);
+ 		      if (GET_CODE (part) == CLOBBER
+ 			  && GET_CODE (XEXP (part, 0)) == REG
+ 			  && REGNO_REG_SET_P (old, REGNO (XEXP (part, 0))))
+ 			{
+ 			  /* INSN could be the only insn in block BNUM,
+ 			     and we could have more than one clobber that
+ 			     needs emitting, so we can't dodge updating
+ 			     either start or end of the basic block.  */
+ 			  part = emit_insn_after (part, insn);
+ 			  if (bb->end == PREV_INSN (part))
+ 			    bb->end = part;
+ 			}
+ 		    }
+ 		}
+ 
  	      PUT_CODE (insn, NOTE);
  	      NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
  	      NOTE_SOURCE_FILE (insn) = 0;
Index: reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.99
diff -p -r1.99 reload.c
*** reload.c	2000/01/17 15:47:28	1.99
--- reload.c	2000/01/27 02:12:42
*************** a register with any other reload.  */
*** 94,102 ****
  #include "insn-config.h"
  #include "insn-codes.h"
  #include "recog.h"
- #include "reload.h"
  #include "regs.h"
  #include "hard-reg-set.h"
  #include "flags.h"
  #include "real.h"
  #include "output.h"
--- 94,103 ----
  #include "insn-config.h"
  #include "insn-codes.h"
  #include "recog.h"
  #include "regs.h"
  #include "hard-reg-set.h"
+ #include "basic-block.h"
+ #include "reload.h"
  #include "flags.h"
  #include "real.h"
  #include "output.h"
*************** struct reload rld[MAX_RELOADS];
*** 123,130 ****
  
  /* All the "earlyclobber" operands of the current insn
     are recorded here.  */
! int n_earlyclobbers;
! rtx reload_earlyclobbers[MAX_RECOG_OPERANDS];
  
  int reload_n_operands;
  
--- 124,131 ----
  
  /* All the "earlyclobber" operands of the current insn
     are recorded here.  */
! static int n_earlyclobbers;
! static rtx reload_earlyclobbers[MAX_RECOG_OPERANDS];
  
  int reload_n_operands;
  
*************** static enum reg_class find_valid_class P
*** 245,252 ****
  static int push_reload		PARAMS ((rtx, rtx, rtx *, rtx *, enum reg_class,
  				       enum machine_mode, enum machine_mode,
  				       int, int, int, enum reload_type));
  static void push_replacement	PARAMS ((rtx *, int, enum machine_mode));
- static void combine_reloads	PARAMS ((void));
  static int find_reusable_reload	PARAMS ((rtx *, rtx, enum reg_class,
  				       enum reload_type, int, int));
  static rtx find_dummy_reload	PARAMS ((rtx, rtx, rtx *, rtx *,
--- 246,253 ----
  static int push_reload		PARAMS ((rtx, rtx, rtx *, rtx *, enum reg_class,
  				       enum machine_mode, enum machine_mode,
  				       int, int, int, enum reload_type));
+ static void push_hard_reload  PARAMS ((int, int, int, enum reload_type));
  static void push_replacement	PARAMS ((rtx *, int, enum machine_mode));
  static int find_reusable_reload	PARAMS ((rtx *, rtx, enum reg_class,
  				       enum reload_type, int, int));
  static rtx find_dummy_reload	PARAMS ((rtx, rtx, rtx *, rtx *,
*************** static int find_inc_amount	PARAMS ((rtx,
*** 273,278 ****
--- 274,281 ----
  static int loc_mentioned_in_p	PARAMS ((rtx *, rtx));
  extern void debug_reload_to_stream PARAMS ((FILE *));
  extern void debug_reload PARAMS ((void));
+ static void note_earlyclobbers PARAMS ((rtx, rtx, void *));
+ static int mentioned_in_operand PARAMS ((rtx *, void *));
  
  #ifdef HAVE_SECONDARY_RELOADS
  
*************** push_reload (in, out, inloc, outloc, cla
*** 1481,1486 ****
--- 1484,1547 ----
    return i;
  }
  
+ /* Indicate that the hard register with register number REGNO is in use
+    for operand OPNUM, using a TYPE reload.  If IN_P is set, use
+    rld[].in / in_reg, otherwise rld[].out / out_reg.  */
+ static void
+ push_hard_reload (in_p, regno, opnum, type)
+      int in_p;
+      int regno;
+      int opnum;
+      enum reload_type type;
+ {
+   rtx x;
+   rtx in, out;
+   int i;
+   enum reg_class class = REGNO_REG_CLASS (regno);
+   enum machine_mode mode = reg_raw_mode[regno];
+ 
+   x = gen_rtx_REG (mode, regno);
+     x = gen_rtx_REG (GET_MODE (x), true_regnum (x));
+   if (in_p)
+     {
+       in = x;
+       out = NULL_RTX;
+     }
+   else
+     {
+       out = x;
+       in = NULL_RTX;
+     }
+ 
+   /* We want a specific reload register to be reserved for type / opnum,
+      thus re-using another reload is just asking for trouble.
+      So unconditionally add a new reload.  */
+ 
+   i = n_reloads;
+   rld[i].in = in;
+   rld[i].out = out;
+   rld[i].class = class;
+   rld[i].inmode = in_p ? mode : VOIDmode;
+   rld[i].outmode = in_p ? VOIDmode : mode;
+   rld[i].reg_rtx = x;
+   rld[i].optional = 0;
+   rld[i].nongroup = 0;
+   rld[i].inc = 0;
+   rld[i].nocombine = 0;
+   rld[i].in_reg = in;
+   rld[i].out_reg = out;
+   rld[i].opnum = opnum;
+   rld[i].when_needed = type;
+   rld[i].secondary_in_reload = -1;
+   rld[i].secondary_out_reload = -1;
+   rld[i].secondary_in_icode = CODE_FOR_nothing;
+   rld[i].secondary_out_icode = CODE_FOR_nothing;
+   rld[i].secondary_p = 0;
+   rld[i].reg_rtx = x;
+ 
+   n_reloads++;
+ }
+ 
  /* Record an additional place we must replace a value
     for which we have already recorded a reload.
     RELOADNUM is the value returned by push_reload
*************** loc_mentioned_in_p (loc, in)
*** 1582,1764 ****
    return 0;
  }
  
- /* If there is only one output reload, and it is not for an earlyclobber
-    operand, try to combine it with a (logically unrelated) input reload
-    to reduce the number of reload registers needed.
- 
-    This is safe if the input reload does not appear in
-    the value being output-reloaded, because this implies
-    it is not needed any more once the original insn completes.
- 
-    If that doesn't work, see we can use any of the registers that
-    die in this insn as a reload register.  We can if it is of the right
-    class and does not appear in the value being output-reloaded.  */
- 
- static void
- combine_reloads ()
- {
-   int i;
-   int output_reload = -1;
-   int secondary_out = -1;
-   rtx note;
- 
-   /* Find the output reload; return unless there is exactly one
-      and that one is mandatory.  */
- 
-   for (i = 0; i < n_reloads; i++)
-     if (rld[i].out != 0)
-       {
- 	if (output_reload >= 0)
- 	  return;
- 	output_reload = i;
-       }
- 
-   if (output_reload < 0 || rld[output_reload].optional)
-     return;
- 
-   /* An input-output reload isn't combinable.  */
- 
-   if (rld[output_reload].in != 0)
-     return;
- 
-   /* If this reload is for an earlyclobber operand, we can't do anything.  */
-   if (earlyclobber_operand_p (rld[output_reload].out))
-     return;
- 
-   /* Check each input reload; can we combine it?  */
- 
-   for (i = 0; i < n_reloads; i++)
-     if (rld[i].in && ! rld[i].optional && ! rld[i].nocombine
- 	/* Life span of this reload must not extend past main insn.  */
- 	&& rld[i].when_needed != RELOAD_FOR_OUTPUT_ADDRESS
- 	&& rld[i].when_needed != RELOAD_FOR_OUTADDR_ADDRESS
- 	&& rld[i].when_needed != RELOAD_OTHER
- 	&& (CLASS_MAX_NREGS (rld[i].class, rld[i].inmode)
- 	    == CLASS_MAX_NREGS (rld[output_reload].class,
- 				rld[output_reload].outmode))
- 	&& rld[i].inc == 0
- 	&& rld[i].reg_rtx == 0
- #ifdef SECONDARY_MEMORY_NEEDED
- 	/* Don't combine two reloads with different secondary
- 	   memory locations.  */
- 	&& (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum] == 0
- 	    || secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum] == 0
- 	    || rtx_equal_p (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum],
- 			    secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum]))
- #endif
- 	&& (SMALL_REGISTER_CLASSES
- 	    ? (rld[i].class == rld[output_reload].class)
- 	    : (reg_class_subset_p (rld[i].class,
- 				   rld[output_reload].class)
- 	       || reg_class_subset_p (rld[output_reload].class,
- 				      rld[i].class)))
- 	&& (MATCHES (rld[i].in, rld[output_reload].out)
- 	    /* Args reversed because the first arg seems to be
- 	       the one that we imagine being modified
- 	       while the second is the one that might be affected.  */
- 	    || (! reg_overlap_mentioned_for_reload_p (rld[output_reload].out,
- 						      rld[i].in)
- 		/* However, if the input is a register that appears inside
- 		   the output, then we also can't share.
- 		   Imagine (set (mem (reg 69)) (plus (reg 69) ...)).
- 		   If the same reload reg is used for both reg 69 and the
- 		   result to be stored in memory, then that result
- 		   will clobber the address of the memory ref.  */
- 		&& ! (GET_CODE (rld[i].in) == REG
- 		      && reg_overlap_mentioned_for_reload_p (rld[i].in,
- 							     rld[output_reload].out))))
- 	&& (reg_class_size[(int) rld[i].class]
- 	    || SMALL_REGISTER_CLASSES)
- 	/* We will allow making things slightly worse by combining an
- 	   input and an output, but no worse than that.  */
- 	&& (rld[i].when_needed == RELOAD_FOR_INPUT
- 	    || rld[i].when_needed == RELOAD_FOR_OUTPUT))
-       {
- 	int j;
- 
- 	/* We have found a reload to combine with!  */
- 	rld[i].out = rld[output_reload].out;
- 	rld[i].out_reg = rld[output_reload].out_reg;
- 	rld[i].outmode = rld[output_reload].outmode;
- 	/* Mark the old output reload as inoperative.  */
- 	rld[output_reload].out = 0;
- 	/* The combined reload is needed for the entire insn.  */
- 	rld[i].when_needed = RELOAD_OTHER;
- 	/* If the output reload had a secondary reload, copy it.  */
- 	if (rld[output_reload].secondary_out_reload != -1)
- 	  {
- 	    rld[i].secondary_out_reload
- 	      = rld[output_reload].secondary_out_reload;
- 	    rld[i].secondary_out_icode
- 	      = rld[output_reload].secondary_out_icode;
- 	  }
- 
- #ifdef SECONDARY_MEMORY_NEEDED
- 	/* Copy any secondary MEM.  */
- 	if (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum] != 0)
- 	  secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum]
- 	    = secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum];
- #endif
- 	/* If required, minimize the register class.  */
- 	if (reg_class_subset_p (rld[output_reload].class,
- 				rld[i].class))
- 	  rld[i].class = rld[output_reload].class;
- 
- 	/* Transfer all replacements from the old reload to the combined.  */
- 	for (j = 0; j < n_replacements; j++)
- 	  if (replacements[j].what == output_reload)
- 	    replacements[j].what = i;
- 
- 	return;
-       }
- 
-   /* If this insn has only one operand that is modified or written (assumed
-      to be the first),  it must be the one corresponding to this reload.  It
-      is safe to use anything that dies in this insn for that output provided
-      that it does not occur in the output (we already know it isn't an
-      earlyclobber.  If this is an asm insn, give up.  */
- 
-   if (INSN_CODE (this_insn) == -1)
-     return;
- 
-   for (i = 1; i < insn_data[INSN_CODE (this_insn)].n_operands; i++)
-     if (insn_data[INSN_CODE (this_insn)].operand[i].constraint[0] == '='
- 	|| insn_data[INSN_CODE (this_insn)].operand[i].constraint[0] == '+')
-       return;
- 
-   /* See if some hard register that dies in this insn and is not used in
-      the output is the right class.  Only works if the register we pick
-      up can fully hold our output reload.  */
-   for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))
-     if (REG_NOTE_KIND (note) == REG_DEAD
- 	&& GET_CODE (XEXP (note, 0)) == REG
- 	&& ! reg_overlap_mentioned_for_reload_p (XEXP (note, 0),
- 						 rld[output_reload].out)
- 	&& REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
- 	&& HARD_REGNO_MODE_OK (REGNO (XEXP (note, 0)), rld[output_reload].outmode)
- 	&& TEST_HARD_REG_BIT (reg_class_contents[(int) rld[output_reload].class],
- 			      REGNO (XEXP (note, 0)))
- 	&& (HARD_REGNO_NREGS (REGNO (XEXP (note, 0)), rld[output_reload].outmode)
- 	    <= HARD_REGNO_NREGS (REGNO (XEXP (note, 0)), GET_MODE (XEXP (note, 0))))
- 	/* Ensure that a secondary or tertiary reload for this output
- 	   won't want this register.  */
- 	&& ((secondary_out = rld[output_reload].secondary_out_reload) == -1
- 	    || (! (TEST_HARD_REG_BIT
- 		   (reg_class_contents[(int) rld[secondary_out].class],
- 		    REGNO (XEXP (note, 0))))
- 		&& ((secondary_out = rld[secondary_out].secondary_out_reload) == -1
- 		    ||  ! (TEST_HARD_REG_BIT
- 			   (reg_class_contents[(int) rld[secondary_out].class],
- 			    REGNO (XEXP (note, 0)))))))
- 	&& ! fixed_regs[REGNO (XEXP (note, 0))])
-       {
- 	rld[output_reload].reg_rtx
- 	  = gen_rtx_REG (rld[output_reload].outmode,
- 			 REGNO (XEXP (note, 0)));
- 	return;
-       }
- }
- 
  /* Try to find a reload register for an in-out reload (expressions IN and OUT).
     See if one of IN and OUT is a register that may be used;
     this is desirable since a spill-register won't be needed.
--- 1643,1648 ----
*************** earlyclobber_operand_p (x)
*** 1934,1939 ****
--- 1818,1839 ----
    return 0;
  }
  
+ /* Return 1 if X overlaps an operand that is being earlyclobbered.  */
+ 
+ int
+ earlyclobber_overlap_p (x)
+      rtx x;
+ {               
+   int i;
+ 
+   for (i = 0; i < n_earlyclobbers; i++)
+     {
+       if (reg_overlap_mentioned_for_reload_p (x, reload_earlyclobbers[i]))
+ 	return 1;
+     }
+   return 0;
+ }
+ 
  /* Return 1 if expression X alters a hard reg in the range
     from BEG_REGNO (inclusive) to END_REGNO (exclusive),
     either explicitly or in the guise of a pseudo-reg allocated to REGNO.
*************** safe_from_earlyclobber (op, clobber)
*** 2325,2332 ****
    early_data = decompose (clobber);
    return immune_p (op, clobber, early_data);
  }
  
! /* Main entry point of this file: search the body of INSN
     for values that need reloading and record them with push_reload.
     REPLACE nonzero means record also where the values occur
     so that subst_reloads can be used.
--- 2225,2275 ----
    early_data = decompose (clobber);
    return immune_p (op, clobber, early_data);
  }
+ 
+ /* Called via for_each_rtx; We look for a hard register *(int*)REGNOP in a
+    piece of rtl *XP from an instruction that has just been recognized.
+    When a match is found, store its address in *(rtx **)regnop.  */
+ static int
+ mentioned_in_operand (xp, regnop)
+      rtx *xp;
+      void *regnop;
+ {
+   rtx x = *xp;
+ 
+   if (GET_CODE (x) == REG
+       || (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == REG))
+     {
+       int regno = * (int *) regnop;
+       if (refers_to_regno_p (regno, regno + 1, x, NULL_PTR))
+ 	{
+ 	  *(rtx**)regnop = xp;
+ 	  return 1;
+ 	}
+     }
+   return 0;
+ }
+ 
+ /* Called from find_reloads via note_stores.  N_OPERAND_EARLYCLOBBERS
+ points to an integer that says how many earlyclobbers have been found
+ in the operands of the current insn.  If we find a clobber that was
+ not noted in the first N_OPERAND_EARLYCLOBBERS in RELOAD_EARLYCLOBBERS,
+ add it to the ones noted in RELOAD_EARLYCLOBBERS.  */
+ static void
+ note_earlyclobbers (x, setter, n_operand_earlyclobbers)
+      rtx x, setter;
+      void *n_operand_earlyclobbers;
+ {
+   int i;
+ 
+   if (GET_CODE (setter) != CLOBBER)
+     return;
+   for (i = *(int *) n_operand_earlyclobbers; i >= 0; i--)
+     if (reload_earlyclobbers[i] == x)
+       return;
+   reload_earlyclobbers[n_earlyclobbers++] = XEXP (setter, 0);
+ }
  
! /* Main entry point of this file: search the body of CHAIN->INSN
     for values that need reloading and record them with push_reload.
     REPLACE nonzero means record also where the values occur
     so that subst_reloads can be used.
*************** safe_from_earlyclobber (op, clobber)
*** 2349,2360 ****
     commutative operands, reg_equiv_address substitution, or whatever.  */
  
  int
! find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
!      rtx insn;
       int replace, ind_levels;
       int live_known;
       short *reload_reg_p;
  {
    register int insn_code_number;
    register int i, j;
    int noperands;
--- 2292,2304 ----
     commutative operands, reg_equiv_address substitution, or whatever.  */
  
  int
! find_reloads (chain, replace, ind_levels, live_known, reload_reg_p)
!      struct insn_chain *chain;
       int replace, ind_levels;
       int live_known;
       short *reload_reg_p;
  {
+   rtx insn = chain->insn;
    register int insn_code_number;
    register int i, j;
    int noperands;
*************** find_reloads (insn, replace, ind_levels,
*** 2400,2405 ****
--- 2344,2351 ----
    int goal_earlyclobber = 0, this_earlyclobber;
    enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
    int retval = 0;
+   int n_operand_earlyclobbers;
+   HARD_REG_SET live_throughout;
  
    this_insn = insn;
    n_reloads = 0;
*************** find_reloads (insn, replace, ind_levels,
*** 2409,2414 ****
--- 2355,2372 ----
    hard_regs_live_known = live_known;
    static_reload_reg_p = reload_reg_p;
  
+   /* Registers that die or are set in
+      this insn are 'free' spill regs.  */
+   REG_SET_TO_HARD_REG_SET (chain->used_spill_regs, &chain->dead_or_set);
+   compute_use_by_pseudos (&chain->used_spill_regs, &chain->dead_or_set);
+ 
+   /* However, since global can now allocate multiple pseudos to one
+      hard reg at a time (when all but one pseudo is uninitialized),
+   we must exclude any hard regs that are live due to another pseudo.  */
+   REG_SET_TO_HARD_REG_SET (live_throughout, &chain->live_throughout);
+   compute_use_by_pseudos (&live_throughout, &chain->live_throughout);
+   AND_COMPL_HARD_REG_SET(chain->used_spill_regs, live_throughout);
+ 
    /* JUMP_INSNs and CALL_INSNs are not allowed to have any output reloads;
       neither are insns that SET cc0.  Insns that use CC0 are not allowed
       to have any input reloads.  */
*************** find_reloads (insn, replace, ind_levels,
*** 2567,2573 ****
  		  || GET_CODE (recog_data.operand[i]) == PLUS))
  	    {
  	      INSN_CODE (insn) = -1;
! 	      retval = find_reloads (insn, replace, ind_levels, live_known,
  				     reload_reg_p);
  	      return retval;
  	    }
--- 2525,2531 ----
  		  || GET_CODE (recog_data.operand[i]) == PLUS))
  	    {
  	      INSN_CODE (insn) = -1;
! 	      retval = find_reloads (chain, replace, ind_levels, live_known,
  				     reload_reg_p);
  	      return retval;
  	    }
*************** find_reloads (insn, replace, ind_levels,
*** 3553,3558 ****
--- 3511,3518 ----
      for (i = 0; i < noperands; i++)
        if (goal_alternative_earlyclobber[i])
  	reload_earlyclobbers[n_earlyclobbers++] = recog_data.operand[i];
+   n_operand_earlyclobbers = n_earlyclobbers;
+   note_stores (PATTERN (insn), note_earlyclobbers, &n_operand_earlyclobbers);
  
    /* Now record reloads for all the operands that need them.  */
    for (i = 0; i < noperands; i++)
*************** find_reloads (insn, replace, ind_levels,
*** 3838,3848 ****
  	  rld[i].in = rld[i].reg_rtx;
        }
  #endif
  
!   /* Perhaps an output reload can be combined with another
!      to reduce needs by one.  */
!   if (!goal_earlyclobber)
!     combine_reloads ();
  
    /* If we have a pair of reloads for parts of an address, they are reloading
       the same object, the operands themselves were not reloaded, and they
--- 3798,3930 ----
  	  rld[i].in = rld[i].reg_rtx;
        }
  #endif
+ 
+   /* If a hard register dies or is born in the insn, record dummy reloads
+      for it.  Some insn have hard register inputs or outputs and these
+      should be noted as RELOAD_FOR_INPUT / RELOAD_FOR_OUTPUT, respectively,
+      to avoid artificial spill register shortage.
+      We don't have to register these uses if there are no reloads otherwise.
+      If the use is outside the operands, we generate a RELOAD_OTHER - to make
+      an insn use more fine-tuned reloads, you have to use a match_operand.  */
+     
+   if (n_reloads)
+     {
+       int next_reg;
+       int n_ordinary_reloads = n_reloads;
+       if (GET_CODE (insn) == CALL_INSN)
+ 	{
+ 	  rtx link;
+ 
+ 	  for (link = CALL_INSN_FUNCTION_USAGE (insn); link;
+ 	       link = XEXP (link, 1))
+ 	    {
+ 	      rtx op = XEXP (link, 0);
+ 	      rtx reg;
+ 	      int in_p, regno, endregno;
+ 
+ 	      if (GET_CODE (op) != USE && GET_CODE (op) != CLOBBER)
+ 		continue;
+ 	      reg = XEXP (op, 0);
+ 	      if (GET_CODE (reg) != REG)
+ 		continue;
+ 
+ 	      in_p = GET_CODE (op) == USE;
+ 	      regno = REGNO (reg);
+ 	      endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ 
+ 	      for (i = regno; i < endregno; i = next_reg)
+ 		{
+ 		  next_reg = i + 1;
+ 		  if (! TEST_HARD_REG_BIT (chain->used_spill_regs, i))
+ 		    continue;
+ 		  next_reg = i + HARD_REGNO_NREGS (i, reg_raw_mode[i]);
+ 		  goal_alternative_matches[noperands] = -1;
+ 		  reload_n_operands = noperands + 1;
+ 		  push_hard_reload (in_p, i, noperands,
+ 				    (in_p
+ 				     ? RELOAD_FOR_INPUT : RELOAD_FOR_OUTPUT));
+ 		}
+ 	    }
+ 	}
+ 
+       for (i = 0; i < FIRST_PSEUDO_REGISTER; i = next_reg)
+ 	{
+ 	  union { int i; rtx *p; } u;
+ 
+ 	  next_reg = i + 1;
+ 
+ 	  if (! TEST_HARD_REG_BIT (chain->used_spill_regs, i))
+ 	    continue;
+ 
+ 	  next_reg = i + HARD_REGNO_NREGS (i, reg_raw_mode[i]);
  
! 	  u.i = i;
! 
! 	  for (j = 0; j < noperands; j++)
! 	    {
! 	      rtx op = recog_data.operand[j];
! 	      enum reload_type type;
! 	      int in_p, out_p;
! 
! 	      u.i = i;
! 	      if (! for_each_rtx (recog_data.operand_loc[j],
! 				  mentioned_in_operand, &u))
! 		continue;
! 
! 	      out_p = recog_data.operand_loc[j] == u.p;
! 
! 	      while (GET_CODE (op) == SUBREG
! 		     || GET_CODE (op) == SIGN_EXTRACT
! 		     || GET_CODE (op) == ZERO_EXTRACT
! 		     || GET_CODE (op) == STRICT_LOW_PART)
! 		{
! 		  out_p |= &XEXP (op, 0) == u.p;
! 		  op = XEXP (op, 0);
! 		}
! 
! 	      out_p &= modified[j] != RELOAD_READ;
! 	      in_p = ! out_p || modified[j] != RELOAD_WRITE;
! 
! 	      if (GET_CODE (op) == REG && constraints[j][0] != 'p')
! 		{
! 		  int k;
! 
! 		  type = operand_type[j];
! 		  /* Check if this hard reg is already reloaded by an ordinary
! 		     reload.  We can't use the replacements array here because
! 		     that doesn't work when REPLACE is zero.  */
! 		  for (k = n_ordinary_reloads - 1; k >= 0; k--)
! 		    {
! 		      if (rld[k].opnum == j && ! rld[k].secondary_p
! 			  && ((in_p
! 			       && (rld[k].in == *u.p
! 				   || loc_mentioned_in_p (u.p, rld[k].in)))
! 			      || (out_p
! 				  && (rld[k].out == *u.p
! 				      || loc_mentioned_in_p (u.p,
! 							     rld[k].out)))))
! 			{
! 			  /* This is like a secondary reload.  */
! 			  type = address_type[j];
! 			  if (type == RELOAD_OTHER)
! 			    type = (in_p
! 				    ? RELOAD_FOR_INPUT_ADDRESS
! 				    : RELOAD_FOR_OUTPUT_ADDRESS);
! 			  break;
! 			}
! 		    }
! 		}
! 	      else
! 		type = address_type[j];
! 	      push_hard_reload (in_p, i, j, type);
! 	      if (in_p && out_p)
! 		push_hard_reload (0, i, j,
! 				  (type == RELOAD_FOR_INPUT_ADDRESS
! 				   ? RELOAD_FOR_OUTPUT_ADDRESS
! 				   : type));
! 	    }
! 	}
!     }
  
    /* If we have a pair of reloads for parts of an address, they are reloading
       the same object, the operands themselves were not reloaded, and they
Index: reload.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.h,v
retrieving revision 1.26
diff -p -r1.26 reload.h
*** reload.h	2000/01/17 17:16:19	1.26
--- reload.h	2000/01/27 01:38:07
*************** Boston, MA 02111-1307, USA.  */
*** 29,34 ****
--- 29,36 ----
    SECONDARY_RELOAD_CLASS (CLASS, MODE, X)
  #endif
  
+ struct insn_chain;
+ 
  /* If either macro is defined, show that we need secondary reloads.  */
  #if defined(SECONDARY_INPUT_RELOAD_CLASS) || defined(SECONDARY_OUTPUT_RELOAD_CLASS)
  #define HAVE_SECONDARY_RELOADS
*************** extern rtx *reg_equiv_memory_loc;
*** 168,178 ****
  extern rtx *reg_equiv_address;
  extern rtx *reg_equiv_mem;
  
- /* All the "earlyclobber" operands of the current insn
-    are recorded here.  */
- extern int n_earlyclobbers;
- extern rtx reload_earlyclobbers[MAX_RECOG_OPERANDS];
- 
  /* Save the number of operands.  */
  extern int reload_n_operands;
  
--- 170,175 ----
*************** extern int safe_from_earlyclobber PARAMS
*** 291,297 ****
  /* Search the body of INSN for values that need reloading and record them
     with push_reload.  REPLACE nonzero means record also where the values occur
     so that subst_reloads can be used.  */
! extern int find_reloads PARAMS ((rtx, int, int, int, short *));
  
  /* Compute the sum of X and Y, making canonicalizations assumed in an
     address, namely: sum constant integers, surround the sum of two
--- 288,294 ----
  /* Search the body of INSN for values that need reloading and record them
     with push_reload.  REPLACE nonzero means record also where the values occur
     so that subst_reloads can be used.  */
! extern int find_reloads PARAMS ((struct insn_chain *, int, int, int, short *));
  
  /* Compute the sum of X and Y, making canonicalizations assumed in an
     address, namely: sum constant integers, surround the sum of two
*************** extern int regno_clobbered_p PARAMS ((in
*** 337,342 ****
--- 334,342 ----
  
  /* Return 1 if X is an operand of an insn that is being earlyclobbered.  */
  int earlyclobber_operand_p PARAMS ((rtx));
+ 
+ /* Return 1 if X overlaps an operand that is being earlyclobbered.  */
+ int earlyclobber_overlap_p PARAMS ((rtx));
  
  /* Functions in reload1.c:  */
  
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.197
diff -p -r1.197 reload1.c
*** reload1.c	2000/01/17 15:47:28	1.197
--- reload1.c	2000/01/27 01:38:09
*************** static rtx reg_reloaded_insn[FIRST_PSEUD
*** 140,148 ****
  
  /* Indicate if reg_reloaded_insn / reg_reloaded_contents is valid */
  static HARD_REG_SET reg_reloaded_valid;
- /* Indicate if the register was dead at the end of the reload.
-    This is only valid if reg_reloaded_contents is set and valid.  */
- static HARD_REG_SET reg_reloaded_dead;
  
  /* Number of spill-regs so far; number of valid elements of spill_regs.  */
  static int n_spills;
--- 140,145 ----
*************** static short spill_reg_order[FIRST_PSEUD
*** 173,180 ****
  
  /* This reg set indicates registers that can't be used as spill registers for
     the currently processed insn.  These are the hard registers which are live
!    during the insn, but not allocated to pseudos, as well as fixed
!    registers.  */
  static HARD_REG_SET bad_spill_regs;
  
  /* These are the hard registers that can't be used as spill register for any
--- 170,177 ----
  
  /* This reg set indicates registers that can't be used as spill registers for
     the currently processed insn.  These are the hard registers which are live
!    during the insn, but not allocated to pseudos, dying, or set, as well as
!    fixed registers.  */
  static HARD_REG_SET bad_spill_regs;
  
  /* These are the hard registers that can't be used as spill register for any
*************** static int spill_stack_slot_width[FIRST_
*** 240,249 ****
  /* Record which pseudos needed to be spilled.  */
  static regset_head spilled_pseudos;
  
- /* Used for communication between order_regs_for_reload and count_pseudo.
-    Used to avoid counting one pseudo twice.  */
- static regset_head pseudos_counted;
- 
  /* First uid used by insns created by reload in this function.
     Used in find_equiv_reg.  */
  int reload_first_uid;
--- 237,242 ----
*************** static void find_reload_regs		PARAMS ((s
*** 375,380 ****
--- 368,374 ----
  static void select_reload_regs		PARAMS ((FILE *));
  static void delete_caller_save_insns	PARAMS ((void));
  
+ static int spill_pseudo			PARAMS ((regset, enum reg_class));
  static void spill_failure		PARAMS ((rtx, enum reg_class));
  static void count_spilled_pseudo	PARAMS ((int, int, int));
  static void delete_dead_insn		PARAMS ((rtx));
*************** static int reload_reg_free_p		PARAMS ((i
*** 408,413 ****
--- 402,408 ----
  static int reload_reg_free_for_value_p	PARAMS ((int, int, enum reload_type,
  					       rtx, rtx, int, int));
  static int reload_reg_reaches_end_p	PARAMS ((int, int, enum reload_type));
+ static int hard_reload_conflict		PARAMS ((int, int));
  static int allocate_reload_reg		PARAMS ((struct insn_chain *, int, int));
  static void failed_reload		PARAMS ((rtx, int));
  static int set_reload_reg		PARAMS ((int, int));
*************** static rtx gen_mode_int			PARAMS ((enum 
*** 452,457 ****
--- 447,453 ----
  static void failed_reload		PARAMS ((rtx, int));
  static int set_reload_reg		PARAMS ((int, int));
  extern void dump_needs			PARAMS ((struct insn_chain *, FILE *));
+ static int mark_regs_outside_operands	PARAMS ((rtx *, void *));
  
  /* Initialize the reload pass once per compilation.  */
  
*************** init_reload ()
*** 506,512 ****
    reload_startobj = (char *) obstack_alloc (&reload_obstack, 0);
  
    INIT_REG_SET (&spilled_pseudos);
-   INIT_REG_SET (&pseudos_counted);
  }
  
  /* List of insn chains that are currently unused.  */
--- 502,507 ----
*************** compute_use_by_pseudos (to, from)
*** 567,572 ****
--- 562,609 ----
  	 }
       });
  }
+ 
+ /* Called via for_each_rtx; We look for a registers in a
+    piece of rtl *XP from an instruction that has just been recognized.
+    *XP is not inside an operand (but it may be one).  Do not look at
+    operands of the recognized insn.
+    LIVE_THROUGHOUT is actually a regset.
+    Include all register numbers found in LIVE_THROUGHOUT.  */
+ 
+ static int
+ mark_regs_outside_operands (xp, live_throughout)
+      rtx *xp;
+      void *live_throughout;
+ {
+   int i;
+   rtx x, reg;
+ 
+   for (i = recog_data.n_operands - 1; i >= 0; i--)
+     {
+       if (xp == recog_data.operand_loc[i])
+       return -1;
+     }
+   x = *xp;
+   reg = x;
+   if (GET_CODE (x) == SUBREG)
+     reg = SUBREG_REG (x);
+   if (GET_CODE (reg) == REG)
+     {
+       int regno = REGNO (reg);
+ 
+       if (regno < FIRST_PSEUDO_REGISTER)
+ 	{
+ 	  int nregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
+ 
+ 	  do
+ 	    SET_REGNO_REG_SET ((regset) live_throughout, regno++);
+ 	  while (--nregs);
+ 	}
+       else if (reg_renumber[regno] >= 0)
+ 	SET_REGNO_REG_SET ((regset) live_throughout, regno);
+     }
+   return 0;
+ }
  
  /* Global variables used by reload and its subroutines.  */
  
*************** reload (first, global, dumpfile)
*** 605,610 ****
--- 642,649 ----
    register int i;
    register rtx insn;
    register struct elim_table *ep;
+   struct insn_chain *chain;
+ 
  
    /* The two pointers used to track the true location of the memory used
       for label offsets.  */
*************** reload (first, global, dumpfile)
*** 772,777 ****
--- 811,829 ----
  	scan_paradoxical_subregs (PATTERN (insn));
      }
  
+   /* Note which register operands are life throughout each insn.  */
+   for (chain = reload_insn_chain; chain; chain = chain->next)
+     {
+       if (GET_RTX_CLASS (GET_CODE (chain->insn)) == 'i')
+ 	{
+ 	  int i;
+ 
+ 	  extract_insn (chain->insn);
+ 	  for_each_rtx (&PATTERN (chain->insn), mark_regs_outside_operands,
+ 			&chain->live_throughout);
+ 	}
+     }
+ 
    init_elim_table ();
  
    num_labels = max_label_num () - get_first_label_num ();
*************** maybe_fix_stack_asms ()
*** 1304,1310 ****
  	if (TEST_HARD_REG_BIT (allowed, i))
  	  {
  	    CLEAR_REGNO_REG_SET (&chain->live_throughout, i);
- 	    CLEAR_REGNO_REG_SET (&chain->dead_or_set, i);
  	  }
      }
  
--- 1356,1361 ----
*************** calculate_needs_all_insns (global)
*** 1377,1383 ****
  	    did_elimination = eliminate_regs_in_insn (insn, 0);
  
  	  /* Analyze the instruction.  */
! 	  operands_changed = find_reloads (insn, 0, spill_indirect_levels,
  					   global, spill_reg_order);
  
  	  /* If a no-op set needs more than one reload, this is likely
--- 1428,1434 ----
  	    did_elimination = eliminate_regs_in_insn (insn, 0);
  
  	  /* Analyze the instruction.  */
! 	  operands_changed = find_reloads (chain, 0, spill_indirect_levels,
  					   global, spill_reg_order);
  
  	  /* If a no-op set needs more than one reload, this is likely
*************** calculate_needs_all_insns (global)
*** 1433,1438 ****
--- 1484,1542 ----
    *pprev_reload = 0;
  }
  
+ /* Try to find pseudo in DEAD_OR_SET that contains has a hard register in
+    CLASS allocated it.  If successful, add it to spilled_pseudos, and
+    return 1.  */
+ static int
+ spill_pseudo (dead_or_set, class)
+      regset dead_or_set;
+      enum reg_class class;
+ {
+   int pseudo;
+   int best_reg = -1;
+   unsigned long best_cost = ~0L;
+ 
+   /* We kick out the least-used pseudo that contains a hard
+      register of the desired class.  We don't strive to kick
+      out all pseudos that live on that hard register, since
+      just kicking out one pseudo might already satisfy our
+      requirements.  */
+   /* ??? We could refine this further by only kicking out pseudos
+      that are actually live during lifetime of the requested
+      reload; i.e. for a RELOAD_FOR_INPUT we'd want to kick out a
+      pseudo that dies, but for a RELOAD_FOR_OUTPUT we'd want to
+      kick out a pseudo that is set.  But for that we'd have to
+      record separately which pseudos are set and which die.
+      For now, we assume it's not worth the hassle.  */
+   EXECUTE_IF_SET_IN_REG_SET
+     (dead_or_set, FIRST_PSEUDO_REGISTER, pseudo,
+      {
+        int r = reg_renumber[pseudo];
+        int n = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (pseudo));
+        unsigned long cost = REG_N_REFS (pseudo) * n;
+ 
+        if (cost < best_cost)
+ 	 {
+ 	   do
+ 	     n--;
+ 	   while (n >= 0
+ 		  && ! TEST_HARD_REG_BIT (reg_class_contents[class],
+ 					  n+r));
+ 	   if (n >= 0)
+ 	     {
+ 	       best_cost = cost;
+ 	       best_reg = pseudo;
+ 	     }
+ 	 }
+      });
+   if (best_reg >= 0)
+     {
+       SET_REGNO_REG_SET (&spilled_pseudos, best_reg);
+       return 1;
+     }
+   return 0;
+ }
+ 
  /* Comparison function for qsort to decide which of two reloads
     should be handled first.  *P1 and *P2 are the reload numbers.  */
  
*************** count_pseudo (reg)
*** 1487,1498 ****
    int r = reg_renumber[reg];
    int nregs;
  
!   if (REGNO_REG_SET_P (&pseudos_counted, reg)
!       || REGNO_REG_SET_P (&spilled_pseudos, reg))
      return;
  
-   SET_REGNO_REG_SET (&pseudos_counted, reg);
- 
    if (r < 0)
      abort ();
    
--- 1591,1599 ----
    int r = reg_renumber[reg];
    int nregs;
  
!   if (REGNO_REG_SET_P (&spilled_pseudos, reg))
      return;
  
    if (r < 0)
      abort ();
    
*************** order_regs_for_reload (chain)
*** 1524,1548 ****
        /* Test the various reasons why we can't use a register for
  	 spilling in this insn.  */
        if (fixed_regs[i]
! 	  || REGNO_REG_SET_P (&chain->live_throughout, i)
! 	  || REGNO_REG_SET_P (&chain->dead_or_set, i))
  	SET_HARD_REG_BIT (bad_spill_regs, i);
      }
    /* Now find out which pseudos are allocated to it, and update
       hard_reg_n_uses.  */
-   CLEAR_REG_SET (&pseudos_counted);
  
    EXECUTE_IF_SET_IN_REG_SET
      (&chain->live_throughout, FIRST_PSEUDO_REGISTER, j,
       {
         count_pseudo (j);
       });
-   EXECUTE_IF_SET_IN_REG_SET
-     (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, j,
-      {
-        count_pseudo (j);
-      });
-   CLEAR_REG_SET (&pseudos_counted);
  }
  
  /* Vector of reload-numbers showing the order in which the reloads should
--- 1625,1641 ----
        /* Test the various reasons why we can't use a register for
  	 spilling in this insn.  */
        if (fixed_regs[i]
! 	  || REGNO_REG_SET_P (&chain->live_throughout, i))
  	SET_HARD_REG_BIT (bad_spill_regs, i);
      }
    /* Now find out which pseudos are allocated to it, and update
       hard_reg_n_uses.  */
  
    EXECUTE_IF_SET_IN_REG_SET
      (&chain->live_throughout, FIRST_PSEUDO_REGISTER, j,
       {
         count_pseudo (j);
       });
  }
  
  /* Vector of reload-numbers showing the order in which the reloads should
*************** find_reg (chain, order, dumpfile)
*** 1595,1606 ****
    IOR_COMPL_HARD_REG_SET (not_usable, reg_class_contents[rl->class]);
  
    CLEAR_HARD_REG_SET (used_by_other_reload);
!   for (i = 0; i < order; i++)
      {
!       int other = reload_order[i];
!       if (rld[other].regno >= 0 && reloads_conflict (other, rnum))
! 	for (j = 0; j < rld[other].nregs; j++)
! 	  SET_HARD_REG_BIT (used_by_other_reload, rld[other].regno + j);
      }
  
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
--- 1688,1700 ----
    IOR_COMPL_HARD_REG_SET (not_usable, reg_class_contents[rl->class]);
  
    CLEAR_HARD_REG_SET (used_by_other_reload);
!   for (i = n_reloads - 1; i >= 0; i--)
      {
!       if (rld[i].regno >= 0
! 	  && (reloads_conflict (i, rnum)
! 	      || hard_reload_conflict (i, rnum)))
! 	for (j = 0; j < rld[i].nregs; j++)
! 	  SET_HARD_REG_BIT (used_by_other_reload, rld[i].regno + j);
      }
  
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
*************** find_reg (chain, order, dumpfile)
*** 1657,1667 ****
       {
         count_spilled_pseudo (best_reg, rl->nregs, j);
       });
-   EXECUTE_IF_SET_IN_REG_SET
-     (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, j,
-      {
-        count_spilled_pseudo (best_reg, rl->nregs, j);
-      });
  
    for (i = 0; i < rl->nregs; i++)
      {
--- 1751,1756 ----
*************** find_reload_regs (chain, dumpfile)
*** 1728,1740 ****
  	  && rld[r].regno == -1)
  	if (! find_reg (chain, i, dumpfile))
  	  {
  	    spill_failure (chain->insn, rld[r].class);
  	    failure = 1;
  	    return;
  	  }
      }
  
!   COPY_HARD_REG_SET (chain->used_spill_regs, used_spill_regs_local);
    IOR_HARD_REG_SET (used_spill_regs, used_spill_regs_local);
  
    memcpy (chain->rld, rld, n_reloads * sizeof (struct reload));
--- 1817,1839 ----
  	  && rld[r].regno == -1)
  	if (! find_reg (chain, i, dumpfile))
  	  {
+ 	    /* Sometimes a pseudo that dies or is set in the insn is allocated
+ 	       to (a group of hard regsiters containing) a hard register in a
+ 	       class that we urgently need - typically a one-register class.
+ 	       If we can find a pseudo we can kick out, do so, and
+ 	       stop further register allocation; we don't know how many
+ 	       hard registers and for what timespan(s) we have freed up.
+ 	       The next reload iteration will find out the new reload
+ 	       requirements.  */
+ 	    if (spill_pseudo (&chain->dead_or_set, rld[r].class))
+ 	      break;
  	    spill_failure (chain->insn, rld[r].class);
  	    failure = 1;
  	    return;
  	  }
      }
  
!   IOR_HARD_REG_SET (chain->used_spill_regs, used_spill_regs_local);
    IOR_HARD_REG_SET (used_spill_regs, used_spill_regs_local);
  
    memcpy (chain->rld, rld, n_reloads * sizeof (struct reload));
*************** finish_spills (global, dumpfile)
*** 3509,3526 ****
  	       ior_hard_reg_set (pseudo_forbidden_regs + i,
  				 &chain->used_spill_regs);
  	     });
- 	  EXECUTE_IF_SET_IN_REG_SET
- 	    (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, i,
- 	     {
- 	       ior_hard_reg_set (pseudo_forbidden_regs + i,
- 				 &chain->used_spill_regs);
- 	     });
  	}
  
        /* Retry allocating the spilled pseudos.  For each reg, merge the
  	 various reg sets that indicate which hard regs can't be used,
  	 and call retry_global_alloc.
! 	 We change spill_pseudos here to only contain pseudos that did not
  	 get a new hard register.  */
        for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
  	if (reg_old_renumber[i] != reg_renumber[i])
--- 3608,3619 ----
  	       ior_hard_reg_set (pseudo_forbidden_regs + i,
  				 &chain->used_spill_regs);
  	     });
  	}
  
        /* Retry allocating the spilled pseudos.  For each reg, merge the
  	 various reg sets that indicate which hard regs can't be used,
  	 and call retry_global_alloc.
! 	 We change spilled_pseudos here to only contain pseudos that did not
  	 get a new hard register.  */
        for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
  	if (reg_old_renumber[i] != reg_renumber[i])
*************** finish_spills (global, dumpfile)
*** 3537,3572 ****
  
    /* Fix up the register information in the insn chain.
       This involves deleting those of the spilled pseudos which did not get
!      a new hard register home from the live_{before,after} sets.  */
    for (chain = reload_insn_chain; chain; chain = chain->next)
      {
-       HARD_REG_SET used_by_pseudos;
-       HARD_REG_SET used_by_pseudos2;
- 
        AND_COMPL_REG_SET (&chain->live_throughout, &spilled_pseudos);
        AND_COMPL_REG_SET (&chain->dead_or_set, &spilled_pseudos);
- 
-       /* Mark any unallocated hard regs as available for spills.  That
- 	 makes inheritance work somewhat better.  */
-       if (chain->need_reload)
- 	{
- 	  REG_SET_TO_HARD_REG_SET (used_by_pseudos, &chain->live_throughout);
- 	  REG_SET_TO_HARD_REG_SET (used_by_pseudos2, &chain->dead_or_set);
- 	  IOR_HARD_REG_SET (used_by_pseudos, used_by_pseudos2);
- 
- 	  /* Save the old value for the sanity test below.  */
- 	  COPY_HARD_REG_SET (used_by_pseudos2, chain->used_spill_regs);
- 
- 	  compute_use_by_pseudos (&used_by_pseudos, &chain->live_throughout);
- 	  compute_use_by_pseudos (&used_by_pseudos, &chain->dead_or_set);
- 	  COMPL_HARD_REG_SET (chain->used_spill_regs, used_by_pseudos);
- 	  AND_HARD_REG_SET (chain->used_spill_regs, used_spill_regs);
- 
- 	  /* Make sure we only enlarge the set.  */
- 	  GO_IF_HARD_REG_SUBSET (used_by_pseudos2, chain->used_spill_regs, ok);
- 	  abort ();
- 	ok:;
- 	}
      }
  
    /* Let alter_reg modify the reg rtx's for the modified pseudos.  */
--- 3630,3641 ----
  
    /* Fix up the register information in the insn chain.
       This involves deleting those of the spilled pseudos which did not get
!      a new hard register home from the live_throughout / pseudo_dead_or_set
!      sets.  */
    for (chain = reload_insn_chain; chain; chain = chain->next)
      {
        AND_COMPL_REG_SET (&chain->live_throughout, &spilled_pseudos);
        AND_COMPL_REG_SET (&chain->dead_or_set, &spilled_pseudos);
      }
  
    /* Let alter_reg modify the reg rtx's for the modified pseudos.  */
*************** reload_as_needed (live_known)
*** 3733,3739 ****
  	      bzero (reg_has_output_reload, max_regno);
  	      CLEAR_HARD_REG_SET (reg_is_output_reload);
  
! 	      find_reloads (insn, 1, spill_indirect_levels, live_known,
  			    spill_reg_order);
  	    }
  
--- 3802,3808 ----
  	      bzero (reg_has_output_reload, max_regno);
  	      CLEAR_HARD_REG_SET (reg_is_output_reload);
  
! 	      find_reloads (chain, 1, spill_indirect_levels, live_known,
  			    spill_reg_order);
  	    }
  
*************** forget_old_reloads_1 (x, ignored, data)
*** 3990,3997 ****
  /* The following HARD_REG_SETs indicate when each hard register is
     used for a reload of various parts of the current insn.  */
  
- /* If reg is unavailable for all reloads.  */
- static HARD_REG_SET reload_reg_unavailable;
  /* If reg is in use as a reload reg for a RELOAD_OTHER reload.  */
  static HARD_REG_SET reload_reg_used;
  /* If reg is in use for a RELOAD_FOR_INPUT_ADDRESS reload for operand I.  */
--- 4059,4064 ----
*************** static HARD_REG_SET reload_reg_used_at_a
*** 4022,4029 ****
     in the group.  */
  static HARD_REG_SET reload_reg_used_for_inherit;
  
! /* Records which hard regs are used in any way, either as explicit use or
!    by being allocated to a pseudo during any point of the current insn.  */
  static HARD_REG_SET reg_used_in_insn;
  
  /* Mark reg REGNO as in use for a reload of the sort spec'd by OPNUM and
--- 4089,4097 ----
     in the group.  */
  static HARD_REG_SET reload_reg_used_for_inherit;
  
! /* Records which hard regs are used in any way not evident in the insn,
!    by being a live hard register or allocated to a pseudo throughout
!    the current insn.  */
  static HARD_REG_SET reg_used_in_insn;
  
  /* Mark reg REGNO as in use for a reload of the sort spec'd by OPNUM and
*************** reload_reg_free_p (regno, opnum, type)
*** 4214,4222 ****
  {
    int i;
  
    /* In use for a RELOAD_OTHER means it's not available for anything.  */
!   if (TEST_HARD_REG_BIT (reload_reg_used, regno)
!       || TEST_HARD_REG_BIT (reload_reg_unavailable, regno))
      return 0;
  
    switch (type)
--- 4282,4293 ----
  {
    int i;
  
+   /* Is this a live hard reg or allocated to a pseudo?  */
+   if (TEST_HARD_REG_BIT (reg_used_in_insn, regno))
+     return 0;
+ 
    /* In use for a RELOAD_OTHER means it's not available for anything.  */
!   if (TEST_HARD_REG_BIT (reload_reg_used, regno))
      return 0;
  
    switch (type)
*************** reloads_conflict (r1, r2)
*** 4566,4571 ****
--- 4637,4695 ----
        abort ();
      }
  }
+ 
+ /* Return nonzero if reload OLD is a hard reload and therefore conflicts
+    with reload NEW.  return zero if there is no conflict.
+    If reloads_conflict will find a conflict, we don't care about the
+    return value of hard_reload_conflict.  */
+ static int
+ hard_reload_conflict (old, new)
+      int old, new;
+ {
+   if (rld[old].reg_rtx == rld[old].in)
+     {
+       enum reload_type old_type = rld[old].when_needed;
+ 
+       switch (rld[new].when_needed)
+ 	{
+ 	case RELOAD_FOR_OTHER_ADDRESS:
+ 	  return 1;
+ 	case RELOAD_FOR_INPADDR_ADDRESS:
+ 	case RELOAD_FOR_INPUT_ADDRESS:
+ 	  if (old_type == RELOAD_FOR_INPUT_ADDRESS
+ 	      && rld[old].opnum >= rld[new].opnum)
+ 	    return 1;
+ 	  /* Fall through.  */
+ 	case RELOAD_FOR_OPADDR_ADDR:
+ 	case RELOAD_FOR_OPERAND_ADDRESS:
+ 	  return (old_type == RELOAD_FOR_INPUT
+ 		  || old_type == RELOAD_FOR_OPERAND_ADDRESS);
+ 
+ 	case RELOAD_FOR_INPUT: case RELOAD_FOR_INSN: case RELOAD_OTHER:
+ 	case RELOAD_FOR_OUTPUT_ADDRESS: case RELOAD_FOR_OUTPUT:
+ 	case RELOAD_FOR_OUTADDR_ADDRESS:
+ 	  ;
+ 	}
+     }
+   if (rld[old].reg_rtx == rld[old].out)
+     {
+       switch (rld[new].when_needed)
+ 	{
+ 	case RELOAD_FOR_OUTPUT_ADDRESS:
+ 	case RELOAD_FOR_OUTADDR_ADDRESS:
+ 	  return (rld[old].when_needed == RELOAD_FOR_OUTPUT
+ 		  || (rld[old].when_needed == RELOAD_FOR_OUTPUT_ADDRESS
+ 		      && rld[old].opnum <= rld[new].opnum));
+ 
+ 	case RELOAD_FOR_OUTPUT: case RELOAD_FOR_INSN: case RELOAD_OTHER:
+ 	case RELOAD_FOR_OTHER_ADDRESS: case RELOAD_FOR_INPADDR_ADDRESS:
+ 	case RELOAD_FOR_INPUT_ADDRESS: case RELOAD_FOR_OPADDR_ADDR:
+ 	case RELOAD_FOR_OPERAND_ADDRESS: case RELOAD_FOR_INPUT: 
+ 	  ;
+ 	}
+     }
+   return 0;
+ }
  
  /* Indexed by reload number, 1 if incoming value
     inherited from previous insns.  */
*************** reload_reg_free_for_value_p (regno, opnu
*** 4620,4628 ****
    int i;
    int copy = 0;
  
-   if (TEST_HARD_REG_BIT (reload_reg_unavailable, regno))
-     return 0;
- 
    if (out == const0_rtx)
      {
        copy = 1;
--- 4744,4749 ----
*************** reload_reg_free_for_value_p (regno, opnu
*** 4782,4789 ****
  		  if (! rld[i].in || rtx_equal_p (rld[i].in, value))
  		    {
  		      time2 = MAX_RECOG_OPERANDS * 4 + 4;
! 		      /* Earlyclobbered outputs must conflict with inputs.  */
! 		      if (earlyclobber_operand_p (rld[i].out))
  			time2 = MAX_RECOG_OPERANDS * 4 + 3;
  			  
  		      break;
--- 4903,4912 ----
  		  if (! rld[i].in || rtx_equal_p (rld[i].in, value))
  		    {
  		      time2 = MAX_RECOG_OPERANDS * 4 + 4;
! 		      /* Earlyclobbered outputs must conflict with inputs.
! 			 If this is a hard reload, earlyclobber_operand_p
! 			 doesn't work, so use earlyclobber_overlap_p.  */
! 		      if (rld[i].out && earlyclobber_overlap_p (rld[i].out))
  			time2 = MAX_RECOG_OPERANDS * 4 + 3;
  			  
  		      break;
*************** reload_reg_free_for_value_p (regno, opnu
*** 4799,4805 ****
  		default:
  		  return 0;
  		}
! 	      if ((time1 >= time2
  		   && (! rld[i].in || rld[i].out
  		       || ! rtx_equal_p (rld[i].in, value)))
  		  || (out && rld[reloadnum].out_reg
--- 4922,4930 ----
  		default:
  		  return 0;
  		}
! 	      if (((time1 >= time2
! 		    /* Test for hard reloads */
! 		    || (rld[i].in && rld[i].in == rld[i].reg_rtx))
  		   && (! rld[i].in || rld[i].out
  		       || ! rtx_equal_p (rld[i].in, value)))
  		  || (out && rld[reloadnum].out_reg
*************** allocate_reload_reg (chain, r, last_relo
*** 4954,4962 ****
  	  if ((reload_reg_free_p (regnum, rld[r].opnum,
  				  rld[r].when_needed)
  	       || (rld[r].in
! 		   /* We check reload_reg_used to make sure we
! 		      don't clobber the return register.  */
! 		   && ! TEST_HARD_REG_BIT (reload_reg_used, regnum)
  		   && reload_reg_free_for_value_p (regnum,
  						   rld[r].opnum,
  						   rld[r].when_needed,
--- 5079,5089 ----
  	  if ((reload_reg_free_p (regnum, rld[r].opnum,
  				  rld[r].when_needed)
  	       || (rld[r].in
! 		   /* We check reg_used_in_insn to make sure we don't clobber
! 		      pseudos or hard regs live after the insn.
! 		      Registers that are set in the insn will be accounted
! 		      for with reloads.  */
! 		   && ! TEST_HARD_REG_BIT (reg_used_in_insn, regnum)
  		   && reload_reg_free_for_value_p (regnum,
  						   rld[r].opnum,
  						   rld[r].when_needed,
*************** choose_reload_regs_init (chain, save_rel
*** 5043,5058 ****
    CLEAR_HARD_REG_SET (reload_reg_used_in_insn);
    CLEAR_HARD_REG_SET (reload_reg_used_in_other_addr);
  
!   CLEAR_HARD_REG_SET (reg_used_in_insn);
!   {
!     HARD_REG_SET tmp;
!     REG_SET_TO_HARD_REG_SET (tmp, &chain->live_throughout);
!     IOR_HARD_REG_SET (reg_used_in_insn, tmp);
!     REG_SET_TO_HARD_REG_SET (tmp, &chain->dead_or_set);
!     IOR_HARD_REG_SET (reg_used_in_insn, tmp);
!     compute_use_by_pseudos (&reg_used_in_insn, &chain->live_throughout);
!     compute_use_by_pseudos (&reg_used_in_insn, &chain->dead_or_set);
!   }
    for (i = 0; i < reload_n_operands; i++)
      {
        CLEAR_HARD_REG_SET (reload_reg_used_in_output[i]);
--- 5170,5178 ----
    CLEAR_HARD_REG_SET (reload_reg_used_in_insn);
    CLEAR_HARD_REG_SET (reload_reg_used_in_other_addr);
  
!   REG_SET_TO_HARD_REG_SET (reg_used_in_insn, &chain->live_throughout);
!   compute_use_by_pseudos (&reg_used_in_insn, &chain->live_throughout);
! 
    for (i = 0; i < reload_n_operands; i++)
      {
        CLEAR_HARD_REG_SET (reload_reg_used_in_output[i]);
*************** choose_reload_regs_init (chain, save_rel
*** 5063,5078 ****
        CLEAR_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i]);
      }
  
-   COMPL_HARD_REG_SET (reload_reg_unavailable, chain->used_spill_regs);
- 
    CLEAR_HARD_REG_SET (reload_reg_used_for_inherit);
  
    for (i = 0; i < n_reloads; i++)
      /* If we have already decided to use a certain register,
         don't use it in another way.  */
      if (rld[i].reg_rtx)
!       mark_reload_reg_in_use (REGNO (rld[i].reg_rtx), rld[i].opnum,
! 			      rld[i].when_needed, rld[i].mode);
  }
  
  /* Assign hard reg targets for the pseudo-registers we must reload
--- 5183,5240 ----
        CLEAR_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i]);
      }
  
    CLEAR_HARD_REG_SET (reload_reg_used_for_inherit);
  
    for (i = 0; i < n_reloads; i++)
      /* If we have already decided to use a certain register,
         don't use it in another way.  */
      if (rld[i].reg_rtx)
!       {
! 	mark_reload_reg_in_use (REGNO (rld[i].reg_rtx), rld[i].opnum,
! 				rld[i].when_needed, rld[i].mode);
! 	/* Hard reloads start out life before the first regular reload and/or
! 	   remain life till after the last regular reload.  */
! 	if (rld[i].reg_rtx == rld[i].in)
! 	  {
! 	    enum reload_type type;
! 
! 	    mark_reload_reg_in_use (REGNO (rld[i].reg_rtx), rld[i].opnum,
! 				    RELOAD_FOR_OTHER_ADDRESS, rld[i].mode);
! 	    type = rld[i].when_needed;
! 	    if (type == RELOAD_FOR_OPERAND_ADDRESS)
! 	      mark_reload_reg_in_use (REGNO (rld[i].reg_rtx), rld[i].opnum,
! 				      RELOAD_FOR_INPUT, rld[i].mode);
! 	    if (type == RELOAD_FOR_INPUT_ADDRESS
! 		|| type == RELOAD_FOR_INPUT
! 		|| type == RELOAD_FOR_OPERAND_ADDRESS)
! 	      {
! 		int j;
! 
! 		for (j = rld[i].opnum; j >= 0; j--)
! 		  {
! 		    mark_reload_reg_in_use (REGNO (rld[i].reg_rtx), j,
! 					    RELOAD_FOR_INPUT_ADDRESS,
! 					    rld[i].mode);
! 		    mark_reload_reg_in_use (REGNO (rld[i].reg_rtx), j,
! 					    RELOAD_FOR_INPADDR_ADDRESS,
! 					    rld[i].mode);
! 		  }
! 	      }
! 	  }
! 	if (rld[i].reg_rtx == rld[i].out)
! 	  {
! 	    int j = rld[i].opnum;
! 
! 	    while (--j >= 0)
! 	      {
! 		mark_reload_reg_in_use (REGNO (rld[i].reg_rtx), j,
! 					RELOAD_FOR_OUTPUT_ADDRESS, rld[i].mode);
! 		mark_reload_reg_in_use (REGNO (rld[i].reg_rtx), j,
! 					RELOAD_FOR_OUTADDR_ADDRESS,
! 					rld[i].mode);
! 	      }
! 	  }
!       }
  }
  
  /* Assign hard reg targets for the pseudo-registers we must reload
*************** choose_reload_regs (chain)
*** 5299,5306 ****
  
  		      if (k == nr)
  			{
- 			  int i1;
- 
  			  last_reg = (GET_MODE (last_reg) == mode
  				      ? last_reg : gen_rtx_REG (mode, i));
  
--- 5461,5466 ----
*************** choose_reload_regs (chain)
*** 5310,5330 ****
  			     current insn, just mark it as a place to
  			     reload from since we can't use it as the
  			     reload register itself.  */
- 
- 			  for (i1 = 0; i1 < n_earlyclobbers; i1++)
- 			    if (reg_overlap_mentioned_for_reload_p
- 				(reg_last_reload_reg[regno],
- 				 reload_earlyclobbers[i1]))
- 			      break;
  
! 			  if (i1 != n_earlyclobbers
  			      || ! (reload_reg_free_for_value_p
  				    (i, rld[r].opnum, rld[r].when_needed,
  				     rld[r].in, rld[r].out, r, 1))
  			      /* Don't use it if we'd clobber a pseudo reg.  */
  			      || (TEST_HARD_REG_BIT (reg_used_in_insn, i)
! 				  && rld[r].out
! 				  && ! TEST_HARD_REG_BIT (reg_reloaded_dead, i))
  			      /* Don't clobber the frame pointer.  */
  			      || (i == HARD_FRAME_POINTER_REGNUM && rld[r].out)
  			      /* Don't really use the inherited spill reg
--- 5470,5483 ----
  			     current insn, just mark it as a place to
  			     reload from since we can't use it as the
  			     reload register itself.  */
  
! 			  if (earlyclobber_overlap_p (last_reg)
  			      || ! (reload_reg_free_for_value_p
  				    (i, rld[r].opnum, rld[r].when_needed,
  				     rld[r].in, rld[r].out, r, 1))
  			      /* Don't use it if we'd clobber a pseudo reg.  */
  			      || (TEST_HARD_REG_BIT (reg_used_in_insn, i)
! 				  && rld[r].out)
  			      /* Don't clobber the frame pointer.  */
  			      || (i == HARD_FRAME_POINTER_REGNUM && rld[r].out)
  			      /* Don't really use the inherited spill reg
*************** choose_reload_regs (chain)
*** 5390,5395 ****
--- 5543,5551 ----
  		  && rtx_equal_p (rld[r].out, SET_DEST (set))
  		  && CONSTANT_P (SET_SRC (set)))
  		search_equiv = SET_SRC (set);
+ 		/* N.B. since this is a simple move insn, we don't actually
+ 		   change the register we use, hence we don't have to
+ 		   tell reload_reg_free_for_value_p about rld[r].out.  */
  	    }
  
  	  if (search_equiv)
*************** choose_reload_regs (chain)
*** 5422,5429 ****
  		  && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
  		       && ! reload_reg_free_for_value_p (regno, rld[r].opnum,
  							 rld[r].when_needed,
! 							 rld[r].in,
! 							 rld[r].out, r, 1))
  		      || ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].class],
  					      regno)))
  		equiv = 0;
--- 5578,5585 ----
  		  && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
  		       && ! reload_reg_free_for_value_p (regno, rld[r].opnum,
  							 rld[r].when_needed,
! 							 search_equiv,
! 							 NULL_RTX, r, 1))
  		      || ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].class],
  					      regno)))
  		equiv = 0;
*************** choose_reload_regs (chain)
*** 5432,5458 ****
  		equiv = 0;
  
  	      /* We found a register that contains the value we need.
! 		 If this register is the same as an `earlyclobber' operand
! 		 of the current insn, just mark it as a place to reload from
! 		 since we can't use it as the reload register itself.  */
! 
! 	      if (equiv != 0)
! 		for (i = 0; i < n_earlyclobbers; i++)
! 		  if (reg_overlap_mentioned_for_reload_p (equiv,
! 							  reload_earlyclobbers[i]))
! 		    {
! 		      reload_override_in[r] = equiv;
! 		      equiv = 0;
! 		      break;
! 		    }
! 
! 	      /* If the equiv register we have found is explicitly clobbered
! 		 in the current insn, it depends on the reload type if we
! 		 can use it, use it for reload_override_in, or not at all.
  		 In particular, we then can't use EQUIV for a
  		 RELOAD_FOR_OUTPUT_ADDRESS reload.  */
  
! 	      if (equiv != 0 && regno_clobbered_p (regno, insn))
  		{
  		  switch (rld[r].when_needed)
  		    {
--- 5588,5604 ----
  		equiv = 0;
  
  	      /* We found a register that contains the value we need.
! 		 If this register is the same as an `earlyclobber' operand,
! 		 or it is explicitly clobbered in the current insn, it depends
! 		 on the reload type if we can use it as the reload register
! 		 itself, use it only for reload_override_in (i.e as a place
! 		 to reload from), or not at all.
  		 In particular, we then can't use EQUIV for a
  		 RELOAD_FOR_OUTPUT_ADDRESS reload.  */
  
! 	      if (equiv != 0
! 		  && (earlyclobber_overlap_p (equiv)
! 		      || regno_clobbered_p (regno, insn)))
  		{
  		  switch (rld[r].when_needed)
  		    {
*************** choose_reload_regs (chain)
*** 5706,5712 ****
  
  	  if (rld[r].when_needed != RELOAD_OTHER
  	      && rld[r].when_needed != RELOAD_FOR_OUTPUT
! 	      && rld[r].when_needed != RELOAD_FOR_INSN)
  	    abort ();
  	}
      }
--- 5852,5860 ----
  
  	  if (rld[r].when_needed != RELOAD_OTHER
  	      && rld[r].when_needed != RELOAD_FOR_OUTPUT
! 	      && rld[r].when_needed != RELOAD_FOR_INSN
! 	      && (rld[r].when_needed != RELOAD_FOR_OUTPUT_ADDRESS
! 		  || rld[r].out_reg != rld[r].reg_rtx))
  	    abort ();
  	}
      }
*************** static rtx other_output_reload_insns[MAX
*** 5856,5862 ****
  
  /* Values to be put in spill_reg_store are put here first.  */
  static rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
- static HARD_REG_SET reg_reloaded_died;
  
  /* Generate insns to perform reload RL, which is for the insn in CHAIN and
     has the number J.  OLD contains the value to be used as input.  */
--- 6004,6009 ----
*************** emit_output_reload_insns (chain, rl, j)
*** 6500,6507 ****
  
  		reload_spill_index[j] = src;
  		SET_HARD_REG_BIT (reg_is_output_reload, src);
- 		if (find_regno_note (insn, REG_DEAD, src))
- 		  SET_HARD_REG_BIT (reg_reloaded_died, src);
  	      }
  	    if (REGNO (rl->reg_rtx) < FIRST_PSEUDO_REGISTER)
  	      {
--- 6647,6652 ----
*************** emit_reload_insns (chain)
*** 6700,6707 ****
    rtx following_insn = NEXT_INSN (insn);
    rtx before_insn = PREV_INSN (insn);
  
-   CLEAR_HARD_REG_SET (reg_reloaded_died);
- 
    for (j = 0; j < reload_n_operands; j++)
      input_reload_insns[j] = input_address_reload_insns[j]
        = inpaddr_address_reload_insns[j]
--- 6845,6850 ----
*************** emit_reload_insns (chain)
*** 6894,6900 ****
  		  /* Now do the inverse operation.  */
  		  for (k = 0; k < nr; k++)
  		    {
- 		      CLEAR_HARD_REG_BIT (reg_reloaded_dead, i + k);
  		      reg_reloaded_contents[i + k]
  			= (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr
  			   ? nregno
--- 7037,7042 ----
*************** emit_reload_insns (chain)
*** 6951,6957 ****
  
  		  for (k = 0; k < nr; k++)
  		    {
- 		      CLEAR_HARD_REG_BIT (reg_reloaded_dead, i + k);
  		      reg_reloaded_contents[i + k]
  			= (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr
  			   ? nregno
--- 7093,7098 ----
*************** emit_reload_insns (chain)
*** 7042,7054 ****
  		      spill_reg_stored_to[src_regno + nr] = out;
  		      reg_reloaded_contents[src_regno + nr] = nregno;
  		      reg_reloaded_insn[src_regno + nr] = store_insn;
- 		      CLEAR_HARD_REG_BIT (reg_reloaded_dead, src_regno + nr);
  		      SET_HARD_REG_BIT (reg_reloaded_valid, src_regno + nr);
  		      SET_HARD_REG_BIT (reg_is_output_reload, src_regno + nr);
- 		      if (note)
- 			SET_HARD_REG_BIT (reg_reloaded_died, src_regno);
- 		      else
- 			CLEAR_HARD_REG_BIT (reg_reloaded_died, src_regno);
  		    }
  		  reg_last_reload_reg[nregno] = src_reg;
  		}
--- 7183,7190 ----
*************** emit_reload_insns (chain)
*** 7062,7068 ****
  	    }
  	}
      }
-   IOR_HARD_REG_SET (reg_reloaded_dead, reg_reloaded_died);
  }
  
  /* Emit code to perform a reload from IN (which may be a reload register) to
--- 7198,7203 ----


More information about the Gcc-patches mailing list