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]

Re: reload patches for egcs


Collapsing the ChangeLog to a single point of time indeed made it a lot
shorter; however, I'm afraid the readability suffers.

In order to test the updated patch, I've backed out the recent gcse changes.

I have simply changed my update_eliminables function into update_eliminables_1
for now; you said you already resolved the conflict in your copy, and I've
been hacking too long now to think of a good alternate name for either
function, so you can just pop in whatever name you already thought of.

With this patch goes, in, we still need to tweak some machine descpritions
(e.g. change 'm' constraints to 'rm' constrains) to allow more optional
input reloads.

Wed Oct  7 00:51:42 1998  J"orn Rennecke <amylaar@cygnus.co.uk>

	Fix consistency problems with reg_equiv_{mem,address};
	Improve reload inheritance;
	Handle equivalences that have been obscured by gcse:

	* reload.c (reload_out_reg): New variable.
	(loc_mentioned_in_p, remove_address_replacements): New functions.
	(remove_replacements): Deleted.
	(push_reload): Set reload_out_reg[i].
	When merging, also set reload_{in,out}_reg[i], and remove
	duplicate address reloads.
	(combine_reloads): Copy reload_out_reg[i].
	(find_reloads): Do make_memloc substitution also when
	reg_equiv_memory_loc[regno] and num_not_at_initial_offset
	are both nonzero.
	Include *recog_operand_loc in commutativity operand changes.
	Generate optional output reloads.
	Delete reference to n_memlocs.  Don't set *recog_operand_loc before
	processing operands.  Call make_memloc in reg_equiv_address code.
	Set *recog_operand_loc only after processing operands, and only
	if replace is true.  Return a value.
	When changing address reload types for operands that didn't get
	reloaded, use RELOAD_FOR_OPADDR_ADDRESS for
	RELOAD_FOR_INPADDR_ADDRESS / RELOAD_FOR_OUTADDR_ADDRESS reloads.
	Don't emit USEs for pseudo SUBREGs when not replacing.
	(find_reloads_address): Do make_memloc substitution also when
	reg_equiv_memory_loc[regno] and num_not_at_initial_offset
	are both nonzero.
	(find_reloads_toplev): Likewise.
	Call make_memloc in reg_equiv_address code.
	(debug_reload_to_stream): Add code to output reload_out_reg.
	(make_memloc): Delete local variable i, ifdefed out code, and
	references to memlocs and n_memlocs.
	(memlocs, n_memlocs): Delete.
	(push_secondary_reload): Clear reload_out_reg.
	(find_reloads_address_1): Provide memrefloc argument to all calls
	to find_reloads_address.
	In AUTO_INC code, handle non-directly addressable equivalences properly.
	* reload.h (reload_out_reg, num_not_at_initial_offset): Declare.
	(find_reloads): Add return type.
	(remove_address_replacements, deallocate_reload_reg): Declare.
	* reload1.c (num_not_at_initial_offset): No longer static.
	(update_eliminables): New static function.
	(delete_address_reloads, delete_address_reloads_1): Likewise.
	(deallocate_reload_reg): New function.
	(spill_reg_stored_to): New array.
	(eliminate_regs): Don't substitute from reg_equiv_memory_loc.
	(eliminate_regs_in_insn): Move assignments of previous_offset and
	max_offset fields, and recalculation of num_not_at_initial_offset
	into new static function:
	(update_eliminables) .
	(reload_as_needed): Call update_eliminables after calling find_reloads.
	Call forget_old_reloads_1 with contents of reloaded auto_inc
	expressions if the actual addressing can't be changed to match the
	auto_inc.
	(choose_reload_regs): For inheritance, replace
	reload_reg_free_before_p test with reload_reg_used_at_all test, and
	remove stand-alone reload_reg_used_at_all test.
	Use reload_out_reg to determine which reload regs have output reloads.
	Treat reload_override_in more similar to inherited reloads.
	Handle (subreg (reg... for inheritance.
	For flag_expensive_optimizations, add an extra pass to remove
	unnecessary reloads from known working inheritance.
	Delete obsolete code for pseudos replaced with MEMs.
	Handle inheritance from auto_inc expressions.
	(emit_reload_insns): If reload_in is a MEM, set OLD to 
	reload_in_reg[j].
	Don't reload directly from oldequiv; if it's a pseudo with a
	stack slot, use reload_in[j].
	Check that reload_in_reg[j] is a MEM before replacing reload_in
	from reg_reloaded_contents.
	Include non-spill registers in reload inheritance processing.
	Also try to use reload_out_reg to set spill_reg_store /
	reg_last_reload_reg.
	In code to set new_spill_reg_store, use single_set to find out if
	there is a single set.
	Add code that allows to delete optional output reloads.
	Add code to allow deletion of output reloads that use no spill reg.
	At the end, set reload_override_in to oldequiv.
	Also call delete_output_reload if reload_out_reg is equal to old
	in oldequiv code.
	Add code to call delete_output_reload for stores with no matching load.
	Set / use spill_reg_stored_to.
        Handle case where secondary output reload uses a temporary, but
	actual store isn't found.
	When looking for a store of a value not loaded in order to call
	delete_output_reload, count_occurences should return 0 for no
	loads; but discount inherited input reloads.
	Don't register spill reg use for input reloads for inheritance
	if the reload register is set in the insn.
	Handle inheritance from auto_inc expressions.
	In secondary input reload code, check if loading from a pseudo
	that is not directly addressible.
	Call delete_output_reload also when we have inherited a register
	for a SUBREG.
	Treat reload_override_in more similar to inherited reloads.
	(delete_output_reload): Don't use delete_insn.
	Third argument is now LAST_RELOAD_REG, an rtx.  Set reg from
	spill_reg_stored_to.  Do checks for extra uses of REG.  Changed all
	callers.
	Use delete_address_reloads.
	(reload): Take return value of find_reloads into account.
	If a no-op set needs more than one reload, delete it.
	Handle equivalences set up in multiple places.
	(reload_reg_free_before_p): RELOAD_FOR_INPUT
	can ignore RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS
	for the same operand.
	(clear_reload_reg_in_use): Check for other reloads that keep a
	register in use.
	(reload_reg_free_for_value_p): handle RELOAD_FOR_OPERAND_ADDRESS /
	RELOAD_FOR_OPADDR_ADDR.
	Take into account when an address address reload is only needed
	for the address reload we are considering.
	(count_occurrences): Use rtx_equal_p for MEMs.
	(inc_for_reload): Return instruction that stores into RELOADREG.
	New argument two, IN, and rtx.  Changed all callers.
	(calculate_needs_all_insns, reload_as_needed):
	Don't clear after_call for a CLOBBER.
	Keep track of how many hard registers need to be copied from
	after_call, and don't clear after_call before we have seen
	that much copies, or we see a different instruction.
	* local-alloc.c (reg_equiv_init_insns): New variable.
	(no_equiv): New function.
	(update_equiv_regs): Handle equivalences set up in multiple places.
	Don't ignore an insn just because its destination is likely to be
	spilled.

Index: local-alloc.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/local-alloc.c,v
retrieving revision 1.21
diff -p -r1.21 local-alloc.c
*** local-alloc.c	1998/10/02 10:21:17	1.21
--- local-alloc.c	1998/10/08 05:00:14
*************** static rtx this_insn;
*** 234,239 ****
--- 234,242 ----
  
  static rtx *reg_equiv_replacement;
  
+ /* Used for communication between update_equiv_regs and no_equiv.  */
+ static rtx *reg_equiv_init_insns;
+ 
  static void alloc_qty		PROTO((int, enum machine_mode, int, int));
  static void validate_equiv_mem_from_store PROTO((rtx, rtx));
  static int validate_equiv_mem	PROTO((rtx, rtx, rtx));
*************** static int contains_replace_regs PROTO((
*** 241,246 ****
--- 244,250 ----
  static int memref_referenced_p	PROTO((rtx, rtx));
  static int memref_used_between_p PROTO((rtx, rtx, rtx));
  static void update_equiv_regs	PROTO((void));
+ static void no_equiv		PROTO((rtx, rtx));
  static void block_alloc		PROTO((int));
  static int qty_sugg_compare    	PROTO((int, int));
  static int qty_sugg_compare_1	PROTO((const GENERIC_PTR, const GENERIC_PTR));
*************** memref_used_between_p (memref, start, en
*** 633,639 ****
  static void
  update_equiv_regs ()
  {
-   rtx *reg_equiv_init_insn = (rtx *) alloca (max_regno * sizeof (rtx *));
    /* Set when an attempt should be made to replace a register with the
       associated reg_equiv_replacement entry at the end of this function.  */
    char *reg_equiv_replace
--- 637,642 ----
*************** update_equiv_regs ()
*** 641,649 ****
    rtx insn;
    int block, depth;
  
    reg_equiv_replacement = (rtx *) alloca (max_regno * sizeof (rtx *));
  
!   bzero ((char *) reg_equiv_init_insn, max_regno * sizeof (rtx *));
    bzero ((char *) reg_equiv_replacement, max_regno * sizeof (rtx *));
    bzero ((char *) reg_equiv_replace, max_regno * sizeof *reg_equiv_replace);
  
--- 644,653 ----
    rtx insn;
    int block, depth;
  
+   reg_equiv_init_insns = (rtx *) alloca (max_regno * sizeof (rtx *));
    reg_equiv_replacement = (rtx *) alloca (max_regno * sizeof (rtx *));
  
!   bzero ((char *) reg_equiv_init_insns, max_regno * sizeof (rtx *));
    bzero ((char *) reg_equiv_replacement, max_regno * sizeof (rtx *));
    bzero ((char *) reg_equiv_replace, max_regno * sizeof *reg_equiv_replace);
  
*************** update_equiv_regs ()
*** 657,663 ****
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
      {
        rtx note;
!       rtx set = single_set (insn);
        rtx dest, src;
        int regno;
  
--- 661,667 ----
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
      {
        rtx note;
!       rtx set;
        rtx dest, src;
        int regno;
  
*************** update_equiv_regs ()
*** 669,678 ****
  	    loop_depth--;
  	}
  
!       /* If this insn contains more (or less) than a single SET, ignore it.  */
!       if (set == 0)
  	continue;
  
        dest = SET_DEST (set);
        src = SET_SRC (set);
  
--- 673,706 ----
  	    loop_depth--;
  	}
  
!       if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
  	continue;
  
+       for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ 	if (REG_NOTE_KIND (note) == REG_INC)
+ 	  no_equiv (XEXP (note, 0), note);
+ 
+       set = single_set (insn);
+ 
+       /* If this insn contains more (or less) than a single SET,
+ 	 only mark all destinations as having no known equivalence.  */
+       if (set == 0)
+ 	{
+ 	  note_stores (PATTERN (insn), no_equiv);
+ 	  continue;
+ 	}
+       else if (GET_CODE (PATTERN (insn)) == PARALLEL)
+ 	{
+ 	  int i;
+ 
+ 	  for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
+ 	    {
+ 	      rtx part = XVECEXP (PATTERN (insn), 0, i);
+ 	      if (part != set)
+ 		note_stores (part, no_equiv);
+ 	    }
+ 	}
+ 
        dest = SET_DEST (set);
        src = SET_SRC (set);
  
*************** update_equiv_regs ()
*** 688,722 ****
  	 If one of the regs in the address is marked as reg_equiv_replace,
  	 then we can't add this REG_EQUIV note.  The reg_equiv_replace
  	 optimization may move the set of this register immediately before
! 	 insn, which puts it after reg_equiv_init_insn[regno], and hence
  	 the mention in the REG_EQUIV note would be to an uninitialized
  	 pseudo.  */
  
!       if (GET_CODE (dest) == MEM && GET_CODE (SET_SRC (set)) == REG
! 	  && (regno = REGNO (SET_SRC (set))) >= FIRST_PSEUDO_REGISTER
  	  && REG_BASIC_BLOCK (regno) >= 0
! 	  && reg_equiv_init_insn[regno] != 0
  	  && ! find_reg_note (insn, REG_EQUIV, NULL_RTX)
! 	  && ! contains_replace_regs (XEXP (dest, 0), reg_equiv_replace)
! 	  && validate_equiv_mem (reg_equiv_init_insn[regno], SET_SRC (set),
! 				 dest)
! 	  && ! memref_used_between_p (SET_DEST (set),
! 				      reg_equiv_init_insn[regno], insn))
! 	REG_NOTES (reg_equiv_init_insn[regno])
! 	  = gen_rtx_EXPR_LIST (REG_EQUIV, dest,
! 			       REG_NOTES (reg_equiv_init_insn[regno]));
  
        /* We only handle the case of a pseudo register being set
! 	 once and only if neither the source nor the destination are
! 	 in a register class that's likely to be spilled.  */
        if (GET_CODE (dest) != REG
  	  || (regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER
! 	  || REG_N_SETS (regno) != 1
! 	  || CLASS_LIKELY_SPILLED_P (reg_preferred_class (REGNO (dest)))
! 	  || (GET_CODE (src) == REG
! 	      && REGNO (src) >= FIRST_PSEUDO_REGISTER
! 	      && CLASS_LIKELY_SPILLED_P (reg_preferred_class (REGNO (src)))))
! 	continue;
  
        note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
  
--- 716,765 ----
  	 If one of the regs in the address is marked as reg_equiv_replace,
  	 then we can't add this REG_EQUIV note.  The reg_equiv_replace
  	 optimization may move the set of this register immediately before
! 	 insn, which puts it after reg_equiv_init_insns[regno], and hence
  	 the mention in the REG_EQUIV note would be to an uninitialized
  	 pseudo.  */
+       /* ????? This test isn't good enough; we might see a MEM with a use of
+ 	 a pseudo register before we see its setting insn that will cause
+ 	 reg_equiv_replace for that pseudo to be set.
+ 	 Equivalences to MEMs should be made in another pass, after the
+ 	 reg_equiv_replace information has been gathered.  */
  
!       if (GET_CODE (dest) == MEM && GET_CODE (src) == REG
! 	  && (regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER
  	  && REG_BASIC_BLOCK (regno) >= 0
! 	  && REG_N_SETS (regno) == 1
! 	  && reg_equiv_init_insns[regno] != 0
! 	  && reg_equiv_init_insns[regno] != const0_rtx
  	  && ! find_reg_note (insn, REG_EQUIV, NULL_RTX)
! 	  && ! contains_replace_regs (XEXP (dest, 0), reg_equiv_replace))
! 	{
! 	  rtx init_insn = XEXP (reg_equiv_init_insns[regno], 0);
! 	  if (validate_equiv_mem (init_insn, src, dest)
! 	      && ! memref_used_between_p (dest, init_insn, insn))
! 	    REG_NOTES (init_insn)
! 	      = gen_rtx_EXPR_LIST (REG_EQUIV, dest, REG_NOTES (init_insn));
! 	}
  
        /* We only handle the case of a pseudo register being set
! 	 once, or always to the same value, and not if the
! 	 destination is in a register class that's likely to be spilled.  */
        if (GET_CODE (dest) != REG
  	  || (regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER
! 	  || reg_equiv_init_insns[regno] == const0_rtx)
! 	{
! 	  /* This might be seting a SUBREG of a pseudo, a pseudo that is
! 	     also set somewhere else to a constant.  */
! 	  note_stores (set, no_equiv);
! 	  continue;
! 	}
!       if (GET_CODE (src) == REG
! 	  && REGNO (src) >= FIRST_PSEUDO_REGISTER
! 	  && CLASS_LIKELY_SPILLED_P (reg_preferred_class (REGNO (src))))
! 	{
! 	  no_equiv (dest, set);
! 	  continue;
! 	}
  
        note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
  
*************** update_equiv_regs ()
*** 736,743 ****
          note = NULL;
  #endif
  
        /* Record this insn as initializing this register.  */
!       reg_equiv_init_insn[regno] = insn;
  
        /* If this register is known to be equal to a constant, record that
  	 it is always equivalent to the constant.  */
--- 779,797 ----
          note = NULL;
  #endif
  
+       if (REG_N_SETS (regno) != 1
+ 	  && (! note
+ 	      || ! CONSTANT_P (XEXP (note, 0))
+ 	      || (reg_equiv_replacement[regno]
+ 		  && ! rtx_equal_p (XEXP (note, 0),
+ 				    reg_equiv_replacement[regno]))))
+ 	{
+ 	  no_equiv (dest, set);
+ 	  continue;
+ 	}
        /* Record this insn as initializing this register.  */
!       reg_equiv_init_insns[regno]
! 	= gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init_insns[regno]);
  
        /* If this register is known to be equal to a constant, record that
  	 it is always equivalent to the constant.  */
*************** update_equiv_regs ()
*** 849,855 ****
  	      if (! reg_equiv_replace[regno])
  		continue;
  
! 	      equiv_insn = reg_equiv_init_insn[regno];
  
  	      if (validate_replace_rtx (regno_reg_rtx[regno],
  					reg_equiv_replacement[regno], insn))
--- 903,914 ----
  	      if (! reg_equiv_replace[regno])
  		continue;
  
! 	      /* reg_equiv_replace[REGNO] gets set only when
! 		 REG_N_REFS[REGNO] is 2, i.e. the register is set
! 		 once and used once.  (If it were only set, but not used,
! 		 flow would have deleted the setting insns.)  Hence 
! 		 there can only be one insn in reg_equiv_init_insns.  */
! 	      equiv_insn = XEXP (reg_equiv_init_insns[regno], 0);
  
  	      if (validate_replace_rtx (regno_reg_rtx[regno],
  					reg_equiv_replacement[regno], insn))
*************** update_equiv_regs ()
*** 895,900 ****
--- 954,988 ----
  	    }
  	}
      }
+ }
+ 
+ /* Mark REG as having no known equivalence.
+    Some instructions might have been proceessed before and furnished
+    with REG_EQUIV notes for this register; these notes will have to be
+    removed.
+    STORE is the piece of RTL that does the non-constant / conflicting
+    assignment - a SET, CLOBBER or REG_INC note.  It is currently not used,
+    but needs to be there because this function is called from note_stores.  */
+ static void
+ no_equiv (reg, store)
+      rtx reg, store;
+ {
+   int regno;
+   rtx list;
+ 
+   if (GET_CODE (reg) != REG)
+     return;
+   regno = REGNO (reg);
+   list = reg_equiv_init_insns[regno];
+   if (list == const0_rtx)
+     return;
+   for (; list; list =  XEXP (list, 1))
+     {
+       rtx insn = XEXP (list, 0);
+       remove_note (insn, find_reg_note (insn, REG_EQUIV, NULL_RTX));
+     }
+   reg_equiv_init_insns[regno] = const0_rtx;
+   reg_equiv_replacement[regno] = NULL_RTX;
  }
  
  /* Allocate hard regs to the pseudo regs used only within block number B.
Index: reload.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/reload.c,v
retrieving revision 1.46
diff -p -r1.46 reload.c
*** reload.c	1998/09/24 10:51:35	1.46
--- reload.c	1998/10/08 05:00:16
*************** char reload_optional[MAX_RELOADS];
*** 181,186 ****
--- 181,187 ----
  char reload_nongroup[MAX_RELOADS];
  int reload_inc[MAX_RELOADS];
  rtx reload_in_reg[MAX_RELOADS];
+ rtx reload_out_reg[MAX_RELOADS];
  char reload_nocombine[MAX_RELOADS];
  int reload_opnum[MAX_RELOADS];
  enum reload_type reload_when_needed[MAX_RELOADS];
*************** struct decomposition
*** 232,242 ****
    HOST_WIDE_INT end;	/* Ending offset or register number.  */
  };
  
- /* MEM-rtx's created for pseudo-regs in stack slots not directly addressable;
-    (see reg_equiv_address).  */
- static rtx memlocs[MAX_RECOG_OPERANDS * ((MAX_REGS_PER_ADDRESS * 2) + 1)];
- static int n_memlocs;
- 
  #ifdef SECONDARY_MEMORY_NEEDED
  
  /* Save MEMs needed to copy from one class of registers to another.  One MEM
--- 233,238 ----
*************** static int hard_reg_set_here_p	PROTO((in
*** 329,339 ****
  static struct decomposition decompose PROTO((rtx));
  static int immune_p		PROTO((rtx, rtx, struct decomposition));
  static int alternative_allows_memconst PROTO((char *, int));
! static rtx find_reloads_toplev	PROTO((rtx, int, enum reload_type, int, int));
  static rtx make_memloc		PROTO((rtx, int));
  static int find_reloads_address	PROTO((enum machine_mode, rtx *, rtx, rtx *,
  				       int, enum reload_type, int, rtx));
! static rtx subst_reg_equivs	PROTO((rtx));
  static rtx subst_indexed_address PROTO((rtx));
  static int find_reloads_address_1 PROTO((enum machine_mode, rtx, int, rtx *,
  					 int, enum reload_type,int, rtx));
--- 325,335 ----
  static struct decomposition decompose PROTO((rtx));
  static int immune_p		PROTO((rtx, rtx, struct decomposition));
  static int alternative_allows_memconst PROTO((char *, int));
! static rtx find_reloads_toplev	PROTO((rtx, int, enum reload_type, int, int, rtx));
  static rtx make_memloc		PROTO((rtx, int));
  static int find_reloads_address	PROTO((enum machine_mode, rtx *, rtx, rtx *,
  				       int, enum reload_type, int, rtx));
! static rtx subst_reg_equivs	PROTO((rtx, rtx));
  static rtx subst_indexed_address PROTO((rtx));
  static int find_reloads_address_1 PROTO((enum machine_mode, rtx, int, rtx *,
  					 int, enum reload_type,int, rtx));
*************** static void find_reloads_address_part PR
*** 341,346 ****
--- 337,343 ----
  					     enum machine_mode, int,
  					     enum reload_type, int));
  static int find_inc_amount	PROTO((rtx, rtx));
+ static int loc_mentioned_in_p	PROTO((rtx *, rtx));
  
  #ifdef HAVE_SECONDARY_RELOADS
  
*************** push_secondary_reload (in_p, x, opnum, o
*** 536,541 ****
--- 533,539 ----
  	  /* Maybe we could combine these, but it seems too tricky.  */
  	  reload_nocombine[t_reload] = 1;
  	  reload_in_reg[t_reload] = 0;
+ 	  reload_out_reg[t_reload] = 0;
  	  reload_opnum[t_reload] = opnum;
  	  reload_when_needed[t_reload] = secondary_type;
  	  reload_secondary_in_reload[t_reload] = -1;
*************** push_secondary_reload (in_p, x, opnum, o
*** 605,610 ****
--- 603,609 ----
        /* Maybe we could combine these, but it seems too tricky.  */
        reload_nocombine[s_reload] = 1;
        reload_in_reg[s_reload] = 0;
+       reload_out_reg[s_reload] = 0;
        reload_opnum[s_reload] = opnum;
        reload_when_needed[s_reload] = secondary_type;
        reload_secondary_in_reload[s_reload] = in_p ? t_reload : -1;
*************** push_reload (in, out, inloc, outloc, cla
*** 1170,1176 ****
  	}
      }
  
!   if (class == NO_REGS)
      abort ();
  
    /* We can use an existing reload if the class is right
--- 1169,1179 ----
  	}
      }
  
!   /* Optional output reloads are always OK even if we have no register class,
!      since the function of these reloads is only to have spill_reg_store etc.
!      set, so that the storing insn can be deleted later.  */
!   if (class == NO_REGS
!       && (optional == 0 || type != RELOAD_FOR_OUTPUT))
      abort ();
  
    /* We can use an existing reload if the class is right
*************** push_reload (in, out, inloc, outloc, cla
*** 1281,1286 ****
--- 1284,1290 ----
        reload_inc[i] = 0;
        reload_nocombine[i] = 0;
        reload_in_reg[i] = inloc ? *inloc : 0;
+       reload_out_reg[i] = outloc ? *outloc : 0;
        reload_opnum[i] = opnum;
        reload_when_needed[i] = type;
        reload_secondary_in_reload[i] = secondary_in_reload;
*************** push_reload (in, out, inloc, outloc, cla
*** 1315,1323 ****
  	  && GET_MODE_SIZE (outmode) > GET_MODE_SIZE (reload_outmode[i]))
  	reload_outmode[i] = outmode;
        if (in != 0)
! 	reload_in[i] = in;
        if (out != 0)
! 	reload_out[i] = out;
        if (reg_class_subset_p (class, reload_reg_class[i]))
  	reload_reg_class[i] = class;
        reload_optional[i] &= optional;
--- 1319,1350 ----
  	  && GET_MODE_SIZE (outmode) > GET_MODE_SIZE (reload_outmode[i]))
  	reload_outmode[i] = outmode;
        if (in != 0)
! 	{
! 	  /* If we merge reloads for two distinct rtl expressions that
! 	     are identical in content, there might be duplicate address
! 	     reloads.  Remove the extra set now, so that if we later find
! 	     that we can inherit this reload, we can get rid of the
! 	     address reloads altogether.  */
! 	  if (reload_in[i] != in && rtx_equal_p (in, reload_in[i]))
! 	    {
! 	      /* We must keep the address reload with the lower operand
! 		 number alive.  */
! 	      if (opnum > reload_opnum[i])
! 		{
! 		  remove_address_replacements (in);
! 		  in = reload_in[i];
! 		}
! 	      else
! 		remove_address_replacements (reload_in[i]);
! 	    }
! 	  reload_in[i] = in;
! 	  reload_in_reg[i] = inloc ? *inloc : 0;
! 	}
        if (out != 0)
! 	{
! 	  reload_out[i] = out;
! 	  reload_out_reg[i] = outloc ? *outloc : 0;
! 	}
        if (reg_class_subset_p (class, reload_reg_class[i]))
  	reload_reg_class[i] = class;
        reload_optional[i] &= optional;
*************** transfer_replacements (to, from)
*** 1506,1525 ****
        replacements[i].what = to;
  }
  
! /* Remove all replacements in reload FROM.  */
! void
! remove_replacements (from)
!      int from;
  {
    int i, j;
  
    for (i = 0, j = 0; i < n_replacements; i++)
      {
!       if (replacements[i].what == from)
!         continue;
!       replacements[j++] = replacements[i];
      }
  }
  
  /* 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
--- 1533,1600 ----
        replacements[i].what = to;
  }
  
! /* IN_RTX is the value loaded by a reload that we now decided to inherit,
!    or a subpart of it.  If we have any replacements registered for IN_RTX,
!    cancel the reloads that were supposed to load them.
!    Return non-zero if we canceled any reloads.  */
! int
! remove_address_replacements (in_rtx)
!      rtx in_rtx;
  {
    int i, j;
+   char reload_flags[MAX_RELOADS];
+   int something_changed = 0;
  
+   bzero (reload_flags, sizeof reload_flags);
    for (i = 0, j = 0; i < n_replacements; i++)
      {
!       if (loc_mentioned_in_p (replacements[i].where, in_rtx))
! 	reload_flags[replacements[i].what] |= 1;
!       else
! 	{
! 	  replacements[j++] = replacements[i];
! 	  reload_flags[replacements[i].what] |= 2;
! 	}
      }
+   /* Note that the following store must be done before the recursive calls.  */
+   n_replacements = j;
+ 
+   for (i = n_reloads - 1; i >= 0; i--)
+     {
+       if (reload_flags[i] == 1)
+ 	{
+ 	  deallocate_reload_reg (i);
+ 	  remove_address_replacements (reload_in[i]);
+ 	  reload_in[i] = 0;
+ 	  something_changed = 1;
+ 	}
+     }
+   return something_changed;
  }
+ 
+ /* Return non-zero if IN contains a piece of rtl that has the address LOC */
+ static int
+ loc_mentioned_in_p (loc, in)
+      rtx *loc, in;
+ {
+   enum rtx_code code = GET_CODE (in);
+   char *fmt = GET_RTX_FORMAT (code);
+   int i, j;
+ 
+   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+     {
+       if (loc == &XEXP (in, i))
+ 	return 1;
+       if (fmt[i] == 'e')
+ 	if (loc_mentioned_in_p (loc, XEXP (in, i)))
+ 	  return 1;
+       else if (fmt[i] == 'E')
+ 	for (j = XVECLEN (in, i) - 1; i >= 0; i--)
+ 	  if (loc_mentioned_in_p (loc, XVECEXP (in, i, j)))
+ 	    return 1;
+     }
+   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
*************** combine_reloads ()
*** 1617,1622 ****
--- 1692,1698 ----
  
  	/* We have found a reload to combine with!  */
  	reload_out[i] = reload_out[output_reload];
+ 	reload_out_reg[i] = reload_out_reg[output_reload];
  	reload_outmode[i] = reload_outmode[output_reload];
  	/* Mark the old output reload as inoperative.  */
  	reload_out[output_reload] = 0;
*************** safe_from_earlyclobber (op, clobber)
*** 2299,2307 ****
     RELOAD_REG_P if nonzero is a vector indexed by hard reg number
     which is nonnegative if the reg has been commandeered for reloading into.
     It is copied into STATIC_RELOAD_REG_P and referenced from there
!    by various subroutines.  */
  
! void
  find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
       rtx insn;
       int replace, ind_levels;
--- 2375,2386 ----
     RELOAD_REG_P if nonzero is a vector indexed by hard reg number
     which is nonnegative if the reg has been commandeered for reloading into.
     It is copied into STATIC_RELOAD_REG_P and referenced from there
!    by various subroutines.
  
!    Return TRUE if some operands need to be changed, because of swapping
!    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;
*************** find_reloads (insn, replace, ind_levels,
*** 2357,2362 ****
--- 2436,2442 ----
    rtx set = single_set (insn);
    int goal_earlyclobber, this_earlyclobber;
    enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
+   int retval = 0;
    /* Cache the last regno for the last pseudo we did an output reload
       for in case the next insn uses it.  */
    static int last_output_reload_regno = -1;
*************** find_reloads (insn, replace, ind_levels,
*** 2365,2371 ****
    this_insn_is_asm = 0;		/* Tentative.  */
    n_reloads = 0;
    n_replacements = 0;
-   n_memlocs = 0;
    n_earlyclobbers = 0;
    replace_reloads = replace;
    hard_regs_live_known = live_known;
--- 2445,2450 ----
*************** find_reloads (insn, replace, ind_levels,
*** 2406,2412 ****
      case ASM_INPUT:
      case ADDR_VEC:
      case ADDR_DIFF_VEC:
!       return;
  
      case SET:
        /* Dispose quickly of (set (reg..) (reg..)) if both have hard regs and it
--- 2485,2491 ----
      case ASM_INPUT:
      case ADDR_VEC:
      case ADDR_DIFF_VEC:
!       return 0;
  
      case SET:
        /* Dispose quickly of (set (reg..) (reg..)) if both have hard regs and it
*************** find_reloads (insn, replace, ind_levels,
*** 2418,2424 ****
  	  && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
  	  && REGISTER_MOVE_COST (REGNO_REG_CLASS (REGNO (SET_SRC (body))),
  				 REGNO_REG_CLASS (REGNO (SET_DEST (body)))) == 2)
! 	return;
      case PARALLEL:
      case ASM_OPERANDS:
        reload_n_operands = noperands = asm_noperands (body);
--- 2497,2503 ----
  	  && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
  	  && REGISTER_MOVE_COST (REGNO_REG_CLASS (REGNO (SET_SRC (body))),
  				 REGNO_REG_CLASS (REGNO (SET_DEST (body)))) == 2)
! 	return 0;
      case PARALLEL:
      case ASM_OPERANDS:
        reload_n_operands = noperands = asm_noperands (body);
*************** find_reloads (insn, replace, ind_levels,
*** 2449,2455 ****
  		    /* Avoid further trouble with this insn.  */
  		    PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
  		    n_reloads = 0;
! 		    return;
  		  }
  	    }
  	  break;
--- 2528,2534 ----
  		    /* Avoid further trouble with this insn.  */
  		    PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
  		    n_reloads = 0;
! 		    return 0;
  		  }
  	    }
  	  break;
*************** find_reloads (insn, replace, ind_levels,
*** 2467,2473 ****
        n_alternatives = insn_n_alternatives[insn_code_number];
        /* Just return "no reloads" if insn has no operands with constraints.  */
        if (n_alternatives == 0)
! 	return;
        insn_extract (insn);
        for (i = 0; i < noperands; i++)
  	{
--- 2546,2552 ----
        n_alternatives = insn_n_alternatives[insn_code_number];
        /* Just return "no reloads" if insn has no operands with constraints.  */
        if (n_alternatives == 0)
! 	return 0;
        insn_extract (insn);
        for (i = 0; i < noperands; i++)
  	{
*************** find_reloads (insn, replace, ind_levels,
*** 2478,2484 ****
      }
  
    if (noperands == 0)
!     return;
  
    commutative = -1;
  
--- 2557,2563 ----
      }
  
    if (noperands == 0)
!     return 0;
  
    commutative = -1;
  
*************** find_reloads (insn, replace, ind_levels,
*** 2598,2606 ****
  		  || GET_CODE (recog_operand[i]) == PLUS))
  	    {
  	      INSN_CODE (insn) = -1;
! 	      find_reloads (insn, replace, ind_levels, live_known,
! 			    reload_reg_p);
! 	      return;
  	    }
  
  	  substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
--- 2677,2685 ----
  		  || GET_CODE (recog_operand[i]) == PLUS))
  	    {
  	      INSN_CODE (insn) = -1;
! 	      retval = find_reloads (insn, replace, ind_levels, live_known,
! 				     reload_reg_p);
! 	      return retval;
  	    }
  
  	  substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
*************** find_reloads (insn, replace, ind_levels,
*** 2622,2635 ****
  	    = find_reloads_toplev (recog_operand[i], i, address_type[i],
  				   ind_levels,
  				   set != 0
! 				   && &SET_DEST (set) == recog_operand_loc[i]);
  
  	  /* If we made a MEM to load (a part of) the stackslot of a pseudo
  	     that didn't get a hard register, emit a USE with a REG_EQUAL
  	     note in front so that we might inherit a previous, possibly
  	     wider reload.  */
  	     
! 	  if (GET_CODE (op) == MEM
  	      && GET_CODE (reg) == REG
  	      && (GET_MODE_SIZE (GET_MODE (reg))
  		  >= GET_MODE_SIZE (GET_MODE (op))))
--- 2701,2716 ----
  	    = find_reloads_toplev (recog_operand[i], i, address_type[i],
  				   ind_levels,
  				   set != 0
! 				   && &SET_DEST (set) == recog_operand_loc[i],
! 				   insn);
  
  	  /* If we made a MEM to load (a part of) the stackslot of a pseudo
  	     that didn't get a hard register, emit a USE with a REG_EQUAL
  	     note in front so that we might inherit a previous, possibly
  	     wider reload.  */
  	     
! 	  if (replace
! 	      && GET_CODE (op) == MEM
  	      && GET_CODE (reg) == REG
  	      && (GET_MODE_SIZE (GET_MODE (reg))
  		  >= GET_MODE_SIZE (GET_MODE (op))))
*************** find_reloads (insn, replace, ind_levels,
*** 2637,2651 ****
                = gen_rtx_EXPR_LIST (REG_EQUAL,
  				   reg_equiv_memory_loc[REGNO (reg)], NULL_RTX);
  
! 	  substed_operand[i] = recog_operand[i] = *recog_operand_loc[i] = op;
  	}
        else if (code == PLUS || GET_RTX_CLASS (code) == '1')
  	/* We can get a PLUS as an "operand" as a result of register
  	   elimination.  See eliminate_regs and gen_reload.  We handle
  	   a unary operator by reloading the operand.  */
! 	substed_operand[i] = recog_operand[i] = *recog_operand_loc[i]
  	  = find_reloads_toplev (recog_operand[i], i, address_type[i],
! 				 ind_levels, 0);
        else if (code == REG)
  	{
  	  /* This is equivalent to calling find_reloads_toplev.
--- 2718,2732 ----
                = gen_rtx_EXPR_LIST (REG_EQUAL,
  				   reg_equiv_memory_loc[REGNO (reg)], NULL_RTX);
  
! 	  substed_operand[i] = recog_operand[i] = op;
  	}
        else if (code == PLUS || GET_RTX_CLASS (code) == '1')
  	/* We can get a PLUS as an "operand" as a result of register
  	   elimination.  See eliminate_regs and gen_reload.  We handle
  	   a unary operator by reloading the operand.  */
! 	substed_operand[i] = recog_operand[i]
  	  = find_reloads_toplev (recog_operand[i], i, address_type[i],
! 				 ind_levels, 0, insn);
        else if (code == REG)
  	{
  	  /* This is equivalent to calling find_reloads_toplev.
*************** find_reloads (insn, replace, ind_levels,
*** 2667,2710 ****
  	      substed_operand[i] = recog_operand[i]
  	        = reg_equiv_constant[regno];
  	    }
! #if 0 /* This might screw code in reload1.c to delete prior output-reload
! 	 that feeds this insn.  */
! 	  if (reg_equiv_mem[regno] != 0)
  	    substed_operand[i] = recog_operand[i]
! 	      = reg_equiv_mem[regno];
! #endif
! 	  if (reg_equiv_address[regno] != 0)
! 	    {
! 	      /* If reg_equiv_address is not a constant address, copy it,
! 		 since it may be shared.  */
! 	      /* We must rerun eliminate_regs, in case the elimination
! 		 offsets have changed.  */
! 	      rtx address = XEXP (eliminate_regs (reg_equiv_memory_loc[regno],
! 						  0, NULL_RTX),
! 				  0);
! 
! 	      if (rtx_varies_p (address))
! 		address = copy_rtx (address);
! 
! 	      /* Emit a USE that shows what register is being used/modified.  */
! 	      REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode,
! 							recog_operand[i]),
! 					   insn))
! 		= gen_rtx_EXPR_LIST (REG_EQUAL,
! 				     reg_equiv_memory_loc[regno],
! 				     NULL_RTX);
! 
! 	      *recog_operand_loc[i] = recog_operand[i]
! 		= gen_rtx_MEM (GET_MODE (recog_operand[i]), address);
! 	      RTX_UNCHANGING_P (recog_operand[i])
! 		= RTX_UNCHANGING_P (regno_reg_rtx[regno]);
! 	      find_reloads_address (GET_MODE (recog_operand[i]),
! 				    recog_operand_loc[i],
! 				    XEXP (recog_operand[i], 0),
! 				    &XEXP (recog_operand[i], 0),
! 				    i, address_type[i], ind_levels, insn);
! 	      substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
! 	    }
  	}
        /* If the operand is still a register (we didn't replace it with an
  	 equivalent), get the preferred class to reload it into.  */
--- 2748,2760 ----
  	      substed_operand[i] = recog_operand[i]
  	        = reg_equiv_constant[regno];
  	    }
! 	  if (reg_equiv_memory_loc[regno] != 0
! 	      && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
! 	    /* We need not give a valid is_set_dest argument since the case
! 	       of a constant equivalence was checked above.  */
  	    substed_operand[i] = recog_operand[i]
! 	      = find_reloads_toplev (recog_operand[i], i, address_type[i],
! 				     ind_levels, 0, insn);
  	}
        /* If the operand is still a register (we didn't replace it with an
  	 equivalent), get the preferred class to reload it into.  */
*************** find_reloads (insn, replace, ind_levels,
*** 3539,3545 ****
        /* Avoid further trouble with this insn.  */
        PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
        n_reloads = 0;
!       return;
      }
  
    /* Jump to `finish' from above if all operands are valid already.
--- 3589,3595 ----
        /* Avoid further trouble with this insn.  */
        PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
        n_reloads = 0;
!       return 0;
      }
  
    /* Jump to `finish' from above if all operands are valid already.
*************** find_reloads (insn, replace, ind_levels,
*** 3574,3579 ****
--- 3624,3632 ----
        tem = recog_operand[commutative];
        recog_operand[commutative] = recog_operand[commutative + 1];
        recog_operand[commutative + 1] = tem;
+       tem = *recog_operand_loc[commutative];
+       *recog_operand_loc[commutative] = *recog_operand_loc[commutative+1];
+       *recog_operand_loc[commutative+1] = tem;
  
        for (i = 0; i < n_reloads; i++)
  	{
*************** find_reloads (insn, replace, ind_levels,
*** 3584,3597 ****
  	}
      }
  
-   /* Perform whatever substitutions on the operands we are supposed
-      to make due to commutativity or replacement of registers
-      with equivalent constants or memory slots.  */
- 
    for (i = 0; i < noperands; i++)
      {
-       *recog_operand_loc[i] = substed_operand[i];
-       /* While we are looping on operands, initialize this.  */
        operand_reloadnum[i] = -1;
  
        /* If this is an earlyclobber operand, we need to widen the scope.
--- 3637,3644 ----
*************** find_reloads (insn, replace, ind_levels,
*** 3633,3639 ****
  	*recog_operand_loc[i] = recog_operand[i]
  	  = find_reloads_toplev (force_const_mem (operand_mode[i],
  						  recog_operand[i]),
! 				 i, address_type[i], ind_levels, 0);
  	if (alternative_allows_memconst (constraints1[i],
  					 goal_alternative_number))
  	  goal_alternative_win[i] = 1;
--- 3680,3686 ----
  	*recog_operand_loc[i] = recog_operand[i]
  	  = find_reloads_toplev (force_const_mem (operand_mode[i],
  						  recog_operand[i]),
! 				 i, address_type[i], ind_levels, 0, insn);
  	if (alternative_allows_memconst (constraints1[i],
  					 goal_alternative_number))
  	  goal_alternative_win[i] = 1;
*************** find_reloads (insn, replace, ind_levels,
*** 3758,3764 ****
  	    /* Avoid further trouble with this insn.  */
  	    PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
  	    n_reloads = 0;
! 	    return;
  	  }
        }
      else if (goal_alternative_matched[i] < 0
--- 3805,3811 ----
  	    /* Avoid further trouble with this insn.  */
  	    PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
  	    n_reloads = 0;
! 	    return 0;
  	  }
        }
      else if (goal_alternative_matched[i] < 0
*************** find_reloads (insn, replace, ind_levels,
*** 3776,3788 ****
  	if ((GET_CODE (operand) == MEM
  	     || (GET_CODE (operand) == REG
  		 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
! 	    && (enum reg_class) goal_alternative[i] != NO_REGS
  	    && ! no_input_reloads
! 	    /* Optional output reloads don't do anything and we mustn't
! 	       make in-out reloads on insns that are not permitted output
! 	       reloads.  */
  	    && (modified[i] == RELOAD_READ
! 		|| (modified[i] == RELOAD_READ_WRITE && ! no_output_reloads)))
  	  operand_reloadnum[i]
  	    = push_reload (modified[i] != RELOAD_WRITE ? recog_operand[i] : 0,
  			   modified[i] != RELOAD_READ ? recog_operand[i] : 0,
--- 3823,3843 ----
  	if ((GET_CODE (operand) == MEM
  	     || (GET_CODE (operand) == REG
  		 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
! 	    /* If this is only for an output, the optional reload would not
! 	       actually cause us to use a register now, just note that
! 	       something is stored here.  */
! 	    && ((enum reg_class) goal_alternative[i] != NO_REGS
! 		|| modified[i] == RELOAD_WRITE)
  	    && ! no_input_reloads
! 	    /* An optional output reload might allow to delete INSN later.
! 	       We mustn't make in-out reloads on insns that are not permitted
! 	       output reloads.
! 	       If this is an asm, we can't delete it; we must not even call
! 	       push_reload for an optional output reload in this case,
! 	       because we can't be sure that the constraint allows a register,
! 	       and push_reload verifies the constraints for asms.  */
  	    && (modified[i] == RELOAD_READ
! 		|| (! no_output_reloads && ! this_insn_is_asm)))
  	  operand_reloadnum[i]
  	    = push_reload (modified[i] != RELOAD_WRITE ? recog_operand[i] : 0,
  			   modified[i] != RELOAD_READ ? recog_operand[i] : 0,
*************** find_reloads (insn, replace, ind_levels,
*** 3798,3803 ****
--- 3853,3876 ----
  			   (insn_code_number < 0 ? 0
  			    : insn_operand_strict_low[insn_code_number][i]),
  			   1, i, operand_type[i]);
+ 	/* If a memory reference remains, yet we can't make an optional
+ 	   reload, check if this is actually a pseudo register reference;
+ 	   we then need to emit a USE and/or a CLOBBER so that reload
+ 	   inheritance will do the right thing.  */
+ 	else if (replace && GET_CODE (operand) == MEM)
+ 	  {
+ 	    operand = *recog_operand_loc[i];
+ 
+ 	    while (GET_CODE (operand) == SUBREG)
+ 	      operand = XEXP (operand, 0);
+ 	    if (GET_CODE (operand) == REG)
+ 	      {
+ 		if (modified[i] != RELOAD_WRITE)
+ 		  emit_insn_before (gen_rtx_USE (VOIDmode, operand), insn);
+ 		if (modified[i] != RELOAD_READ)
+ 		  emit_insn_after (gen_rtx_CLOBBER (VOIDmode, operand), insn);
+ 	      }
+ 	  }
        }
      else if (goal_alternative_matches[i] >= 0
  	     && goal_alternative_win[goal_alternative_matches[i]]
*************** find_reloads (insn, replace, ind_levels,
*** 3829,3834 ****
--- 3902,3924 ----
  			   0, 1, goal_alternative_matches[i], RELOAD_OTHER);
        }
    
+   /* Perform whatever substitutions on the operands we are supposed
+      to make due to commutativity or replacement of registers
+      with equivalent constants or memory slots.  */
+ 
+   for (i = 0; i < noperands; i++)
+     {
+       /* We only do this on the last pass through reload, because it is
+        possible for some data (like reg_equiv_address) to be changed during
+        later passes.  Moreover, we loose the opportunity to get a useful
+        reload_{in,out}_reg when we do these replacements.  */
+ 
+       if (replace)
+ 	*recog_operand_loc[i] = substed_operand[i];
+       else
+ 	retval |= (substed_operand[i] != *recog_operand_loc[i]);
+     }
+ 
    /* If this insn pattern contains any MATCH_DUP's, make sure that
       they will be substituted if the operands they match are substituted.
       Also do now any substitutions we already did on the operands.
*************** find_reloads (insn, replace, ind_levels,
*** 3983,3989 ****
  		  = RELOAD_FOR_OPADDR_ADDR;
  	    }
  
! 	  reload_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
  	}
  
        if ((reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
--- 4073,4083 ----
  		  = RELOAD_FOR_OPADDR_ADDR;
  	    }
  
! 	  if (reload_when_needed[i] == RELOAD_FOR_INPADDR_ADDRESS
! 	      || reload_when_needed[i] == RELOAD_FOR_OUTADDR_ADDRESS)
! 	    reload_when_needed[i] = RELOAD_FOR_OPADDR_ADDR;
! 	  else
! 	    reload_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
  	}
  
        if ((reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
*************** find_reloads (insn, replace, ind_levels,
*** 4198,4203 ****
--- 4292,4298 ----
    int goal_earlyclobber = 0; /* Always 0, to make combine_reloads happen.  */
    register int i;
    rtx body = PATTERN (insn);
+   int retval = 0;
  
    n_reloads = 0;
    n_replacements = 0;
*************** find_reloads (insn, replace, ind_levels,
*** 4297,4302 ****
--- 4392,4398 ----
    if (!goal_earlyclobber)
      combine_reloads ();
  #endif /* no REGISTER_CONSTRAINTS */
+   return retval;
  }
  
  /* Return 1 if alternative number ALTNUM in constraint-string CONSTRAINT
*************** alternative_allows_memconst (constraint,
*** 4335,4349 ****
     OPNUM and TYPE identify the purpose of the reload.
  
     IS_SET_DEST is true if X is the destination of a SET, which is not
!    appropriate to be replaced by a constant.  */
  
  static rtx
! find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
       rtx x;
       int opnum;
       enum reload_type type;
       int ind_levels;
       int is_set_dest;
  {
    register RTX_CODE code = GET_CODE (x);
  
--- 4431,4450 ----
     OPNUM and TYPE identify the purpose of the reload.
  
     IS_SET_DEST is true if X is the destination of a SET, which is not
!    appropriate to be replaced by a constant.
! 
!    INSN, if nonzero, is the insn in which we do the reload.  It is used
!    to determine if we may generate output reloads, and where to put USEs
!    for pseudos that we have to replace with stack slots.  */
  
  static rtx
! find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn)
       rtx x;
       int opnum;
       enum reload_type type;
       int ind_levels;
       int is_set_dest;
+      rtx insn;
  {
    register RTX_CODE code = GET_CODE (x);
  
*************** find_reloads_toplev (x, opnum, type, ind
*** 4362,4384 ****
        else if (reg_equiv_mem[regno] != 0)
  	x = reg_equiv_mem[regno];
  #endif
!       else if (reg_equiv_address[regno] != 0)
  	{
! 	  /* If reg_equiv_address varies, it may be shared, so copy it.  */
! 	  /* We must rerun eliminate_regs, in case the elimination
! 	     offsets have changed.  */
! 	  rtx addr = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0,
! 					   NULL_RTX),
! 			   0);
! 
! 	  if (rtx_varies_p (addr))
! 	    addr = copy_rtx (addr);
! 
! 	  x = gen_rtx_MEM (GET_MODE (x), addr);
! 	  RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
! 	  find_reloads_address (GET_MODE (x), NULL_PTR,
! 				XEXP (x, 0),
! 				&XEXP (x, 0), opnum, type, ind_levels, 0);
  	}
        return x;
      }
--- 4463,4484 ----
        else if (reg_equiv_mem[regno] != 0)
  	x = reg_equiv_mem[regno];
  #endif
!       else if (reg_equiv_memory_loc[regno]
! 	       && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
  	{
! 	  rtx mem = make_memloc (x, regno);
! 	  if (reg_equiv_address[regno]
! 	      || ! rtx_equal_p (mem, reg_equiv_mem[regno]))
! 	    {
! 	      /* If this is not a toplevel operand, find_reloads doesn't see
! 		 this substitution.  We have to emit a USE of the pseudo so
! 		 that delete_output_reload can see it.  */
! 	      if (replace_reloads && recog_operand[opnum] != x)
! 		emit_insn_before (gen_rtx_USE (VOIDmode, x), insn);
! 	      x = mem;
! 	      find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
! 				    opnum, type, ind_levels, insn);
! 	    }
  	}
        return x;
      }
*************** find_reloads_toplev (x, opnum, type, ind
*** 4386,4392 ****
      {
        rtx tem = x;
        find_reloads_address (GET_MODE (x), &tem, XEXP (x, 0), &XEXP (x, 0),
! 			    opnum, type, ind_levels, 0);
        return tem;
      }
  
--- 4486,4492 ----
      {
        rtx tem = x;
        find_reloads_address (GET_MODE (x), &tem, XEXP (x, 0), &XEXP (x, 0),
! 			    opnum, type, ind_levels, insn);
        return tem;
      }
  
*************** find_reloads_toplev (x, opnum, type, ind
*** 4480,4486 ****
  		   || (reg_equiv_mem[regno] != 0
  		       && (! strict_memory_address_p (GET_MODE (x), 
  						      XEXP (reg_equiv_mem[regno], 0))
! 			   || ! offsettable_memref_p (reg_equiv_mem[regno])))))
  	{
  	  int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
  	  /* We must rerun eliminate_regs, in case the elimination
--- 4580,4587 ----
  		   || (reg_equiv_mem[regno] != 0
  		       && (! strict_memory_address_p (GET_MODE (x), 
  						      XEXP (reg_equiv_mem[regno], 0))
! 			   || ! offsettable_memref_p (reg_equiv_mem[regno])
! 			   || num_not_at_initial_offset))))
  	{
  	  int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
  	  /* We must rerun eliminate_regs, in case the elimination
*************** find_reloads_toplev (x, opnum, type, ind
*** 4501,4507 ****
  	  RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
  	  find_reloads_address (GET_MODE (x), NULL_PTR,
  				XEXP (x, 0),
! 				&XEXP (x, 0), opnum, type, ind_levels, 0);
  	}
  
      }
--- 4602,4613 ----
  	  RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
  	  find_reloads_address (GET_MODE (x), NULL_PTR,
  				XEXP (x, 0),
! 				&XEXP (x, 0), opnum, type, ind_levels, insn);
! 	  /* If this is not a toplevel operand, find_reloads doesn't see this
! 	     substitution.  We have to emit a USE of the pseudo so that
! 	     delete_output_reload can see it.  */
! 	  if (replace_reloads && recog_operand[opnum] != x)
! 	    emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)), insn);
  	}
  
      }
*************** find_reloads_toplev (x, opnum, type, ind
*** 4510,4516 ****
      {
        if (fmt[i] == 'e')
  	XEXP (x, i) = find_reloads_toplev (XEXP (x, i), opnum, type,
! 					   ind_levels, is_set_dest);
      }
    return x;
  }
--- 4616,4622 ----
      {
        if (fmt[i] == 'e')
  	XEXP (x, i) = find_reloads_toplev (XEXP (x, i), opnum, type,
! 					   ind_levels, is_set_dest, insn);
      }
    return x;
  }
*************** make_memloc (ad, regno)
*** 4523,4544 ****
       rtx ad;
       int regno;
  {
- #if 0
-   register int i;
- #endif
    /* We must rerun eliminate_regs, in case the elimination
       offsets have changed.  */
!   rtx tem = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0, NULL_RTX), 0);
! 
! #if 0 /* We cannot safely reuse a memloc made here;
! 	 if the pseudo appears twice, and its mem needs a reload,
! 	 it gets two separate reloads assigned, but it only
! 	 gets substituted with the second of them;
! 	 then it can get used before that reload reg gets loaded up.  */
!   for (i = 0; i < n_memlocs; i++)
!     if (rtx_equal_p (tem, XEXP (memlocs[i], 0)))
!       return memlocs[i];
! #endif
  
    /* If TEM might contain a pseudo, we must copy it to avoid
       modifying it when we do the substitution for the reload.  */
--- 4629,4638 ----
       rtx ad;
       int regno;
  {
    /* We must rerun eliminate_regs, in case the elimination
       offsets have changed.  */
!   rtx tem
!     = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0, NULL_RTX), 0);
  
    /* If TEM might contain a pseudo, we must copy it to avoid
       modifying it when we do the substitution for the reload.  */
*************** make_memloc (ad, regno)
*** 4547,4553 ****
  
    tem = gen_rtx_MEM (GET_MODE (ad), tem);
    RTX_UNCHANGING_P (tem) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
-   memlocs[n_memlocs++] = tem;
    return tem;
  }
  
--- 4641,4646 ----
*************** make_memloc (ad, regno)
*** 4563,4569 ****
     supports.
  
     INSN, if nonzero, is the insn in which we do the reload.  It is used
!    to determine if we may generate output reloads.
  
     Value is nonzero if this address is reloaded or replaced as a whole.
     This is interesting to the caller if the address is an autoincrement.
--- 4656,4663 ----
     supports.
  
     INSN, if nonzero, is the insn in which we do the reload.  It is used
!    to determine if we may generate output reloads, and where to put USEs
!    for pseudos that we have to replace with stack slots.
  
     Value is nonzero if this address is reloaded or replaced as a whole.
     This is interesting to the caller if the address is an autoincrement.
*************** find_reloads_address (mode, memrefloc, a
*** 4603,4634 ****
  	  return 1;
  	}
  
!       else if (reg_equiv_address[regno] != 0)
  	{
! 	  tem = make_memloc (ad, regno);
! 	  find_reloads_address (GET_MODE (tem), NULL_PTR, XEXP (tem, 0),
! 				&XEXP (tem, 0), opnum, ADDR_TYPE (type),
! 				ind_levels, insn);
! 	  push_reload (tem, NULL_RTX, loc, NULL_PTR,
! 		       reload_address_base_reg_class,
! 		       GET_MODE (ad), VOIDmode, 0, 0,
! 		       opnum, type);
! 	  return 1;
  	}
  
-       /* We can avoid a reload if the register's equivalent memory expression
- 	 is valid as an indirect memory address.
- 	 But not all addresses are valid in a mem used as an indirect address:
- 	 only reg or reg+constant.  */
- 
-       else if (reg_equiv_mem[regno] != 0 && ind_levels > 0
- 	       && strict_memory_address_p (mode, reg_equiv_mem[regno])
- 	       && (GET_CODE (XEXP (reg_equiv_mem[regno], 0)) == REG
- 		   || (GET_CODE (XEXP (reg_equiv_mem[regno], 0)) == PLUS
- 		       && GET_CODE (XEXP (XEXP (reg_equiv_mem[regno], 0), 0)) == REG
- 		       && CONSTANT_P (XEXP (XEXP (reg_equiv_mem[regno], 0), 1)))))
- 	return 0;
- 
        /* The only remaining case where we can avoid a reload is if this is a
  	 hard register that is valid as a base register and which is not the
  	 subject of a CLOBBER in this insn.  */
--- 4697,4744 ----
  	  return 1;
  	}
  
!       tem = reg_equiv_memory_loc[regno];
!       if (tem != 0)
  	{
! 	  if (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)
! 	    {
! 	      tem = make_memloc (ad, regno);
! 	      if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
! 		{
! 		  find_reloads_address (GET_MODE (tem), NULL_PTR, XEXP (tem, 0),
! 					&XEXP (tem, 0), opnum, ADDR_TYPE (type),
! 					ind_levels, insn);
! 		}
! 	      /* We can avoid a reload if the register's equivalent memory
! 		 expression is valid as an indirect memory address.
! 		 But not all addresses are valid in a mem used as an indirect
! 		 address: only reg or reg+constant.  */
! 
! 	      if (ind_levels > 0
! 		  && strict_memory_address_p (mode, tem)
! 		  && (GET_CODE (XEXP (tem, 0)) == REG
! 		      || (GET_CODE (XEXP (tem, 0)) == PLUS
! 			  && GET_CODE (XEXP (XEXP (tem, 0), 0)) == REG
! 			  && CONSTANT_P (XEXP (XEXP (tem, 0), 1)))))
! 		{
! 		  /* TEM is not the same as what we'll be replacing the
! 		     pseudo with after reload, put a USE in front of INSN
! 		     in the final reload pass.  */
! 		  if (replace_reloads
! 		      && num_not_at_initial_offset
! 		      && ! rtx_equal_p (tem, reg_equiv_mem[regno]))
! 		    {
! 		      *loc = tem;
! 		      emit_insn_before (gen_rtx_USE (VOIDmode, ad), insn);
! 		      /* This doesn't really count as replacing the address
! 			 as a whole, since it is still a memory access.  */
! 		    }
! 		  return 0;
! 		}
! 	      ad = tem;
! 	    }
  	}
  
        /* The only remaining case where we can avoid a reload is if this is a
  	 hard register that is valid as a base register and which is not the
  	 subject of a CLOBBER in this insn.  */
*************** find_reloads_address (mode, memrefloc, a
*** 4661,4667 ****
  	return 0;
  
        subst_reg_equivs_changed = 0;
!       *loc = subst_reg_equivs (ad);
  
        if (! subst_reg_equivs_changed)
  	return 0;
--- 4771,4777 ----
  	return 0;
  
        subst_reg_equivs_changed = 0;
!       *loc = subst_reg_equivs (ad, insn);
  
        if (! subst_reg_equivs_changed)
  	return 0;
*************** find_reloads_address (mode, memrefloc, a
*** 4866,4872 ****
  	 registers.  */
  
        subst_reg_equivs_changed = 0;
!       tem = subst_reg_equivs (tem);
  
        /* Make sure that didn't make the address invalid again.  */
  
--- 4976,4982 ----
  	 registers.  */
  
        subst_reg_equivs_changed = 0;
!       tem = subst_reg_equivs (tem, insn);
  
        /* Make sure that didn't make the address invalid again.  */
  
*************** find_reloads_address (mode, memrefloc, a
*** 4902,4912 ****
  
  /* Find all pseudo regs appearing in AD
     that are eliminable in favor of equivalent values
!    and do not have hard regs; replace them by their equivalents.  */
  
  static rtx
! subst_reg_equivs (ad)
       rtx ad;
  {
    register RTX_CODE code = GET_CODE (ad);
    register int i;
--- 5012,5025 ----
  
  /* Find all pseudo regs appearing in AD
     that are eliminable in favor of equivalent values
!    and do not have hard regs; replace them by their equivalents.
!    INSN, if nonzero, is the insn in which we do the reload.  We put USEs in
!    front of it for pseudos that we have to replace with stack slots.  */
  
  static rtx
! subst_reg_equivs (ad, insn)
       rtx ad;
+      rtx insn;
  {
    register RTX_CODE code = GET_CODE (ad);
    register int i;
*************** subst_reg_equivs (ad)
*** 4933,4938 ****
--- 5046,5061 ----
  	    subst_reg_equivs_changed = 1;
  	    return reg_equiv_constant[regno];
  	  }
+ 	if (reg_equiv_memory_loc[regno] && num_not_at_initial_offset)
+ 	  {
+ 	    rtx mem = make_memloc (ad, regno);
+ 	    if (! rtx_equal_p (mem, reg_equiv_mem[regno]))
+ 	      {
+ 		subst_reg_equivs_changed = 1;
+ 		emit_insn_before (gen_rtx_USE (VOIDmode, ad), insn);
+ 		return mem;
+ 	      }
+ 	  }
        }
        return ad;
  
*************** subst_reg_equivs (ad)
*** 4950,4956 ****
    fmt = GET_RTX_FORMAT (code);
    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
      if (fmt[i] == 'e')
!       XEXP (ad, i) = subst_reg_equivs (XEXP (ad, i));
    return ad;
  }
  
--- 5073,5079 ----
    fmt = GET_RTX_FORMAT (code);
    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
      if (fmt[i] == 'e')
!       XEXP (ad, i) = subst_reg_equivs (XEXP (ad, i), insn);
    return ad;
  }
  
*************** find_reloads_address_1 (mode, x, context
*** 5223,5241 ****
  
  	  /* Handle a register that is equivalent to a memory location
  	     which cannot be addressed directly.  */
! 	  if (reg_equiv_address[regno] != 0)
  	    {
  	      rtx tem = make_memloc (XEXP (x, 0), regno);
! 	      /* First reload the memory location's address.
! 		 We can't use ADDR_TYPE (type) here, because we need to
! 		 write back the value after reading it, hence we actually
! 		 need two registers.  */
! 	      find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
! 				    &XEXP (tem, 0), opnum, type,
! 				    ind_levels, insn);
! 	      /* Put this inside a new increment-expression.  */
! 	      x = gen_rtx_fmt_e (GET_CODE (x), GET_MODE (x), tem);
! 	      /* Proceed to reload that, as if it contained a register.  */
  	    }
  
  	  /* If we have a hard register that is ok as an index,
--- 5346,5369 ----
  
  	  /* Handle a register that is equivalent to a memory location
  	     which cannot be addressed directly.  */
! 	  if (reg_equiv_memory_loc[regno] != 0
! 	      && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
  	    {
  	      rtx tem = make_memloc (XEXP (x, 0), regno);
! 	      if (reg_equiv_address[regno]
! 		  || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
! 		{
! 		  /* First reload the memory location's address.
! 		     We can't use ADDR_TYPE (type) here, because we need to
! 		     write back the value after reading it, hence we actually
! 		     need two registers.  */
! 		  find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
! 					&XEXP (tem, 0), opnum, type,
! 					ind_levels, insn);
! 		  /* Put this inside a new increment-expression.  */
! 		  x = gen_rtx_fmt_e (GET_CODE (x), GET_MODE (x), tem);
! 		  /* Proceed to reload that, as if it contained a register.  */
! 		}
  	    }
  
  	  /* If we have a hard register that is ok as an index,
*************** find_reloads_address_1 (mode, x, context
*** 5268,5276 ****
  		 memory location, since this will make it harder to
  		 reuse address reloads, and increases register pressure.
  		 Also don't do this if we can probably update x directly.  */
! 	      rtx equiv = reg_equiv_mem[regno];
  	      int icode = (int) add_optab->handlers[(int) Pmode].insn_code;
  	      if (insn && GET_CODE (insn) == INSN && equiv
  #ifdef HAVE_cc0
  		  && ! sets_cc0_p (PATTERN (insn))
  #endif
--- 5396,5407 ----
  		 memory location, since this will make it harder to
  		 reuse address reloads, and increases register pressure.
  		 Also don't do this if we can probably update x directly.  */
! 	      rtx equiv = (GET_CODE (XEXP (x, 0)) == MEM
! 			   ? XEXP (x, 0)
! 			   : reg_equiv_mem[regno]);
  	      int icode = (int) add_optab->handlers[(int) Pmode].insn_code;
  	      if (insn && GET_CODE (insn) == INSN && equiv
+ 		  && memory_operand (equiv, GET_MODE (equiv))
  #ifdef HAVE_cc0
  		  && ! sets_cc0_p (PATTERN (insn))
  #endif
*************** find_reloads_address_1 (mode, x, context
*** 5403,5413 ****
  	  }
  #endif
  
! 	if (reg_equiv_address[regno] != 0)
  	  {
! 	    x = make_memloc (x, regno);
! 	    find_reloads_address (GET_MODE (x), 0, XEXP (x, 0), &XEXP (x, 0),
! 				  opnum, ADDR_TYPE (type), ind_levels, insn);
  	  }
  
  	if (reg_renumber[regno] >= 0)
--- 5534,5551 ----
  	  }
  #endif
  
! 	if (reg_equiv_memory_loc[regno]
! 	    && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
  	  {
! 	    rtx tem = make_memloc (x, regno);
! 	    if (reg_equiv_address[regno] != 0
! 		|| ! rtx_equal_p (tem, reg_equiv_mem[regno]))
! 	      {
! 		x = tem;
! 		find_reloads_address (GET_MODE (x), &x, XEXP (x, 0),
! 				      &XEXP (x, 0), opnum, ADDR_TYPE (type),
! 				      ind_levels, insn);
! 	      }
  	  }
  
  	if (reg_renumber[regno] >= 0)
*************** debug_reload_to_stream (f)
*** 6543,6548 ****
--- 6681,6692 ----
  	{
  	  fprintf (f, "\n\treload_in_reg: ");
  	  print_inline_rtx (f, reload_in_reg[r], 24);
+ 	}
+ 
+       if (reload_out_reg[r] != 0)
+ 	{
+ 	  fprintf (f, "\n\treload_out_reg: ");
+ 	  print_inline_rtx (f, reload_out_reg[r], 24);
  	}
  
        if (reload_reg_rtx[r] != 0)
Index: reload.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/reload.h,v
retrieving revision 1.11
diff -p -r1.11 reload.h
*** reload.h	1998/10/07 00:13:48	1.11
--- reload.h	1998/10/08 05:00:17
*************** extern enum reg_class reload_address_ind
*** 55,60 ****
--- 55,61 ----
  extern rtx reload_in[MAX_RELOADS];
  extern rtx reload_out[MAX_RELOADS];
  extern rtx reload_in_reg[MAX_RELOADS];
+ extern rtx reload_out_reg[MAX_RELOADS];
  extern enum reg_class reload_reg_class[MAX_RELOADS];
  extern enum machine_mode reload_inmode[MAX_RELOADS];
  extern enum machine_mode reload_outmode[MAX_RELOADS];
*************** extern char indirect_symref_ok;
*** 134,139 ****
--- 135,142 ----
  /* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid.  */
  extern char double_reg_address_ok;
  
+ extern int num_not_at_initial_offset;
+ 
  #ifdef MAX_INSN_CODE
  /* These arrays record the insn_code of insns that may be needed to
     perform input and output reloads of special objects.  They provide a
*************** extern void clear_secondary_mem PROTO((v
*** 232,239 ****
     reload TO.  */
  extern void transfer_replacements PROTO((int, int));
  
! /* Remove all replacements in reload FROM.  */
! extern void remove_replacements PROTO((int));
  
  /* Like rtx_equal_p except that it allows a REG and a SUBREG to match
     if they are the same hard reg, and has special hacks for
--- 235,245 ----
     reload TO.  */
  extern void transfer_replacements PROTO((int, int));
  
! /* IN_RTX is the value loaded by a reload that we now decided to inherit,
!    or a subpart of it.  If we have any replacements registered for IN_RTX,
!    chancel the reloads that were supposed to load them.
!    Return non-zero if we chanceled any reloads.  */
! extern int remove_address_replacements PROTO((rtx in_rtx));
  
  /* Like rtx_equal_p except that it allows a REG and a SUBREG to match
     if they are the same hard reg, and has special hacks for
*************** extern int safe_from_earlyclobber PROTO(
*** 249,255 ****
  /* 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 void find_reloads PROTO((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
--- 255,261 ----
  /* 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 PROTO((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
*************** extern rtx eliminate_regs PROTO((rtx, en
*** 317,322 ****
--- 323,331 ----
     OUT (which may also be a reload register).  IN or OUT is from operand
     OPNUM with reload type TYPE.  */
  extern rtx gen_reload PROTO((rtx, rtx, int, enum reload_type));
+ 
+ /* Deallocate the reload register used by reload number R.  */
+ extern void deallocate_reload_reg PROTO((int r));
  
  /* Functions in caller-save.c:  */
  
Index: reload1.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/reload1.c,v
retrieving revision 1.74
diff -p -r1.74 reload1.c
*** reload1.c	1998/10/07 09:45:58	1.74
--- reload1.c	1998/10/08 05:00:20
*************** rtx *reg_equiv_mem;
*** 113,119 ****
  /* Widest width in which each pseudo reg is referred to (via subreg).  */
  static int *reg_max_ref_width;
  
! /* Element N is the insn that initialized reg N from its equivalent
     constant or memory slot.  */
  static rtx *reg_equiv_init;
  
--- 113,119 ----
  /* Widest width in which each pseudo reg is referred to (via subreg).  */
  static int *reg_max_ref_width;
  
! /* Element N is the list of insns that initialized reg N from its equivalent
     constant or memory slot.  */
  static rtx *reg_equiv_init;
  
*************** static rtx spill_reg_rtx[FIRST_PSEUDO_RE
*** 148,153 ****
--- 148,158 ----
     The precise value is the insn generated to do the store.  */
  static rtx spill_reg_store[FIRST_PSEUDO_REGISTER];
  
+ /* This is the register that was stored with spill_reg_store.  This is a
+    copy of reload_out / reload_out_reg when the value was stored; if
+    reload_out is a MEM, spill_reg_stored_to will be set to reload_out_reg.  */
+ static rtx spill_reg_stored_to[FIRST_PSEUDO_REGISTER];
+ 
  /* This table is the inverse mapping of spill_regs:
     indexed by hard reg number,
     it contains the position of that reg in spill_regs,
*************** static struct elim_table
*** 338,344 ****
  /* Record the number of pending eliminations that have an offset not equal
     to their initial offset.  If non-zero, we use a new copy of each
     replacement result in any insns encountered.  */
! static int num_not_at_initial_offset;
  
  /* Count the number of registers that we may be able to eliminate.  */
  static int num_eliminable;
--- 343,349 ----
  /* Record the number of pending eliminations that have an offset not equal
     to their initial offset.  If non-zero, we use a new copy of each
     replacement result in any insns encountered.  */
! int num_not_at_initial_offset;
  
  /* Count the number of registers that we may be able to eliminate.  */
  static int num_eliminable;
*************** static void delete_dead_insn		PROTO((rtx
*** 379,384 ****
--- 384,390 ----
  static void alter_reg  			PROTO((int, int));
  static void set_label_offsets		PROTO((rtx, rtx, int));
  static int eliminate_regs_in_insn	PROTO((rtx, int));
+ static void update_eliminables_1	PROTO((void));
  static void mark_not_eliminable		PROTO((rtx, rtx));
  static void set_initial_elim_offsets	PROTO((void));
  static void init_elim_table		PROTO((void));
*************** static int allocate_reload_reg		PROTO((i
*** 403,410 ****
  static void choose_reload_regs		PROTO((rtx, rtx));
  static void merge_assigned_reloads	PROTO((rtx));
  static void emit_reload_insns		PROTO((rtx, int));
! static void delete_output_reload	PROTO((rtx, int, rtx));
! static void inc_for_reload		PROTO((rtx, rtx, int));
  static int constraint_accepts_reg_p	PROTO((char *, rtx));
  static void find_set_and_used_regs	PROTO((rtx, int, int));
  static void calc_reg_usage		PROTO((rtx, int));
--- 409,418 ----
  static void choose_reload_regs		PROTO((rtx, rtx));
  static void merge_assigned_reloads	PROTO((rtx));
  static void emit_reload_insns		PROTO((rtx, int));
! static void delete_output_reload	PROTO((rtx, int, int));
! static void delete_address_reloads	PROTO((rtx, rtx));
! static void delete_address_reloads_1	PROTO((rtx, rtx, rtx));
! static rtx inc_for_reload		PROTO((rtx, rtx, rtx, int));
  static int constraint_accepts_reg_p	PROTO((char *, rtx));
  static void find_set_and_used_regs	PROTO((rtx, int, int));
  static void calc_reg_usage		PROTO((rtx, int));
*************** new_insn_chain ()
*** 567,572 ****
--- 575,582 ----
  static int something_needs_reloads;
  /* Set during calculate_needs if an insn needs register elimination.  */
  static int something_needs_elimination;
+ /* Set during calculate_needs if an insn needs an operand changed.  */
+ int something_needs_operands_changed;
  
  /* For each class, number of reload regs needed in that class.
     This is the maximum over all insns of the needs in that class
*************** reload (first, global, dumpfile)
*** 769,775 ****
  		     So don't mark this insn now.  */
  		  if (GET_CODE (x) != MEM
  		      || rtx_equal_p (SET_SRC (set), x))
! 		    reg_equiv_init[i] = insn;
  		}
  	    }
  	}
--- 779,786 ----
  		     So don't mark this insn now.  */
  		  if (GET_CODE (x) != MEM
  		      || rtx_equal_p (SET_SRC (set), x))
! 		    reg_equiv_init[i]
! 		      = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init[i]);
  		}
  	    }
  	}
*************** reload (first, global, dumpfile)
*** 781,787 ****
  	       && reg_equiv_memory_loc[REGNO (SET_SRC (set))]
  	       && rtx_equal_p (SET_DEST (set),
  			       reg_equiv_memory_loc[REGNO (SET_SRC (set))]))
! 	reg_equiv_init[REGNO (SET_SRC (set))] = insn;
  
        if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
  	scan_paradoxical_subregs (PATTERN (insn));
--- 792,800 ----
  	       && reg_equiv_memory_loc[REGNO (SET_SRC (set))]
  	       && rtx_equal_p (SET_DEST (set),
  			       reg_equiv_memory_loc[REGNO (SET_SRC (set))]))
! 	reg_equiv_init[REGNO (SET_SRC (set))]
! 	  = gen_rtx_INSN_LIST (VOIDmode, insn,
! 			       reg_equiv_init[REGNO (SET_SRC (set))]);
  
        if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
  	scan_paradoxical_subregs (PATTERN (insn));
*************** reload (first, global, dumpfile)
*** 900,905 ****
--- 913,919 ----
    /* This flag is set if there are any insns that require register
       eliminations.  */
    something_needs_elimination = 0;
+   something_needs_operands_changed = 0;
    while (something_changed)
      {
        HOST_WIDE_INT starting_frame_size;
*************** reload (first, global, dumpfile)
*** 1091,1118 ****
       If that insn didn't set the register (i.e., it copied the register to
       memory), just delete that insn instead of the equivalencing insn plus
       anything now dead.  If we call delete_dead_insn on that insn, we may
!      delete the insn that actually sets the register if the register die
       there and that is incorrect.  */
  
    for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
!     if (reg_renumber[i] < 0 && reg_equiv_init[i] != 0
! 	&& GET_CODE (reg_equiv_init[i]) != NOTE)
!       {
! 	if (reg_set_p (regno_reg_rtx[i], PATTERN (reg_equiv_init[i])))
! 	  delete_dead_insn (reg_equiv_init[i]);
! 	else
! 	  {
! 	    PUT_CODE (reg_equiv_init[i], NOTE);
! 	    NOTE_SOURCE_FILE (reg_equiv_init[i]) = 0;
! 	    NOTE_LINE_NUMBER (reg_equiv_init[i]) = NOTE_INSN_DELETED;
! 	  }
!       }
  
    /* Use the reload registers where necessary
       by generating move instructions to move the must-be-register
       values into or out of the reload registers.  */
  
!   if (something_needs_reloads || something_needs_elimination)
      reload_as_needed (first, global);
  
    /* If we were able to eliminate the frame pointer, show that it is no
--- 1105,1141 ----
       If that insn didn't set the register (i.e., it copied the register to
       memory), just delete that insn instead of the equivalencing insn plus
       anything now dead.  If we call delete_dead_insn on that insn, we may
!      delete the insn that actually sets the register if the register dies
       there and that is incorrect.  */
  
    for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
!     {
!       if (reg_renumber[i] < 0 && reg_equiv_init[i] != 0)
! 	{
! 	  rtx list;
! 	  for (list = reg_equiv_init[i]; list; list = XEXP (list, 1))
! 	    {
! 	      rtx equiv_insn = XEXP (list, 0);
! 	      if (GET_CODE (equiv_insn) == NOTE)
! 		continue;
! 	      if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn)))
! 		delete_dead_insn (equiv_insn);
! 	      else
! 		{
! 		  PUT_CODE (equiv_insn, NOTE);
! 		  NOTE_SOURCE_FILE (equiv_insn) = 0;
! 		  NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
! 		}
! 	    }
! 	}
!     }
  
    /* Use the reload registers where necessary
       by generating move instructions to move the must-be-register
       values into or out of the reload registers.  */
  
!   if (something_needs_reloads || something_needs_elimination
!       || something_needs_operands_changed)
      reload_as_needed (first, global);
  
    /* If we were able to eliminate the frame pointer, show that it is no
*************** calculate_needs_all_insns (first, global
*** 1258,1263 ****
--- 1281,1287 ----
    rtx insn;
    int something_changed = 0;
    rtx after_call = 0;
+   int after_call_nregs;
    /* Keep track of which basic blocks are needing the reloads.  */
    int this_block = 0;
  
*************** calculate_needs_all_insns (first, global
*** 1285,1290 ****
--- 1309,1315 ----
  	  int old_code = INSN_CODE (insn);
  	  rtx old_notes = REG_NOTES (insn);
  	  int did_elimination = 0;
+ 	  int operands_changed = 0;
  
  	  /* Nonzero means don't use a reload reg that overlaps
  	     the place where a function value can be returned.  */
*************** calculate_needs_all_insns (first, global
*** 1295,1315 ****
  	  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 needed, eliminate any eliminable registers.  */
--- 1320,1363 ----
  	  if (SMALL_REGISTER_CLASSES && GET_CODE (insn) == CALL_INSN)
  	    {
  	      if (GET_CODE (PATTERN (insn)) == SET)
! 		{
! 		  after_call = SET_DEST (PATTERN (insn));
! 		  after_call_nregs = HARD_REGNO_NREGS (REGNO (after_call),
! 						       GET_MODE (after_call));
! 		}
  	      else if (GET_CODE (PATTERN (insn)) == PARALLEL
  		       && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
! 		{
! 		  after_call = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
! 		  after_call_nregs = HARD_REGNO_NREGS (REGNO (after_call),
! 						       GET_MODE (after_call));
! 		}
  	      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)) != CLOBBER
  		   && GET_CODE (PATTERN (insn)) != USE)
  	    {
  	      if (reg_referenced_p (after_call, PATTERN (insn)))
! 		{
! 		  avoid_return_reg = after_call;
! 		  if (! --after_call_nregs)
! 		    after_call = 0;
! 		  else
! 		    {
! 		      /* If INSN copies the return register in a single chunk,
! 			 clear after_call now.  */
! 		      rtx set = single_set (insn);
! 		      if (set && (GET_MODE_SIZE (GET_MODE (SET_DEST (set)))
! 				  == GET_MODE_SIZE (GET_MODE (after_call))))
! 			after_call = 0;
! 		    }
! 		}
! 	      else
! 		after_call = 0;
  	    }
  
  	  /* If needed, eliminate any eliminable registers.  */
*************** calculate_needs_all_insns (first, global
*** 1317,1325 ****
  	    did_elimination = eliminate_regs_in_insn (insn, 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.
  
--- 1365,1397 ----
  	    did_elimination = eliminate_regs_in_insn (insn, 0);
  
  	  /* Analyze the instruction.  */
! 	  operands_changed = find_reloads (insn, 0, spill_indirect_levels,
! 					   global, spill_reg_order);
  
+ 	  /* If a no-op set needs more than one reload, this is likely
+ 	     to be something that needs input address reloads.  We
+ 	     can't get rid of this cleanly later, and it is of no use
+ 	     anyway, so discard it now.
+ 	     We only do this when expensive_optimizations is enabled,
+ 	     since this complements reload inheritance / output
+ 	     reload deletion, and it can make debugging harder.  */
+ 	  if (flag_expensive_optimizations && n_reloads > 1)
+ 	    {
+ 	      rtx set = single_set (insn);
+ 	      if (set
+ 		  && SET_SRC (set) == SET_DEST (set)
+ 		  && GET_CODE (SET_SRC (set)) == REG
+ 		  && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER)
+ 		{
+ 		  PUT_CODE (insn, NOTE);
+ 		  NOTE_SOURCE_FILE (insn) = 0;
+ 		  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ 		  continue;
+ 		}
+ 	    }
+ 	  if (num_eliminable)
+ 	    update_eliminables_1 ();
+ 
  	  /* Remember for later shortcuts which insns had any reloads or
  	     register eliminations.
  
*************** calculate_needs_all_insns (first, global
*** 1335,1341 ****
  	     but not register replacement.  */
  
  	  PUT_MODE (insn, (did_elimination ? QImode
! 			   : n_reloads ? HImode
  			   : GET_MODE (insn) == DImode ? DImode
  			   : VOIDmode));
  
--- 1407,1413 ----
  	     but not register replacement.  */
  
  	  PUT_MODE (insn, (did_elimination ? QImode
! 			   : (n_reloads | operands_changed) ? HImode
  			   : GET_MODE (insn) == DImode ? DImode
  			   : VOIDmode));
  
*************** calculate_needs_all_insns (first, global
*** 1349,1354 ****
--- 1421,1428 ----
  	      something_needs_elimination = 1;
  	    }
  
+ 	  something_needs_operands_changed |= operands_changed;
+ 
  	  if (n_reloads != 0)
  	    something_changed |= calculate_needs (this_block, insn,
  						  avoid_return_reg, global);
*************** eliminate_regs (x, mem_mode, insn)
*** 2772,2798 ****
  	      }
  
  	}
-       else if (reg_equiv_memory_loc && reg_equiv_memory_loc[regno]
- 	       && (reg_equiv_address[regno] || num_not_at_initial_offset))
- 	{
- 	  /* In this case, find_reloads would attempt to either use an
- 	     incorrect address (if something is not at its initial offset)
- 	     or substitute an replaced address into an insn (which loses
- 	     if the offset is changed by some later action).  So we simply
- 	     return the replaced stack slot (assuming it is changed by
- 	     elimination) and ignore the fact that this is actually a
- 	     reference to the pseudo.  Ensure we make a copy of the
- 	     address in case it is shared.  */
- 	  new = eliminate_regs (reg_equiv_memory_loc[regno], mem_mode, insn);
- 	  if (new != reg_equiv_memory_loc[regno])
- 	    {
- 	      if (insn != 0 && GET_CODE (insn) != EXPR_LIST
- 		  && GET_CODE (insn) != INSN_LIST)
- 		REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode, x), insn))
- 		  = gen_rtx_EXPR_LIST (REG_EQUAL, new, NULL_RTX);
- 	      return copy_rtx (new);
- 	    }
- 	}
        return x;
  
      case PLUS:
--- 2846,2851 ----
*************** eliminate_regs (x, mem_mode, insn)
*** 3000,3005 ****
--- 3053,3059 ----
  	  && reg_equiv_memory_loc != 0
  	  && reg_equiv_memory_loc[REGNO (SUBREG_REG (x))] != 0)
  	{
+ #if 0
  	  new = eliminate_regs (reg_equiv_memory_loc[REGNO (SUBREG_REG (x))],
  				mem_mode, insn);
  
*************** eliminate_regs (x, mem_mode, insn)
*** 3020,3025 ****
--- 3074,3082 ----
  	      /* Ensure NEW isn't shared in case we have to reload it.  */
  	      new = copy_rtx (new);
  	    }
+ #else
+ 	  new = SUBREG_REG (x);
+ #endif
  	}
        else
  	new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
*************** eliminate_regs_in_insn (insn, replace)
*** 3382,3388 ****
  	 in the insn is the negative of the offset in FROM.  Substitute
  	 (set (reg) (reg to)) for the insn and change its code.
  
! 	 We have to do this here, rather than in eliminate_regs, do that we can
  	 change the insn code.  */
  
        if (GET_CODE (SET_SRC (old_set)) == PLUS
--- 3439,3445 ----
  	 in the insn is the negative of the offset in FROM.  Substitute
  	 (set (reg) (reg to)) for the insn and change its code.
  
! 	 We have to do this here, rather than in eliminate_regs, so that we can
  	 change the insn code.  */
  
        if (GET_CODE (SET_SRC (old_set)) == PLUS
*************** eliminate_regs_in_insn (insn, replace)
*** 3468,3479 ****
  
        val = 1;
      }
- 
-   /* Loop through all elimination pairs.  See if any have changed and
-      recalculate the number not at initial offset.
  
!      Compute the maximum offset (minimum offset if the stack does not
!      grow downward) for each elimination pair.
  
       We also detect a cases where register elimination cannot be done,
       namely, if a register would be both changed and referenced outside a MEM
--- 3525,3532 ----
  
        val = 1;
      }
  
!   /* Loop through all elimination pairs.  See if any have changed.
  
       We also detect a cases where register elimination cannot be done,
       namely, if a register would be both changed and referenced outside a MEM
*************** eliminate_regs_in_insn (insn, replace)
*** 3484,3490 ****
  
       If anything changes, return nonzero.  */
  
-   num_not_at_initial_offset = 0;
    for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
      {
        if (ep->previous_offset != ep->offset && ep->ref_outside_mem)
--- 3537,3542 ----
*************** eliminate_regs_in_insn (insn, replace)
*** 3494,3509 ****
  
        if (ep->previous_offset != ep->offset)
  	val = 1;
- 
-       ep->previous_offset = ep->offset;
-       if (ep->can_eliminate && ep->offset != ep->initial_offset)
- 	num_not_at_initial_offset++;
- 
- #ifdef STACK_GROWS_DOWNWARD
-       ep->max_offset = MAX (ep->max_offset, ep->offset);
- #else
-       ep->max_offset = MIN (ep->max_offset, ep->offset);
- #endif
      }
  
   done:
--- 3546,3551 ----
*************** eliminate_regs_in_insn (insn, replace)
*** 3521,3526 ****
--- 3563,3594 ----
    return val;
  }
  
+ /* Loop through all elimination pairs.
+    Recalculate the number not at initial offset.
+ 
+    Compute the maximum offset (minimum offset if the stack does not
+    grow downward) for each elimination pair.  */
+ 
+ static void
+ update_eliminables_1 ()
+ {
+   struct elim_table *ep;
+ 
+   num_not_at_initial_offset = 0;
+   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+     {
+       ep->previous_offset = ep->offset;
+       if (ep->can_eliminate && ep->offset != ep->initial_offset)
+ 	num_not_at_initial_offset++;
+ 
+ #ifdef STACK_GROWS_DOWNWARD
+       ep->max_offset = MAX (ep->max_offset, ep->offset);
+ #else
+       ep->max_offset = MIN (ep->max_offset, ep->offset);
+ #endif
+     }
+ }
+ 
  /* Given X, a SET or CLOBBER of DEST, if DEST is the target of a register
     replacement we currently believe is valid, mark it as not eliminable if X
     modifies DEST in any way other than by adding a constant integer to it.
*************** reload_as_needed (first, live_known)
*** 4029,4034 ****
--- 4097,4103 ----
    int this_block = 0;
    rtx x;
    rtx after_call = 0;
+   int after_call_nregs;
  
    bzero ((char *) spill_reg_rtx, sizeof spill_reg_rtx);
    bzero ((char *) spill_reg_store, sizeof spill_reg_store);
*************** reload_as_needed (first, live_known)
*** 4066,4071 ****
--- 4135,4141 ----
    for (insn = first; insn;)
      {
        register rtx next = NEXT_INSN (insn);
+       rtx prev;
  
        /* Notice when we move to a new basic block.  */
        if (live_known && this_block + 1 < n_basic_blocks
*************** reload_as_needed (first, live_known)
*** 4098,4118 ****
  	  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
--- 4168,4211 ----
  	  if (SMALL_REGISTER_CLASSES && GET_CODE (insn) == CALL_INSN)
  	    {
  	      if (GET_CODE (PATTERN (insn)) == SET)
! 		{
! 		  after_call = SET_DEST (PATTERN (insn));
! 		  after_call_nregs = HARD_REGNO_NREGS (REGNO (after_call),
! 						       GET_MODE (after_call));
! 		}
  	      else if (GET_CODE (PATTERN (insn)) == PARALLEL
  		       && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
! 		{
! 		  after_call = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
! 		  after_call_nregs = HARD_REGNO_NREGS (REGNO (after_call),
! 						       GET_MODE (after_call));
! 		}
  	      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)) != CLOBBER
  		   && GET_CODE (PATTERN (insn)) != USE)
  	    {
  	      if (reg_referenced_p (after_call, PATTERN (insn)))
! 		{
! 		  avoid_return_reg = after_call;
! 		  if (! --after_call_nregs)
! 		    after_call = 0;
! 		  else
! 		    {
! 		      /* If INSN copies the return register in a single chunk,
! 			 clear after_call now.  */
! 		      rtx set = single_set (insn);
! 		      if (set && (GET_MODE_SIZE (GET_MODE (SET_DEST (set)))
! 				  == GET_MODE_SIZE (GET_MODE (after_call))))
! 			after_call = 0;
! 		    }
! 		}
! 	      else
! 		after_call = 0;
  	    }
  
  	  /* If this is a USE and CLOBBER of a MEM, ensure that any
*************** reload_as_needed (first, live_known)
*** 4133,4138 ****
--- 4226,4232 ----
  	      eliminate_regs_in_insn (insn, 1);
  	      if (GET_CODE (insn) == NOTE)
  		{
+ 		  update_eliminables_1 ();
  		  insn = next;
  		  continue;
  		}
*************** reload_as_needed (first, live_known)
*** 4153,4164 ****
  			    spill_reg_order);
  	    }
  
  	  if (n_reloads > 0)
  	    {
! 	      rtx prev = PREV_INSN (insn), next = NEXT_INSN (insn);
  	      rtx p;
  	      int class;
  
  	      /* If this block has not had spilling done for a
  		 particular clas and we have any non-optionals that need a
  		 spill reg in that class, abort.  */
--- 4247,4263 ----
  			    spill_reg_order);
  	    }
  
+ 	  if (num_eliminable && GET_MODE (insn) == QImode)
+ 	    update_eliminables_1 ();
+ 
  	  if (n_reloads > 0)
  	    {
! 	      rtx next = NEXT_INSN (insn);
  	      rtx p;
  	      int class;
  
+ 	      prev = PREV_INSN (insn);
+ 
  	      /* 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.  */
*************** reload_as_needed (first, live_known)
*** 4230,4235 ****
--- 4329,4382 ----
  
  #ifdef AUTO_INC_DEC
  	  /* Likewise for regs altered by auto-increment in this insn.
+ 	     REG_INC notes have been changed by reloading:
+ 	     find_reloads_address_1 records substitutions for them,
+ 	     which have been performed by subst_reloads above.  */
+ 	  for (i = n_reloads - 1; i >= 0; i--)
+ 	    {
+ 	      rtx in_reg = reload_in_reg[i];
+ 	      if (in_reg)
+ 		{
+ 		  enum rtx_code code = GET_CODE (in_reg);
+ 		  /* PRE_INC / PRE_DEC will have the reload register ending up
+ 		     with the same value as the stack slot, but that doesn't
+ 		     hold true for POST_INC / POST_DEC.  Either we have to
+ 		     convert the memory access to a true POST_INC / POST_DEC,
+ 		     or we can't use the reload register for inheritance.  */
+ 		  if ((code == POST_INC || code == POST_DEC)
+ 		      && TEST_HARD_REG_BIT (reg_reloaded_valid,
+ 					    REGNO (reload_reg_rtx[i])))
+ 		    {
+ 		      rtx reload_reg = reload_reg_rtx[i];
+ 		      enum machine_mode mode = GET_MODE (reload_reg);
+ 		      int n = 0;
+ 		      rtx p;
+ 
+ 		      for (p = PREV_INSN (next); p != prev; p = PREV_INSN (p))
+ 			{
+ 			  /* We really want to ignore REG_INC notes here, so
+ 			     use PATTERN (p) as argument to reg_set_p .  */
+ 			  if (reg_set_p (reload_reg, PATTERN (p)))
+ 			    break;
+ 			  n = count_occurrences (PATTERN (p), reload_reg);
+ 			  if (! n)
+ 			    continue;
+ 			  if (n == 1)
+ 			    n = validate_replace_rtx (reload_reg,
+ 						      gen_rtx (code, mode,
+ 							       reload_reg), p);
+ 			  break;
+ 			}
+ 		      if (n == 1)
+ 			REG_NOTES (p) = gen_rtx_EXPR_LIST (REG_INC, reload_reg,
+ 							   REG_NOTES (p));
+ 		      else
+ 			forget_old_reloads_1 (XEXP (in_reg, 0), NULL_RTX);
+ 		    }
+ 		}
+ 	    }
+ #if 0 /* ??? Is this code obsolete now?  Need to check carefully. */
+ 	  /* Likewise for regs altered by auto-increment in this insn.
  	     But note that the reg-notes are not changed by reloading:
  	     they still contain the pseudo-regs, not the spill regs.  */
  	  for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
*************** reload_as_needed (first, live_known)
*** 4246,4251 ****
--- 4393,4399 ----
  		  forget_old_reloads_1 (XEXP (x, 0), NULL_RTX);
  	      }
  #endif
+ #endif
  	}
        /* A reload reg's contents are unknown after a label.  */
        if (GET_CODE (insn) == CODE_LABEL)
*************** clear_reload_reg_in_use (regno, opnum, t
*** 4483,4539 ****
       enum machine_mode mode;
  {
    int nregs = HARD_REGNO_NREGS (regno, mode);
    int i;
  
!   for (i = regno; i < nregs + regno; i++)
      {
!       switch (type)
! 	{
! 	case RELOAD_OTHER:
! 	  CLEAR_HARD_REG_BIT (reload_reg_used, i);
! 	  break;
  
! 	case RELOAD_FOR_INPUT_ADDRESS:
! 	  CLEAR_HARD_REG_BIT (reload_reg_used_in_input_addr[opnum], i);
! 	  break;
  
! 	case RELOAD_FOR_INPADDR_ADDRESS:
! 	  CLEAR_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[opnum], i);
! 	  break;
  
! 	case RELOAD_FOR_OUTPUT_ADDRESS:
! 	  CLEAR_HARD_REG_BIT (reload_reg_used_in_output_addr[opnum], i);
! 	  break;
  
! 	case RELOAD_FOR_OUTADDR_ADDRESS:
! 	  CLEAR_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], i);
! 	  break;
  
! 	case RELOAD_FOR_OPERAND_ADDRESS:
! 	  CLEAR_HARD_REG_BIT (reload_reg_used_in_op_addr, i);
! 	  break;
  
! 	case RELOAD_FOR_OPADDR_ADDR:
! 	  CLEAR_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, i);
! 	  break;
  
! 	case RELOAD_FOR_OTHER_ADDRESS:
! 	  CLEAR_HARD_REG_BIT (reload_reg_used_in_other_addr, i);
! 	  break;
  
! 	case RELOAD_FOR_INPUT:
! 	  CLEAR_HARD_REG_BIT (reload_reg_used_in_input[opnum], i);
! 	  break;
  
! 	case RELOAD_FOR_OUTPUT:
! 	  CLEAR_HARD_REG_BIT (reload_reg_used_in_output[opnum], i);
! 	  break;
  
! 	case RELOAD_FOR_INSN:
! 	  CLEAR_HARD_REG_BIT (reload_reg_used_in_insn, i);
! 	  break;
  	}
      }
  }
  
  /* 1 if reg REGNO is free as a reload reg for a reload of the sort
--- 4631,4734 ----
       enum machine_mode mode;
  {
    int nregs = HARD_REGNO_NREGS (regno, mode);
+   int start_regno, end_regno;
    int i;
+   /* A complication is that for some reload types, inheritance might
+      allow multiple reloads of the same types to share a reload register.
+      We set check_opnum if we have to check only reloads with the same
+      operand number, and check_any if we have to check all reloads.  */
+   int check_opnum = 0;
+   int check_any = 0;
+   HARD_REG_SET *used_in_set;
  
!   switch (type)
      {
!     case RELOAD_OTHER:
!       used_in_set = &reload_reg_used;
!       break;
  
!     case RELOAD_FOR_INPUT_ADDRESS:
!       used_in_set = &reload_reg_used_in_input_addr[opnum];
!       break;
  
!     case RELOAD_FOR_INPADDR_ADDRESS:
!       check_opnum = 1;
!       used_in_set = &reload_reg_used_in_inpaddr_addr[opnum];
!       break;
  
!     case RELOAD_FOR_OUTPUT_ADDRESS:
!       used_in_set = &reload_reg_used_in_output_addr[opnum];
!       break;
  
!     case RELOAD_FOR_OUTADDR_ADDRESS:
!       check_opnum = 1;
!       used_in_set = &reload_reg_used_in_outaddr_addr[opnum];
!       break;
  
!     case RELOAD_FOR_OPERAND_ADDRESS:
!       used_in_set = &reload_reg_used_in_op_addr;
!       break;
  
!     case RELOAD_FOR_OPADDR_ADDR:
!       check_any = 1;
!       used_in_set = &reload_reg_used_in_op_addr_reload;
!       break;
  
!     case RELOAD_FOR_OTHER_ADDRESS:
!       used_in_set = &reload_reg_used_in_other_addr;
!       check_any = 1;
!       break;
  
!     case RELOAD_FOR_INPUT:
!       used_in_set = &reload_reg_used_in_input[opnum];
!       break;
  
!     case RELOAD_FOR_OUTPUT:
!       used_in_set = &reload_reg_used_in_output[opnum];
!       break;
  
!     case RELOAD_FOR_INSN:
!       used_in_set = &reload_reg_used_in_insn;
!       break;
!     default:
!       abort ();
!     }
!   /* We resolve conflicts with remaining reloads of the same type by
!      excluding the intervals of of reload registers by them from the
!      interval of freed reload registers.  Since we only keep track of
!      one set of interval bounds, we might have to exclude somewhat
!      more then what would be necessary if we used a HARD_REG_SET here.
!      But this should only happen very infrequently, so there should
!      be no reason to worry about it.  */
!     
!   start_regno = regno;
!   end_regno = regno + nregs;
!   if (check_opnum || check_any)
!     {
!       for (i = n_reloads - 1; i >= 0; i--)
! 	{
! 	  if (reload_when_needed[i] == type
! 	      && (check_any || reload_opnum[i] == opnum)
! 	      && reload_reg_rtx[i])
! 	    {
! 	      int conflict_start = true_regnum (reload_reg_rtx[i]);
! 	      int conflict_end
! 		= (conflict_start
! 		   + HARD_REGNO_NREGS (conflict_start, reload_mode[i]));
! 
! 	      /* If there is an overlap with the first to-be-freed register,
! 		 adjust the interval start.  */
! 	      if (conflict_start <= start_regno && conflict_end > start_regno)
! 		start_regno = conflict_end;
! 	      /* Otherwise, if there is a conflict with one of the other
! 		 to-be-freed registers, adjust the interval end.  */
! 	      if (conflict_start > start_regno && conflict_start < end_regno)
! 		end_regno = conflict_start;
! 	    }
  	}
      }
+   for (i = start_regno; i < end_regno; i++)
+     CLEAR_HARD_REG_BIT (*used_in_set, i);
  }
  
  /* 1 if reg REGNO is free as a reload reg for a reload of the sort
*************** reload_reg_free_before_p (regno, opnum, 
*** 4814,4822 ****
  
        /* The only things earlier are the address for this and
  	 earlier inputs, other inputs (which we know we don't conflict
! 	 with), and addresses of RELOAD_OTHER objects.  */
  
!       for (i = 0; i <= opnum; i++)
  	if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
  	    || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
  	  return 0;
--- 5009,5019 ----
  
        /* The only things earlier are the address for this and
  	 earlier inputs, other inputs (which we know we don't conflict
! 	 with), and addresses of RELOAD_OTHER objects.
! 	 We can ignore the conflict with addresses of this operand, since
!          when we inherit this operand, its address reloads are discarded.  */
  
!       for (i = 0; i < opnum; i++)
  	if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
  	    || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
  	  return 0;
*************** reload_reg_free_for_value_p (regno, opnu
*** 5129,5146 ****
      case RELOAD_FOR_INPUT_ADDRESS:
        time1 = opnum * 4 + 2;
        break;
      case RELOAD_FOR_INPUT:
        /* All RELOAD_FOR_INPUT reloads remain live till just before the
  	 instruction is executed.  */
!       time1 = (MAX_RECOG_OPERANDS - 1) * 4 + 3;
        break;
!     /* opnum * 4 + 3 < opnum * 4 + 4
!        <= (MAX_RECOG_OPERANDS - 1) * 4 + 4 == MAX_RECOG_OPERANDS * 4 */
      case RELOAD_FOR_OUTPUT_ADDRESS:
!       time1 = MAX_RECOG_OPERANDS * 4 + opnum;
        break;
      default:
!       time1 = MAX_RECOG_OPERANDS * 5;
      }
  
    for (i = 0; i < n_reloads; i++)
--- 5326,5351 ----
      case RELOAD_FOR_INPUT_ADDRESS:
        time1 = opnum * 4 + 2;
        break;
+     case RELOAD_FOR_OPADDR_ADDR:
+     /* opnum * 4 + 3 < opnum * 4 + 4
+        <= (MAX_RECOG_OPERANDS - 1) * 4 + 4 == MAX_RECOG_OPERANDS * 4 */
+       time1 = MAX_RECOG_OPERANDS * 4;
+       break;
      case RELOAD_FOR_INPUT:
        /* All RELOAD_FOR_INPUT reloads remain live till just before the
  	 instruction is executed.  */
!       time1 = MAX_RECOG_OPERANDS * 4 + 1;
        break;
!     case RELOAD_FOR_OPERAND_ADDRESS:
!       /* RELOAD_FOR_OPERAND_ADDRESS reloads are live even while the insn
! 	 is executed.  */
!       time1 = MAX_RECOG_OPERANDS * 4 + 2;
!       break;
      case RELOAD_FOR_OUTPUT_ADDRESS:
!       time1 = MAX_RECOG_OPERANDS * 4 + 3 + opnum;
        break;
      default:
!       time1 = MAX_RECOG_OPERANDS * 5 + 3;
      }
  
    for (i = 0; i < n_reloads; i++)
*************** reload_reg_free_for_value_p (regno, opnu
*** 5166,5171 ****
--- 5371,5384 ----
  		  time2 = 0;
  		  break;
  		case RELOAD_FOR_INPADDR_ADDRESS:
+ 		  /* find_reloads makes sure that a
+ 		     RELOAD_FOR_{INP,OP,OUT}ADDR_ADDRESS reload is only used
+ 		     by at most one - the first -
+ 		     RELOAD_FOR_{INPUT,OPERAND,OUTPUT}_ADDRESS .  If the
+ 		     address reload is inherited, the address address reload
+ 		     goes away, so we can ignore this conflict.  */
+ 		  if (type == RELOAD_FOR_INPUT_ADDRESS && reloadnum == i + 1)
+ 		    continue;
  		  time2 = reload_opnum[i] * 4 + 1;
  		  break;
  		case RELOAD_FOR_INPUT_ADDRESS:
*************** reload_reg_free_for_value_p (regno, opnu
*** 5174,5193 ****
  		case RELOAD_FOR_INPUT:
  		  time2 = reload_opnum[i] * 4 + 3;
  		  break;
  		case RELOAD_FOR_OUTPUT:
  		/* All RELOAD_FOR_OUTPUT reloads become live just after the
  		   instruction is executed.  */
! 		  time2 = MAX_RECOG_OPERANDS * 4;
  		  break;
  		/* The first RELOAD_FOR_OUTPUT_ADDRESS reload conflicts with the
  		   RELOAD_FOR_OUTPUT reloads, so assign it the same time value.  */
  		case RELOAD_FOR_OUTPUT_ADDRESS:
! 		  time2 = MAX_RECOG_OPERANDS * 4 + reload_opnum[i];
  		  break;
  		case RELOAD_OTHER:
  		  if (! reload_in[i] || rtx_equal_p (reload_in[i], value))
  		    {
! 		      time2 = MAX_RECOG_OPERANDS * 4;
  		      break;
  		    }
  		default:
--- 5387,5418 ----
  		case RELOAD_FOR_INPUT:
  		  time2 = reload_opnum[i] * 4 + 3;
  		  break;
+ 		case RELOAD_FOR_OPADDR_ADDR:
+ 		  if (type == RELOAD_FOR_OPERAND_ADDRESS && reloadnum == i + 1)
+ 		    continue;
+ 		  time2 = MAX_RECOG_OPERANDS * 4;
+ 		  break;
+ 		case RELOAD_FOR_OPERAND_ADDRESS:
+ 		  time2 = MAX_RECOG_OPERANDS * 4 + 1;
+ 		  break;
  		case RELOAD_FOR_OUTPUT:
  		/* All RELOAD_FOR_OUTPUT reloads become live just after the
  		   instruction is executed.  */
! 		  time2 = MAX_RECOG_OPERANDS * 4 + 3;
  		  break;
+ 		case RELOAD_FOR_OUTADDR_ADDRESS:
+ 		  if (type == RELOAD_FOR_OUTPUT_ADDRESS && reloadnum == i + 1)
+ 		    continue;
+ 		/* fall through. */
  		/* The first RELOAD_FOR_OUTPUT_ADDRESS reload conflicts with the
  		   RELOAD_FOR_OUTPUT reloads, so assign it the same time value.  */
  		case RELOAD_FOR_OUTPUT_ADDRESS:
! 		  time2 = MAX_RECOG_OPERANDS * 4 + 3 + reload_opnum[i];
  		  break;
  		case RELOAD_OTHER:
  		  if (! reload_in[i] || rtx_equal_p (reload_in[i], value))
  		    {
! 		      time2 = MAX_RECOG_OPERANDS * 4 + 3;
  		      break;
  		    }
  		default:
*************** choose_reload_regs (insn, avoid_return_r
*** 5425,5430 ****
--- 5650,5656 ----
    int max_group_size = 1;
    enum reg_class group_class = NO_REGS;
    int inheritance;
+   int pass;
  
    rtx save_reload_reg_rtx[MAX_RELOADS];
    char save_reload_inherited[MAX_RELOADS];
*************** choose_reload_regs (insn, avoid_return_r
*** 5682,5687 ****
--- 5908,5914 ----
  
  	  if (inheritance)
  	    {
+ 	      int word = 0;
  	      register int regno = -1;
  	      enum machine_mode mode;
  
*************** choose_reload_regs (insn, avoid_return_r
*** 5697,5729 ****
  		  regno = REGNO (reload_in_reg[r]);
  		  mode = GET_MODE (reload_in_reg[r]);
  		}
! 	      else if (GET_CODE (reload_in[r]) == MEM)
  		{
! 		  rtx prev = prev_nonnote_insn (insn), note;
! 
! 		  if (prev && GET_CODE (prev) == INSN
! 		      && GET_CODE (PATTERN (prev)) == USE
! 		      && GET_CODE (XEXP (PATTERN (prev), 0)) == REG
! 		      && (REGNO (XEXP (PATTERN (prev), 0))
! 			  >= FIRST_PSEUDO_REGISTER)
! 		      && (note = find_reg_note (prev, REG_EQUAL, NULL_RTX))
! 		      && GET_CODE (XEXP (note, 0)) == MEM)
! 		    {
! 		      rtx addr = XEXP (XEXP (note, 0), 0);
! 		      int size_diff
! 			= (GET_MODE_SIZE (GET_MODE (addr))
! 			   - GET_MODE_SIZE (GET_MODE (reload_in[r])));
! 		      if (size_diff >= 0
! 			  && rtx_equal_p ((BYTES_BIG_ENDIAN
! 					   ? plus_constant (addr, size_diff)
! 					   : addr),
! 					  XEXP (reload_in[r], 0)))
! 			{
! 			  regno = REGNO (XEXP (PATTERN (prev), 0));
! 			  mode = GET_MODE (reload_in[r]);
! 			}
! 		    }
  		}
  #if 0
  	      /* This won't work, since REGNO can be a pseudo reg number.
  		 Also, it takes much more hair to keep track of all the things
--- 5924,5950 ----
  		  regno = REGNO (reload_in_reg[r]);
  		  mode = GET_MODE (reload_in_reg[r]);
  		}
! 	      else if (GET_CODE (reload_in_reg[r]) == SUBREG
! 		       && GET_CODE (SUBREG_REG (reload_in_reg[r])) == REG)
  		{
! 		  word = SUBREG_WORD (reload_in_reg[r]);
! 		  regno = REGNO (SUBREG_REG (reload_in_reg[r]));
! 		  if (regno < FIRST_PSEUDO_REGISTER)
! 		    regno += word;
! 		  mode = GET_MODE (reload_in_reg[r]);
! 		}
! #ifdef AUTO_INC_DEC
! 	      else if ((GET_CODE (reload_in_reg[r]) == PRE_INC
! 			|| GET_CODE (reload_in_reg[r]) == PRE_DEC
! 			|| GET_CODE (reload_in_reg[r]) == POST_INC
! 			|| GET_CODE (reload_in_reg[r]) == POST_DEC)
! 		       && GET_CODE (XEXP (reload_in_reg[r], 0)) == REG)
! 		{
! 		  regno = REGNO (XEXP (reload_in_reg[r], 0));
! 		  mode = GET_MODE (XEXP (reload_in_reg[r], 0));
! 		  reload_out[r] = reload_in[r];
  		}
+ #endif
  #if 0
  	      /* This won't work, since REGNO can be a pseudo reg number.
  		 Also, it takes much more hair to keep track of all the things
*************** choose_reload_regs (insn, avoid_return_r
*** 5735,5749 ****
  
  	      if (regno >= 0 && reg_last_reload_reg[regno] != 0)
  		{
! 		  i = REGNO (reg_last_reload_reg[regno]);
! 
! 		  if (reg_reloaded_contents[i] == regno
  		      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
- 		      && (GET_MODE_SIZE (GET_MODE (reg_last_reload_reg[regno]))
- 			  >= GET_MODE_SIZE (mode))
  		      && HARD_REGNO_MODE_OK (i, reload_mode[r])
! 		      && TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
! 					    i)
  		      && (reload_nregs[r] == max_group_size
  			  || ! TEST_HARD_REG_BIT (reg_class_contents[(int) group_class],
  						  i))
--- 5956,5989 ----
  
  	      if (regno >= 0 && reg_last_reload_reg[regno] != 0)
  		{
! 		  enum reg_class class = reload_reg_class[r], last_class;
! 		  rtx last_reg = reg_last_reload_reg[regno];
! 		  
! 		  i = REGNO (last_reg) + word;
! 		  last_class = REGNO_REG_CLASS (i);
! 		  if ((GET_MODE_SIZE (GET_MODE (last_reg))
! 		       >= GET_MODE_SIZE (mode) + word * UNITS_PER_WORD)
! 		      && reg_reloaded_contents[i] == regno
  		      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
  		      && HARD_REGNO_MODE_OK (i, reload_mode[r])
! 		      && (TEST_HARD_REG_BIT (reg_class_contents[(int) class], i)
! 			  /* Even if we can't use this register as a reload
! 			     register, we might use it for reload_override_in,
! 			     if copying it to the desired class is cheap
! 			     enough.  */
! 			  || ((REGISTER_MOVE_COST (last_class, class)
! 			       < MEMORY_MOVE_COST (mode, class, 1))
! #ifdef SECONDARY_INPUT_RELOAD_CLASS
! 			      && (SECONDARY_INPUT_RELOAD_CLASS (class, mode,
! 								last_reg)
! 				  == NO_REGS)
! #endif
! #ifdef SECONDARY_MEMORY_NEEDED
! 			      && ! SECONDARY_MEMORY_NEEDED (last_class, class,
! 							    mode)
! #endif
! 			      ))
! 
  		      && (reload_nregs[r] == max_group_size
  			  || ! TEST_HARD_REG_BIT (reg_class_contents[(int) group_class],
  						  i))
*************** choose_reload_regs (insn, avoid_return_r
*** 5772,5777 ****
--- 6012,6020 ----
  			{
  			  int i1;
  
+ 			  last_reg = (GET_MODE (last_reg) == mode
+ 				      ? last_reg : gen_rtx_REG (mode, i));
+ 
  			  /* We found a register that contains the
  			     value we need.  If this register is the
  			     same as an `earlyclobber' operand of the
*************** choose_reload_regs (insn, avoid_return_r
*** 5794,5806 ****
  				 if we need it wider than we've got it.  */
  			      || (GET_MODE_SIZE (reload_mode[r])
  				  > GET_MODE_SIZE (mode))
  			      /* If find_reloads chose reload_out as reload
  				 register, stay with it - that leaves the
  				 inherited register for subsequent reloads.  */
  			      || (reload_out[r] && reload_reg_rtx
  				  && rtx_equal_p (reload_out[r],
  						  reload_reg_rtx[r])))
! 			    reload_override_in[r] = reg_last_reload_reg[regno];
  			  else
  			    {
  			      int k;
--- 6037,6056 ----
  				 if we need it wider than we've got it.  */
  			      || (GET_MODE_SIZE (reload_mode[r])
  				  > GET_MODE_SIZE (mode))
+ 			      || ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
+ 						      i)
+ 
  			      /* If find_reloads chose reload_out as reload
  				 register, stay with it - that leaves the
  				 inherited register for subsequent reloads.  */
  			      || (reload_out[r] && reload_reg_rtx
  				  && rtx_equal_p (reload_out[r],
  						  reload_reg_rtx[r])))
! 			    {
! 			      reload_override_in[r] = last_reg;
! 			      reload_inheritance_insn[r]
! 				= reg_reloaded_insn[i];
! 			    }
  			  else
  			    {
  			      int k;
*************** choose_reload_regs (insn, avoid_return_r
*** 5811,5817 ****
  						      reload_opnum[r],
  						      reload_when_needed[r],
  						      reload_mode[r]);
! 			      reload_reg_rtx[r] = reg_last_reload_reg[regno];
  			      reload_inherited[r] = 1;
  			      reload_inheritance_insn[r]
  				= reg_reloaded_insn[i];
--- 6061,6067 ----
  						      reload_opnum[r],
  						      reload_when_needed[r],
  						      reload_mode[r]);
! 			      reload_reg_rtx[r] = last_reg;
  			      reload_inherited[r] = 1;
  			      reload_inheritance_insn[r]
  				= reg_reloaded_insn[i];
*************** choose_reload_regs (insn, avoid_return_r
*** 5862,5882 ****
  	      /* If we found a spill reg, reject it unless it is free
  		 and of the desired class.  */
  	      if (equiv != 0
! 		  && ((spill_reg_order[regno] >= 0
! 		       && ! (reload_reg_free_before_p (regno, reload_opnum[r],
! 						       reload_when_needed[r], 1)
! 			     || reload_reg_free_for_value_p (regno,
! 							     reload_opnum[r],
! 							     reload_when_needed[r],
! 							     reload_in[r],
! 							     reload_out[r], r)))
  		      || ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
  					      regno)))
  		equiv = 0;
  
- 	      if (equiv != 0 && TEST_HARD_REG_BIT (reload_reg_used_at_all, regno))
- 		equiv = 0;
- 
  	      if (equiv != 0 && ! HARD_REGNO_MODE_OK (regno, reload_mode[r]))
  		equiv = 0;
  
--- 6112,6126 ----
  	      /* If we found a spill reg, reject it unless it is free
  		 and of the desired class.  */
  	      if (equiv != 0
! 		  && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
! 		       && ! reload_reg_free_for_value_p (regno, reload_opnum[r],
! 							 reload_when_needed[r],
! 							 reload_in[r],
! 							 reload_out[r], r))
  		      || ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
  					      regno)))
  		equiv = 0;
  
  	      if (equiv != 0 && ! HARD_REGNO_MODE_OK (regno, reload_mode[r]))
  		equiv = 0;
  
*************** choose_reload_regs (insn, avoid_return_r
*** 6061,6135 ****
  
    /* If we thought we could inherit a reload, because it seemed that
       nothing else wanted the same reload register earlier in the insn,
!      verify that assumption, now that all reloads have been assigned.  */
  
!   for (j = 0; j < n_reloads; j++)
      {
!       register int r = reload_order[j];
! 
!       if (reload_inherited[r] && reload_reg_rtx[r] != 0
! 	  && ! (reload_reg_free_before_p (true_regnum (reload_reg_rtx[r]),
! 					  reload_opnum[r],
! 					  reload_when_needed[r], 0)
! 		|| reload_reg_free_for_value_p (true_regnum (reload_reg_rtx[r]),
! 						reload_opnum[r],
! 						reload_when_needed[r],
! 						reload_in[r],
! 						reload_out[r], r)))
! 	reload_inherited[r] = 0;
!       /* If we can inherit a RELOAD_FOR_INPUT, then we do not need its related
! 	 RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS reloads.
! 	 ??? This could be extended to other reload types, but these are
!          more tricky to handle:
! 	 RELOAD_FOR_OTHER_ADDRESS reloads might have been merged, so we
! 	 can't eliminate them without a check that *all* references are
! 	 now unused due to inheritance.
! 	 While RELOAD_FOR_INPADDR_ADDRESS and RELOAD_FOR_OUTADDR_ADDRESS are
! 	 not merged, we can't be sure that we have eliminated the use of
! 	 that particular reload if we have seen just one
! 	 RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_OUTPUT_ADDRESS being inherited,
! 	 since there might be multiple of the latter two reloads for a single
! 	 operand.
! 	 RELOAD_FOR_OPADDR_ADDR reloads for different operands are not
! 	 merged, but might share the same register by courtesy of
! 	 reload_reg_free_for_value_p.  reload_reg_used_in_op_addr_reload
! 	 does not differentiate by opnum, thus calling clear_reload_reg_in_use
! 	 for one of these reloads would mark the register as free even though
! 	 another RELOAD_FOR_OPADDR_ADDR reload might still use it.  */
!       else if (reload_inherited[r] && reload_when_needed[r] == RELOAD_FOR_INPUT)
! 	{
! 	  for (i = 0; i < n_reloads; i++)
! 	    {
! 	      if ((reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
! 		   || reload_when_needed[i] == RELOAD_FOR_INPADDR_ADDRESS)
! 		  && reload_opnum[i] == reload_opnum[r]
! 		  && reload_in[i] && reload_reg_rtx[i])
! 		{
! 		  int regno = true_regnum (reload_reg_rtx[i]);
  
! 		  reload_in[i] = 0;
! 		  if (spill_reg_order[regno] >= 0)
! 		    clear_reload_reg_in_use (regno, reload_opnum[i],
! 					     reload_when_needed[i],
! 					     reload_mode[i]);
! 		  reload_reg_rtx[i] = 0;
! 		  reload_spill_index[i] = -1;
! 		  remove_replacements (i);
! 		}
  	    }
! 	}
! 
!       /* If we found a better place to reload from,
! 	 validate it in the same fashion, if it is a reload reg.  */
!       if (reload_override_in[r]
! 	  && (GET_CODE (reload_override_in[r]) == REG
! 	      || GET_CODE (reload_override_in[r]) == SUBREG))
! 	{
! 	  int regno = true_regnum (reload_override_in[r]);
! 	  if (spill_reg_order[regno] >= 0
! 	      && ! reload_reg_free_before_p (regno, reload_opnum[r],
! 					     reload_when_needed[r], 1))
! 	    reload_override_in[r] = 0;
  	}
      }
  
--- 6305,6361 ----
  
    /* If we thought we could inherit a reload, because it seemed that
       nothing else wanted the same reload register earlier in the insn,
!      verify that assumption, now that all reloads have been assigned.
!      Likewise for reloads where reload_override_in has been set.  */
  
!   /* If doing expensive optimizations, do one preliminary pass that doesn't
!      cancel any inheritance, but removes reloads that have been needed only
!      for reloads that we know can be inherited.  */
!   for (pass = flag_expensive_optimizations; pass >= 0; pass--)
      {
!       for (j = 0; j < n_reloads; j++)
! 	{
! 	  register int r = reload_order[j];
! 	  rtx check_reg;
  
! 	  if (reload_inherited[r] && reload_reg_rtx[r])
! 	    check_reg = reload_reg_rtx[r];
! 	  else if (reload_override_in[r]
! 		   && (GET_CODE (reload_override_in[r]) == REG
! 	    		     || GET_CODE (reload_override_in[r]) == SUBREG))
! 	    check_reg = reload_override_in[r];
! 	  else
! 	    continue;
! 	  if (! (reload_reg_free_before_p (true_regnum (check_reg),
! 	    			       reload_opnum[r], reload_when_needed[r],
! 	    			       ! reload_inherited[r])
! 		 || reload_reg_free_for_value_p (true_regnum (check_reg),
! 	    				     reload_opnum[r],
! 	    				     reload_when_needed[r],
! 	    				     reload_in[r],
! 	    				     reload_out[r], r)))
! 	    {
! 	      if (pass)
! 		continue;
! 	      reload_inherited[r] = 0;
! 	      reload_override_in[r] = 0;
  	    }
! 	  /* If we can inherit a RELOAD_FOR_INPUT, or can use a
! 	     reload_override_in, then we do not need its related
! 	     RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS reloads;
! 	     likewise for other reload types.
! 	     We handle this by removing a reload when its only replacement
! 	     is mentioned in reload_in of the reload we are going to inherit.
! 	     A special case are auto_inc expressions; even if the input is
! 	     inherited, we still need the address for the output.  We can
! 	     recognize them because they have RELOAD_OUT set but not
! 	     RELOAD_OUT_REG.
! 	     If we suceeded removing some reload and we are doing a preliminary
! 	     pass just to remove such reloads, make another pass, since the
! 	     removal of one reload might allow us to inherit another one.  */
! 	  else if ((! reload_out[r] || reload_out_reg[r])
! 		   && remove_address_replacements (reload_in[r]) && pass)
! 	    pass = 2;
  	}
      }
  
*************** choose_reload_regs (insn, avoid_return_r
*** 6166,6175 ****
        /* I is nonneg if this reload uses a register.
  	 If reload_reg_rtx[r] is 0, this is an optional reload
  	 that we opted to ignore.  */
!       if (reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG
  	  && reload_reg_rtx[r] != 0)
  	{
! 	  register int nregno = REGNO (reload_out[r]);
  	  int nr = 1;
  
  	  if (nregno < FIRST_PSEUDO_REGISTER)
--- 6392,6401 ----
        /* I is nonneg if this reload uses a register.
  	 If reload_reg_rtx[r] is 0, this is an optional reload
  	 that we opted to ignore.  */
!       if (reload_out_reg[r] != 0 && GET_CODE (reload_out_reg[r]) == REG
  	  && reload_reg_rtx[r] != 0)
  	{
! 	  register int nregno = REGNO (reload_out_reg[r]);
  	  int nr = 1;
  
  	  if (nregno < FIRST_PSEUDO_REGISTER)
*************** choose_reload_regs (insn, avoid_return_r
*** 6192,6197 ****
--- 6418,6441 ----
  	}
      }
  }
+ 
+ /* Deallocate the reload register for reload R.  This is called from
+    remove_address_replacements.  */
+ void
+ deallocate_reload_reg (r)
+      int r;
+ {
+   int regno;
+ 
+   if (! reload_reg_rtx[r])
+     return;
+   regno = true_regnum (reload_reg_rtx[r]);
+   reload_reg_rtx[r] = 0;
+   if (spill_reg_order[regno] >= 0)
+     clear_reload_reg_in_use (regno, reload_opnum[r], reload_when_needed[r],
+ 			     reload_mode[r]);
+   reload_spill_index[r] = -1;
+ }
  
  /* If SMALL_REGISTER_CLASSES is non-zero, we may not have merged two
     reloads of the same item for fear that we might not have enough reload
*************** emit_reload_insns (insn, bb)
*** 6350,6361 ****
        rtx oldequiv_reg = 0;
        rtx this_reload_insn = 0;
        int expect_occurrences = 1;
  
!       if (reload_spill_index[j] >= 0)
! 	new_spill_reg_store[reload_spill_index[j]] = 0;
  
!       old = reload_in[j];
!       if (old != 0 && ! reload_inherited[j]
  	  && ! rtx_equal_p (reload_reg_rtx[j], old)
  	  && reload_reg_rtx[j] != 0)
  	{
--- 6594,6611 ----
        rtx oldequiv_reg = 0;
        rtx this_reload_insn = 0;
        int expect_occurrences = 1;
+ 
+       if (reload_reg_rtx[j]
+ 	  && REGNO (reload_reg_rtx[j]) < FIRST_PSEUDO_REGISTER)
+ 	new_spill_reg_store[REGNO (reload_reg_rtx[j])] = 0;
  
!       old = (reload_in[j] && GET_CODE (reload_in[j]) == MEM
! 	     ? reload_in_reg[j] : reload_in[j]);
  
!       if (old != 0
! 	  /* AUTO_INC reloads need to be handled even if inherited.  We got an
! 	     AUTO_INC reload if reload_out is set but reload_out_reg isn't.  */
! 	  && (! reload_inherited[j] || (reload_out[j] && ! reload_out_reg[j]))
  	  && ! rtx_equal_p (reload_reg_rtx[j], old)
  	  && reload_reg_rtx[j] != 0)
  	{
*************** emit_reload_insns (insn, bb)
*** 6484,6489 ****
--- 6734,6750 ----
  		oldequiv = 0;
  	    }
  
+ 	  /* delete_output_reload is only invoked properly if old contains
+ 	     the original pseudo register.  Since this is replaced with a
+ 	     hard reg when RELOAD_OVERRIDE_IN is set, see if we can
+ 	     find the pseudo in RELOAD_IN_REG.  */
+ 	  if (oldequiv == 0
+ 	      && reload_override_in[j]
+ 	      && GET_CODE (reload_in_reg[j]) == REG)
+ 	    {
+ 	      oldequiv = old;
+ 	      old = reload_in_reg[j];
+ 	    }
  	  if (oldequiv == 0)
  	    oldequiv = old;
  	  else if (GET_CODE (oldequiv) == REG)
*************** emit_reload_insns (insn, bb)
*** 6498,6508 ****
  	  if (optimize && GET_CODE (oldequiv) == REG
  	      && REGNO (oldequiv) < FIRST_PSEUDO_REGISTER
  	      && spill_reg_store[REGNO (oldequiv)]
! 	      && GET_CODE (old) == REG && dead_or_set_p (insn, old)
! 	      /* This is unsafe if operand occurs more than once in current
! 		 insn.  Perhaps some occurrences weren't reloaded.  */
! 	      && count_occurrences (PATTERN (insn), old) == 1)
! 	    delete_output_reload (insn, j, spill_reg_store[REGNO (oldequiv)]);
  
  	  /* Encapsulate both RELOADREG and OLDEQUIV into that mode,
  	     then load RELOADREG from OLDEQUIV.  Note that we cannot use
--- 6759,6769 ----
  	  if (optimize && GET_CODE (oldequiv) == REG
  	      && REGNO (oldequiv) < FIRST_PSEUDO_REGISTER
  	      && spill_reg_store[REGNO (oldequiv)]
! 	      && GET_CODE (old) == REG
! 	      && (dead_or_set_p (insn, spill_reg_stored_to[REGNO (oldequiv)])
! 		  || rtx_equal_p (spill_reg_stored_to[REGNO (oldequiv)],
! 				  reload_out_reg[j])))
! 	    delete_output_reload (insn, j, REGNO (oldequiv));
  
  	  /* Encapsulate both RELOADREG and OLDEQUIV into that mode,
  	     then load RELOADREG from OLDEQUIV.  Note that we cannot use
*************** emit_reload_insns (insn, bb)
*** 6556,6575 ****
  	  special = 0;
  
  	  /* Auto-increment addresses must be reloaded in a special way.  */
! 	  if (GET_CODE (oldequiv) == POST_INC
! 	      || GET_CODE (oldequiv) == POST_DEC
! 	      || GET_CODE (oldequiv) == PRE_INC
! 	      || GET_CODE (oldequiv) == PRE_DEC)
  	    {
  	      /* We are not going to bother supporting the case where a
  		 incremented register can't be copied directly from
  		 OLDEQUIV since this seems highly unlikely.  */
  	      if (reload_secondary_in_reload[j] >= 0)
  		abort ();
  	      /* Prevent normal processing of this reload.  */
  	      special = 1;
  	      /* Output a special code sequence for this case.  */
! 	      inc_for_reload (reloadreg, oldequiv, reload_inc[j]);
  	    }
  
  	  /* If we are reloading a pseudo-register that was set by the previous
--- 6817,6851 ----
  	  special = 0;
  
  	  /* Auto-increment addresses must be reloaded in a special way.  */
! 	  if (reload_out[j] && ! reload_out_reg[j])
  	    {
  	      /* We are not going to bother supporting the case where a
  		 incremented register can't be copied directly from
  		 OLDEQUIV since this seems highly unlikely.  */
  	      if (reload_secondary_in_reload[j] >= 0)
  		abort ();
+ 
+ 	      if (reload_inherited[j])
+ 		oldequiv = reloadreg;
+ 
+ 	      old = XEXP (reload_in_reg[j], 0);
+ 
+ 	      if (optimize && GET_CODE (oldequiv) == REG
+ 		  && REGNO (oldequiv) < FIRST_PSEUDO_REGISTER
+ 		  && spill_reg_store[REGNO (oldequiv)]
+ 		  && GET_CODE (old) == REG
+ 		  && (dead_or_set_p (insn,
+ 				     spill_reg_stored_to[REGNO (oldequiv)])
+ 		      || rtx_equal_p (spill_reg_stored_to[REGNO (oldequiv)],
+ 				      old)))
+ 		delete_output_reload (insn, j, REGNO (oldequiv));
+ 
  	      /* Prevent normal processing of this reload.  */
  	      special = 1;
  	      /* Output a special code sequence for this case.  */
! 	      new_spill_reg_store[REGNO (reloadreg)]
! 		= inc_for_reload (reloadreg, oldequiv, reload_out[j],
! 				  reload_inc[j]);
  	    }
  
  	  /* If we are reloading a pseudo-register that was set by the previous
*************** emit_reload_insns (insn, bb)
*** 6645,6659 ****
  		  /* If OLDEQUIV is a pseudo with a MEM, get the real MEM
  		     and similarly for OLD.
  		     See comments in get_secondary_reload in reload.c.  */
  		  if (GET_CODE (oldequiv) == REG
  		      && REGNO (oldequiv) >= FIRST_PSEUDO_REGISTER
! 		      && reg_equiv_mem[REGNO (oldequiv)] != 0)
! 		    real_oldequiv = reg_equiv_mem[REGNO (oldequiv)];
  
  		  if (GET_CODE (old) == REG
  		      && REGNO (old) >= FIRST_PSEUDO_REGISTER
! 		      && reg_equiv_mem[REGNO (old)] != 0)
! 		    real_old = reg_equiv_mem[REGNO (old)];
  
  		  second_reload_reg = reload_reg_rtx[secondary_reload];
  		  icode = reload_secondary_in_icode[j];
--- 6921,6951 ----
  		  /* If OLDEQUIV is a pseudo with a MEM, get the real MEM
  		     and similarly for OLD.
  		     See comments in get_secondary_reload in reload.c.  */
+ 		  /* If it is a pseudo that cannot be replaced with its
+ 		     equivalent MEM, we must fall back to reload_in, which
+ 		     will have all the necessary substitutions registered.  */
+ 				
  		  if (GET_CODE (oldequiv) == REG
  		      && REGNO (oldequiv) >= FIRST_PSEUDO_REGISTER
! 		      && reg_equiv_memory_loc[REGNO (oldequiv)] != 0)
! 		    {
! 		      if (reg_equiv_address[REGNO (oldequiv)]
! 			  || num_not_at_initial_offset)
! 			real_oldequiv = reload_in[j];
! 		      else
! 			real_oldequiv = reg_equiv_mem[REGNO (oldequiv)];
! 		    }
  
  		  if (GET_CODE (old) == REG
  		      && REGNO (old) >= FIRST_PSEUDO_REGISTER
! 		      && reg_equiv_memory_loc[REGNO (old)] != 0)
! 		    {
! 		      if (reg_equiv_address[REGNO (old)]
! 			  || num_not_at_initial_offset)
! 			real_old = reload_in[j];
! 		      else
! 			real_old = reg_equiv_mem[REGNO (old)];
! 		    }
  
  		  second_reload_reg = reload_reg_rtx[secondary_reload];
  		  icode = reload_secondary_in_icode[j];
*************** emit_reload_insns (insn, bb)
*** 6738,6744 ****
  					   third_reload_reg)));
  			    }
  			  else
! 			    gen_reload (second_reload_reg, oldequiv,
  					reload_opnum[j],
  					reload_when_needed[j]);
  
--- 7030,7036 ----
  					   third_reload_reg)));
  			    }
  			  else
! 			    gen_reload (second_reload_reg, real_oldequiv,
  					reload_opnum[j],
  					reload_when_needed[j]);
  
*************** emit_reload_insns (insn, bb)
*** 6749,6756 ****
  #endif
  
  	      if (! special && ! rtx_equal_p (reloadreg, oldequiv))
! 		gen_reload (reloadreg, oldequiv, reload_opnum[j],
! 			    reload_when_needed[j]);
  
  	    }
  
--- 7041,7062 ----
  #endif
  
  	      if (! special && ! rtx_equal_p (reloadreg, oldequiv))
! 		{
! 		  rtx real_oldequiv = oldequiv;
! 
! 		  if ((GET_CODE (oldequiv) == REG
! 		       && REGNO (oldequiv) >= FIRST_PSEUDO_REGISTER
! 		       && reg_equiv_memory_loc[REGNO (oldequiv)] != 0)
! 		      || (GET_CODE (oldequiv) == SUBREG
! 			  && GET_CODE (SUBREG_REG (oldequiv)) == REG
! 			  && (REGNO (SUBREG_REG (oldequiv))
! 			      >= FIRST_PSEUDO_REGISTER)
! 			  && (reg_equiv_memory_loc
! 			      [REGNO (SUBREG_REG (oldequiv))] != 0)))
! 		    real_oldequiv = reload_in[j];
! 		  gen_reload (reloadreg, real_oldequiv, reload_opnum[j],
! 			      reload_when_needed[j]);
! 		}
  
  	    }
  
*************** emit_reload_insns (insn, bb)
*** 6758,6763 ****
--- 7064,7074 ----
  	  /* End this sequence.  */
  	  *where = get_insns ();
  	  end_sequence ();
+ 
+ 	  /* Update reload_override_in so that delete_address_reloads_1
+ 	     can see the actual register usage.  */
+ 	  if (oldequiv_reg)
+ 	    reload_override_in[j] = oldequiv;
  	}
  
        /* When inheriting a wider reload, we have a MEM in reload_in[j],
*************** emit_reload_insns (insn, bb)
*** 6765,6770 ****
--- 7076,7082 ----
  	 (mem:HI (plus:SI (reg:SI 14 fp) (const_int 10)))  */
        if (optimize && reload_inherited[j] && reload_in[j]
  	  && GET_CODE (reload_in[j]) == MEM
+ 	  && GET_CODE (reload_in_reg[j]) == MEM
  	  && reload_spill_index[j] >= 0
  	  && TEST_HARD_REG_BIT (reg_reloaded_valid, reload_spill_index[j]))
  	{
*************** emit_reload_insns (insn, bb)
*** 6778,6804 ****
  	 output-reload, see if we can prove there was
  	 actually no need to store the old value in it.  */
  
!       if (optimize && reload_inherited[j] && reload_spill_index[j] >= 0
! 	  && reload_in[j] != 0
! 	  && GET_CODE (reload_in[j]) == REG
  #if 0
  	  /* There doesn't seem to be any reason to restrict this to pseudos
  	     and doing so loses in the case where we are copying from a
  	     register of the wrong class.  */
! 	  && REGNO (reload_in[j]) >= FIRST_PSEUDO_REGISTER
  #endif
! 	  && spill_reg_store[reload_spill_index[j]] != 0
! 	  /* This is unsafe if some other reload uses the same reg first.  */
! 	  && reload_reg_free_before_p (reload_spill_index[j],
! 				       reload_opnum[j], reload_when_needed[j],
! 				       0)
! 	  && dead_or_set_p (insn, reload_in[j])
! 	  /* This is unsafe if operand occurs more than once in current
! 	     insn.  Perhaps some occurrences weren't reloaded.  */
! 	  && (count_occurrences (PATTERN (insn), reload_in[j])
! 	      == expect_occurrences))
! 	delete_output_reload (insn, j,
! 			      spill_reg_store[reload_spill_index[j]]);
  
        /* Input-reloading is done.  Now do output-reloading,
  	 storing the value from the reload-register after the main insn
--- 7090,7115 ----
  	 output-reload, see if we can prove there was
  	 actually no need to store the old value in it.  */
  
!       if (optimize
! 	  && (reload_inherited[j] || reload_override_in[j])
! 	  && reload_reg_rtx[j]
! 	  && GET_CODE (reload_reg_rtx[j]) == REG
! 	  && spill_reg_store[REGNO (reload_reg_rtx[j])] != 0
  #if 0
  	  /* There doesn't seem to be any reason to restrict this to pseudos
  	     and doing so loses in the case where we are copying from a
  	     register of the wrong class.  */
! 	  && REGNO (spill_reg_stored_to[REGNO (reload_reg_rtx[j])])
! 	     >= FIRST_PSEUDO_REGISTER
  #endif
! 	     /* The insn might have already some references to stackslots
! 		replaced by MEMs, while reload_out_reg still names the
! 		original pseudo.  */
! 	  && (dead_or_set_p (insn,
! 			     spill_reg_stored_to[REGNO (reload_reg_rtx[j])])
! 	      || rtx_equal_p (spill_reg_stored_to[REGNO (reload_reg_rtx[j])],
! 			      reload_out_reg[j])))
! 	delete_output_reload (insn, j, REGNO (reload_reg_rtx[j]));
  
        /* Input-reloading is done.  Now do output-reloading,
  	 storing the value from the reload-register after the main insn
*************** emit_reload_insns (insn, bb)
*** 6806,6812 ****
  
  	 ??? At some point we need to support handling output reloads of
  	 JUMP_INSNs or insns that set cc0.  */
!       old = reload_out[j];
        if (old != 0
  	  && reload_reg_rtx[j] != old
  	  && reload_reg_rtx[j] != 0)
--- 7117,7149 ----
  
  	 ??? At some point we need to support handling output reloads of
  	 JUMP_INSNs or insns that set cc0.  */
! 
!       /* If this is an output reload that stores something that is
! 	 not loaded in this same reload, see if we can eliminate a previous
! 	 store.  */
!       {
! 	rtx pseudo = reload_out_reg[j];
! 	  
! 	if (pseudo
! 	    && GET_CODE (pseudo) == REG
! 	    && ! rtx_equal_p (reload_in_reg[j], pseudo)
! 	    && REGNO (pseudo) >= FIRST_PSEUDO_REGISTER
! 	    && reg_last_reload_reg[REGNO (pseudo)])
! 	  {
! 	    int pseudo_no = REGNO (pseudo);
! 	    int last_regno = REGNO (reg_last_reload_reg[pseudo_no]);
! 
! 	    /* We don't need to test full validity of last_regno for
! 	       inherit here; we only want to know if the store actually
! 	       matches the pseudo.  */
! 	    if (reg_reloaded_contents[last_regno] == pseudo_no
! 		&& spill_reg_store[last_regno]
! 		&& rtx_equal_p (pseudo, spill_reg_stored_to[last_regno]))
! 	      delete_output_reload (insn, j, last_regno);
! 	  }
!       }
! 
!       old = reload_out_reg[j];
        if (old != 0
  	  && reload_reg_rtx[j] != old
  	  && reload_reg_rtx[j] != 0)
*************** emit_reload_insns (insn, bb)
*** 6862,6867 ****
--- 7199,7206 ----
  	  else
  	    push_to_sequence (output_reload_insns[reload_opnum[j]]);
  
+ 	  old = reload_out[j];
+ 
  	  /* Determine the mode to reload in.
  	     See comments above (for input reloading).  */
  
*************** emit_reload_insns (insn, bb)
*** 6992,7012 ****
  
  		if (reg_mentioned_p (reload_reg_rtx[j], pat))
  		  {
  		    if (reload_spill_index[j] < 0
! 			&& GET_CODE (pat) == SET
! 			&& SET_SRC (pat) == reload_reg_rtx[j])
  		      {
! 			int src = REGNO (SET_SRC (pat));
  
  			reload_spill_index[j] = src;
  			SET_HARD_REG_BIT (reg_is_output_reload, src);
  			if (find_regno_note (insn, REG_DEAD, src))
  			  SET_HARD_REG_BIT (reg_reloaded_died, src);
  		      }
! 		    if (reload_spill_index[j] >= 0)
  		      {
  			int s = reload_secondary_out_reload[j];
! 			rtx set = single_set (p);
  			/* If this reload copies only to the secondary reload
  			   register, the secondary reload does the actual
  			   store.  */
--- 7331,7352 ----
  
  		if (reg_mentioned_p (reload_reg_rtx[j], pat))
  		  {
+ 		    rtx set = single_set (insn);
  		    if (reload_spill_index[j] < 0
! 			&& set
! 			&& SET_SRC (set) == reload_reg_rtx[j])
  		      {
! 			int src = REGNO (SET_SRC (set));
  
  			reload_spill_index[j] = src;
  			SET_HARD_REG_BIT (reg_is_output_reload, src);
  			if (find_regno_note (insn, REG_DEAD, src))
  			  SET_HARD_REG_BIT (reg_reloaded_died, src);
  		      }
! 		    if (REGNO (reload_reg_rtx[j]) < FIRST_PSEUDO_REGISTER)
  		      {
  			int s = reload_secondary_out_reload[j];
! 			set = single_set (p);
  			/* If this reload copies only to the secondary reload
  			   register, the secondary reload does the actual
  			   store.  */
*************** emit_reload_insns (insn, bb)
*** 7025,7037 ****
  			    rtx s_reg = reload_reg_rtx[s];
  			    rtx next = NEXT_INSN (p);
  			    reload_out[s] = reload_out[j];
  			    set = single_set (next);
  			    if (set && SET_SRC (set) == s_reg
  				&& ! new_spill_reg_store[REGNO (s_reg)])
! 			      new_spill_reg_store[REGNO (s_reg)] = next;
  			  }
  			else
! 			  new_spill_reg_store[reload_spill_index[j]] = p;
  		      }
  		  }
  	      }
--- 7365,7382 ----
  			    rtx s_reg = reload_reg_rtx[s];
  			    rtx next = NEXT_INSN (p);
  			    reload_out[s] = reload_out[j];
+ 			    reload_out_reg[s] = reload_out_reg[j];
  			    set = single_set (next);
  			    if (set && SET_SRC (set) == s_reg
  				&& ! new_spill_reg_store[REGNO (s_reg)])
! 			      {
! 				SET_HARD_REG_BIT (reg_is_output_reload,
! 						  REGNO (s_reg));
! 				new_spill_reg_store[REGNO (s_reg)] = next;
! 			      }
  			  }
  			else
! 			  new_spill_reg_store[REGNO (reload_reg_rtx[j])] = p;
  		      }
  		  }
  	      }
*************** emit_reload_insns (insn, bb)
*** 7148,7161 ****
  		CLEAR_HARD_REG_BIT (reg_reloaded_valid, i + k);
  
  	      /* Maybe the spill reg contains a copy of reload_out.  */
! 	      if (reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
  		{
! 		  register int nregno = REGNO (reload_out[r]);
  		  int nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
  			     : HARD_REGNO_NREGS (nregno,
  						 GET_MODE (reload_reg_rtx[r])));
  
  		  spill_reg_store[i] = new_spill_reg_store[i];
  		  reg_last_reload_reg[nregno] = reload_reg_rtx[r];
  
  		  /* If NREGNO is a hard register, it may occupy more than
--- 7493,7517 ----
  		CLEAR_HARD_REG_BIT (reg_reloaded_valid, i + k);
  
  	      /* Maybe the spill reg contains a copy of reload_out.  */
! 	      if (reload_out[r] != 0
! 		  && (GET_CODE (reload_out[r]) == REG
! #ifdef AUTO_INC_DEC
! 		      || ! reload_out_reg[r]
! #endif
! 		      || GET_CODE (reload_out_reg[r]) == REG))
  		{
! 		  rtx out = (GET_CODE (reload_out[r]) == REG
! 			     ? reload_out[r]
! 			     : reload_out_reg[r]
! 			     ? reload_out_reg[r]
! /* AUTO_INC */		     : XEXP (reload_in_reg[r], 0));
! 		  register int nregno = REGNO (out);
  		  int nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
  			     : HARD_REGNO_NREGS (nregno,
  						 GET_MODE (reload_reg_rtx[r])));
  
  		  spill_reg_store[i] = new_spill_reg_store[i];
+ 		  spill_reg_stored_to[i] = out;
  		  reg_last_reload_reg[nregno] = reload_reg_rtx[r];
  
  		  /* If NREGNO is a hard register, it may occupy more than
*************** emit_reload_insns (insn, bb)
*** 7188,7208 ****
  	      /* Maybe the spill reg contains a copy of reload_in.  Only do
  		 something if there will not be an output reload for
  		 the register being reloaded.  */
! 	      else if (reload_out[r] == 0
  		       && reload_in[r] != 0
- 		       && spill_reg_order[i] >= 0
  		       && ((GET_CODE (reload_in[r]) == REG
  			    && ! reg_has_output_reload[REGNO (reload_in[r])])
  			   || (GET_CODE (reload_in_reg[r]) == REG
! 			       && ! reg_has_output_reload[REGNO (reload_in_reg[r])])))
  		{
  		  register int nregno;
  		  int nnr;
  
! 		  if (GET_CODE (reload_in[r]) == REG)
  		    nregno = REGNO (reload_in[r]);
! 		  else
  		    nregno = REGNO (reload_in_reg[r]);
  
  		  nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
  			 : HARD_REGNO_NREGS (nregno,
--- 7544,7568 ----
  	      /* Maybe the spill reg contains a copy of reload_in.  Only do
  		 something if there will not be an output reload for
  		 the register being reloaded.  */
! 	      else if (reload_out_reg[r] == 0
  		       && reload_in[r] != 0
  		       && ((GET_CODE (reload_in[r]) == REG
+ 			    && REGNO (reload_in[r]) >= FIRST_PSEUDO_REGISTER
  			    && ! reg_has_output_reload[REGNO (reload_in[r])])
  			   || (GET_CODE (reload_in_reg[r]) == REG
! 			       && ! reg_has_output_reload[REGNO (reload_in_reg[r])]))
! 		       && ! reg_set_p (reload_reg_rtx[r], PATTERN (insn)))
  		{
  		  register int nregno;
  		  int nnr;
  
! 		  if (GET_CODE (reload_in[r]) == REG
! 		      && REGNO (reload_in[r]) >= FIRST_PSEUDO_REGISTER)
  		    nregno = REGNO (reload_in[r]);
! 		  else if (GET_CODE (reload_in_reg[r]) == REG)
  		    nregno = REGNO (reload_in_reg[r]);
+ 		  else
+ 		    nregno = REGNO (XEXP (reload_in_reg[r], 0));
  
  		  nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
  			 : HARD_REGNO_NREGS (nregno,
*************** emit_reload_insns (insn, bb)
*** 7219,7226 ****
  			   : 0);
  
  		  /* Unless we inherited this reload, show we haven't
! 		     recently done a store.  */
! 		  if (! reload_inherited[r])
  		    spill_reg_store[i] = 0;
  
  		  for (k = 0; k < nr; k++)
--- 7579,7589 ----
  			   : 0);
  
  		  /* Unless we inherited this reload, show we haven't
! 		     recently done a store.
! 		     Previous stores of inherited auto_inc expressions
! 		     also have to be discarded.  */
! 		  if (! reload_inherited[r]
! 		      || (reload_out[r] && ! reload_out_reg[r]))
  		    spill_reg_store[i] = 0;
  
  		  for (k = 0; k < nr; k++)
*************** emit_reload_insns (insn, bb)
*** 7256,7266 ****
  	 that invalidates any previous reloaded copy of it.
  	 But forget_old_reloads_1 won't get to see it, because
  	 it thinks only about the original insn.  So invalidate it here.  */
!       if (i < 0 && reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
! 	{
! 	  register int nregno = REGNO (reload_out[r]);
  	  if (nregno >= FIRST_PSEUDO_REGISTER)
! 	    reg_last_reload_reg[nregno] = 0;
  	  else
  	    {
  	      int num_regs = HARD_REGNO_NREGS (nregno,GET_MODE (reload_out[r]));
--- 7619,7694 ----
  	 that invalidates any previous reloaded copy of it.
  	 But forget_old_reloads_1 won't get to see it, because
  	 it thinks only about the original insn.  So invalidate it here.  */
!       if (i < 0 && reload_out[r] != 0
! 	  && (GET_CODE (reload_out[r]) == REG
! 	      || (GET_CODE (reload_out[r]) == MEM
! 		  && GET_CODE (reload_out_reg[r]) == REG)))
! 	{
! 	  rtx out = (GET_CODE (reload_out[r]) == REG
! 		     ? reload_out[r] : reload_out_reg[r]);
! 	  register int nregno = REGNO (out);
  	  if (nregno >= FIRST_PSEUDO_REGISTER)
! 	    {
! 	      rtx src_reg, store_insn;
! 
! 	      reg_last_reload_reg[nregno] = 0;
! 
! 	      /* If we can find a hard register that is stored, record
! 		 the storing insn so that we may delete this insn with
! 		 delete_output_reload.  */
! 	      src_reg = reload_reg_rtx[r];
! 
! 	      /* If this is an optional reload, try to find the source reg
! 		 from an input reload.  */
! 	      if (! src_reg)
! 		{
! 		  rtx set = single_set (insn);
! 		  if (SET_DEST (set) == reload_out[r])
! 		    {
! 		      int k;
! 
! 		      src_reg = SET_SRC (set);
! 		      store_insn = insn;
! 		      for (k = 0; k < n_reloads; k++)
! 			{
! 			  if (reload_in[k] == src_reg)
! 			    {
! 			      src_reg = reload_reg_rtx[k];
! 			      break;
! 			    }
! 			}
! 		    }
! 		}
! 	      else
! 		store_insn = new_spill_reg_store[REGNO (src_reg)];
! 	      if (src_reg && GET_CODE (src_reg) == REG
! 		  && REGNO (src_reg) < FIRST_PSEUDO_REGISTER)
! 		{
! 		  int src_regno = REGNO (src_reg);
! 		  int nr = HARD_REGNO_NREGS (src_regno, reload_mode[r]);
! 		  /* The place where to find a death note varies with
! 		     PRESERVE_DEATH_INFO_REGNO_P .  The condition is not
! 		     necessarily checked exactly in the code that moves
! 		     notes, so just check both locations.  */
! 		  rtx note = find_regno_note (insn, REG_DEAD, src_regno);
! 		  if (! note)
! 		    note = find_regno_note (store_insn, REG_DEAD, src_regno);
! 		  while (nr-- > 0)
! 		    {
! 		      spill_reg_store[src_regno + nr] = store_insn;
! 		      spill_reg_stored_to[src_regno + nr] = out;
! 		      reg_reloaded_contents[src_regno + nr] = nregno;
! 		      reg_reloaded_insn[src_regno + nr] = store_insn;
! 		      SET_HARD_REG_BIT (reg_reloaded_valid, src_regno + nr);
! 		      SET_HARD_REG_BIT (reg_is_output_reload, src_regno + nr);
! 		      if (note)
! 			SET_HARD_REG_BIT (reg_reloaded_died, src_regno);
! 		      else
! 			CLEAR_HARD_REG_BIT (reg_reloaded_died, src_regno);
! 		    }
! 		  reg_last_reload_reg[nregno] = src_reg;
! 		}
! 	    }
  	  else
  	    {
  	      int num_regs = HARD_REGNO_NREGS (nregno,GET_MODE (reload_out[r]));
*************** gen_reload (out, in, opnum, type)
*** 7486,7507 ****
     First we double-check.
  
     INSN is the insn now being processed.
!    OUTPUT_RELOAD_INSN is the insn of the output reload.
!    J is the reload-number for this insn.  */
  
  static void
! delete_output_reload (insn, j, output_reload_insn)
       rtx insn;
       int j;
!      rtx output_reload_insn;
  {
    register rtx i1;
! 
    /* Get the raw pseudo-register referred to.  */
  
-   rtx reg = reload_in[j];
    while (GET_CODE (reg) == SUBREG)
      reg = SUBREG_REG (reg);
  
    /* If the pseudo-reg we are reloading is no longer referenced
       anywhere between the store into it and here,
--- 7914,7979 ----
     First we double-check.
  
     INSN is the insn now being processed.
!    LAST_RELOAD_REG is the hard register number for which we want to delete
!    the last output reload.
!    J is the reload-number that originally used REG.  The caller has made
!    certain that reload J doesn't use REG any longer for input.  */
  
  static void
! delete_output_reload (insn, j, last_reload_reg)
       rtx insn;
       int j;
!      int last_reload_reg;
  {
+   rtx output_reload_insn = spill_reg_store[last_reload_reg];
+   rtx reg = spill_reg_stored_to[last_reload_reg];
+   int k;
+   int n_occurrences;
+   int n_inherited = 0;
    register rtx i1;
!   rtx substed;
!   
    /* Get the raw pseudo-register referred to.  */
  
    while (GET_CODE (reg) == SUBREG)
      reg = SUBREG_REG (reg);
+   substed = reg_equiv_memory_loc[REGNO (reg)];
+ 
+   /* This is unsafe if the operand occurs more often in the current
+      insn than it is inherited.  */
+   for (k = n_reloads - 1; k >= 0; k--)
+     {
+       rtx reg2 = reload_in[k];
+       if (! reg2)
+ 	continue;
+       if (GET_CODE (reg2) == MEM || reload_override_in[k])
+ 	reg2 = reload_in_reg[k];
+ #ifdef AUTO_INC_DEC
+       if (reload_out[k] && ! reload_out_reg[k])
+ 	reg2 = XEXP (reload_in_reg[k], 0);
+ #endif
+       while (GET_CODE (reg2) == SUBREG)
+ 	reg2 = SUBREG_REG (reg2);
+       if (rtx_equal_p (reg2, reg))
+ 	if (reload_inherited[k] || reload_override_in[k] || k == j)
+ 	  {
+ 	    n_inherited++;
+ 	    reg2 = reload_out_reg[k];
+ 	    if (! reg2)
+ 	      continue;
+ 	    while (GET_CODE (reg2) == SUBREG)
+ 	      reg2 = XEXP (reg2, 0);
+ 	    if (rtx_equal_p (reg2, reg))
+ 	      n_inherited++;
+ 	  }
+ 	else
+ 	  return;
+     }
+   n_occurrences = count_occurrences (PATTERN (insn), reg);
+   if (substed)
+     n_occurrences += count_occurrences (PATTERN (insn), substed);
+   if (n_occurrences > n_inherited)
+     return;
  
    /* If the pseudo-reg we are reloading is no longer referenced
       anywhere between the store into it and here,
*************** delete_output_reload (insn, j, output_re
*** 7516,7536 ****
        if ((GET_CODE (i1) == INSN || GET_CODE (i1) == CALL_INSN)
  	  && reg_mentioned_p (reg, PATTERN (i1)))
  	{
! 	  /* If this is just a single USE with an REG_EQUAL note in front
! 	     of INSN, this is no problem, because this mentions just the
! 	     address that we are using here.
! 	     But if there is more than one such USE, the insn might use
! 	     the operand directly, or another reload might do that.
! 	     This is analogous to the count_occurences check in the callers.  */
! 	  int num_occurences = 0;
! 
! 	  while (GET_CODE (i1) == INSN && GET_CODE (PATTERN (i1)) == USE
! 		 && find_reg_note (i1, REG_EQUAL, NULL_RTX))
  	    {
! 	      num_occurences += rtx_equal_p (reg, XEXP (PATTERN (i1), 0)) != 0;
  	      i1 = NEXT_INSN (i1);
  	    }
! 	  if (num_occurences == 1 && i1 == insn)
  	    break;
  	  return;
  	}
--- 7988,8001 ----
        if ((GET_CODE (i1) == INSN || GET_CODE (i1) == CALL_INSN)
  	  && reg_mentioned_p (reg, PATTERN (i1)))
  	{
! 	  /* If this is USE in front of INSN, we only have to check that
! 	     there are no more references than accounted for by inheritance.  */
! 	  while (GET_CODE (i1) == INSN && GET_CODE (PATTERN (i1)) == USE)
  	    {
! 	      n_occurrences += rtx_equal_p (reg, XEXP (PATTERN (i1), 0)) != 0;
  	      i1 = NEXT_INSN (i1);
  	    }
! 	  if (n_occurrences <= n_inherited && i1 == insn)
  	    break;
  	  return;
  	}
*************** delete_output_reload (insn, j, output_re
*** 7573,7579 ****
  	    {
  	      /* Some other ref remains; just delete the output reload we
  		 know to be dead.  */
! 	      delete_insn (output_reload_insn);
  	      return;
  	    }
  	}
--- 8038,8047 ----
  	    {
  	      /* Some other ref remains; just delete the output reload we
  		 know to be dead.  */
! 	      delete_address_reloads (output_reload_insn, insn);
! 	      PUT_CODE (output_reload_insn, NOTE);
! 	      NOTE_SOURCE_FILE (output_reload_insn) = 0;
! 	      NOTE_LINE_NUMBER (output_reload_insn) = NOTE_INSN_DELETED;
  	      return;
  	    }
  	}
*************** delete_output_reload (insn, j, output_re
*** 7585,7590 ****
--- 8053,8059 ----
  
  	  if (set != 0 && SET_DEST (set) == reg)
  	    {
+ 	      delete_address_reloads (i2, insn);
  	      /* This might be a basic block head,
  		 thus don't use delete_insn.  */
  	      PUT_CODE (i2, NOTE);
*************** delete_output_reload (insn, j, output_re
*** 7600,7622 ****
  	 say the pseudo lives in this reload reg.  */
        reg_renumber[REGNO (reg)] = REGNO (reload_reg_rtx[j]);
        alter_reg (REGNO (reg), -1);
      }
-   delete_insn (output_reload_insn);
  
  }
  
  /* Output reload-insns to reload VALUE into RELOADREG.
     VALUE is an autoincrement or autodecrement RTX whose operand
     is a register or memory location;
     so reloading involves incrementing that location.
  
     INC_AMOUNT is the number to increment or decrement by (always positive).
!    This cannot be deduced from VALUE.  */
  
! static void
! inc_for_reload (reloadreg, value, inc_amount)
       rtx reloadreg;
!      rtx value;
       int inc_amount;
  {
    /* REG or MEM to be copied and incremented.  */
--- 8069,8247 ----
  	 say the pseudo lives in this reload reg.  */
        reg_renumber[REGNO (reg)] = REGNO (reload_reg_rtx[j]);
        alter_reg (REGNO (reg), -1);
+     }
+   delete_address_reloads (output_reload_insn, insn);
+   PUT_CODE (output_reload_insn, NOTE);
+   NOTE_SOURCE_FILE (output_reload_insn) = 0;
+   NOTE_LINE_NUMBER (output_reload_insn) = NOTE_INSN_DELETED;
+ 
+ }
+ 
+ /* We are going to delete DEAD_INSN.  Recursively delete loads of
+    reload registers used in DEAD_INSN that are not used till CURRENT_INSN.
+    CURRENT_INSN is being reloaded, so we have to check its reloads too.  */
+ static void
+ delete_address_reloads (dead_insn, current_insn)
+      rtx dead_insn, current_insn;
+ {
+   rtx set = single_set (dead_insn);
+   rtx set2, dst, prev, next;
+   if (set)
+     {
+       rtx dst = SET_DEST (set);
+       if (GET_CODE (dst) == MEM)
+ 	delete_address_reloads_1 (dead_insn, XEXP (dst, 0), current_insn);
+     }
+   /* If we deleted the store from a reloaded post_{in,de}c expression,
+      we can delete the matching adds.  */
+   prev = PREV_INSN (dead_insn);
+   next = NEXT_INSN (dead_insn);
+   if (! prev || ! next)
+     return;
+   set = single_set (next);
+   set2 = single_set (prev);
+   if (! set || ! set2
+       || GET_CODE (SET_SRC (set)) != PLUS || GET_CODE (SET_SRC (set2)) != PLUS
+       || GET_CODE (XEXP (SET_SRC (set), 1)) != CONST_INT
+       || GET_CODE (XEXP (SET_SRC (set2), 1)) != CONST_INT)
+     return;
+   dst = SET_DEST (set);
+   if (! rtx_equal_p (dst, SET_DEST (set2))
+       || ! rtx_equal_p (dst, XEXP (SET_SRC (set), 0))
+       || ! rtx_equal_p (dst, XEXP (SET_SRC (set2), 0))
+       || (INTVAL (XEXP (SET_SRC (set), 1))
+ 	  != - INTVAL (XEXP (SET_SRC (set2), 1))))
+     return;
+   delete_insn (prev);
+   delete_insn (next);
+ }
+ 
+ /* Subfunction of delete_address_reloads: process registers found in X.  */
+ static void
+ delete_address_reloads_1 (dead_insn, x, current_insn)
+      rtx dead_insn, x, current_insn;
+ {
+   rtx prev, set, dst, i2;
+   int i, j;
+   enum rtx_code code = GET_CODE (x);
+ 
+   if (code != REG)
+     {
+       char *fmt= GET_RTX_FORMAT (code);
+       for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ 	{
+ 	  if (fmt[i] == 'e')
+ 	    delete_address_reloads_1 (dead_insn, XEXP (x, i), current_insn);
+ 	  else if (fmt[i] == 'E')
+ 	    {
+ 	      for (j = XVECLEN (x, i) - 1; j >=0; j--)
+ 		delete_address_reloads_1 (dead_insn, XVECEXP (x, i, j),
+ 					  current_insn);
+ 	    }
+ 	}
+       return;
      }
  
+   if (spill_reg_order[REGNO (x)] < 0)
+     return;
+ 
+   /* Scan backwards for the insn that sets x.  This might be a way back due
+      to inheritance.  */
+   for (prev = PREV_INSN (dead_insn); prev; prev = PREV_INSN (prev))
+     {
+       code = GET_CODE (prev);
+       if (code == CODE_LABEL || code == JUMP_INSN)
+ 	return;
+       if (GET_RTX_CLASS (code) != 'i')
+ 	continue;
+       if (reg_set_p (x, PATTERN (prev)))
+ 	break;
+       if (reg_referenced_p (x, PATTERN (prev)))
+ 	return;
+     }
+   if (! prev || INSN_UID (prev) < reload_first_uid)
+     return;
+   /* Check that PREV only sets the reload register.  */
+   set = single_set (prev);
+   if (! set)
+     return;
+   dst = SET_DEST (set);
+   if (GET_CODE (dst) != REG
+       || ! rtx_equal_p (dst, x))
+     return;
+   if (! reg_set_p (dst, PATTERN (dead_insn)))
+     {
+       /* Check if DST was used in a later insn -
+ 	 it might have been inherited.  */
+       for (i2 = NEXT_INSN (dead_insn); i2; i2 = NEXT_INSN (i2))
+ 	{
+ 	  if (GET_CODE (i2) == CODE_LABEL)
+ 	    break;
+ 	  if (GET_RTX_CLASS (GET_CODE (i2)) != 'i')
+ 	    continue;
+ 	  if (reg_referenced_p (dst, PATTERN (i2)))
+ 	    {
+ 	      /* If there is a reference to the register in the current insn,
+ 		 it might be loaded in a non-inherited reload.  If no other
+ 		 reload uses it, that means the register is set before
+ 		 referenced.  */
+ 	      if (i2 == current_insn)
+ 		{
+ 		  for (j = n_reloads - 1; j >= 0; j--)
+ 		    if ((reload_reg_rtx[j] == dst && reload_inherited[j])
+ 			|| reload_override_in[j] == dst)
+ 		      return;
+ 		  for (j = n_reloads - 1; j >= 0; j--)
+ 		    if (reload_in[j] && reload_reg_rtx[j] == dst)
+ 		      break;
+ 		  if (j >= 0)
+ 		    break;
+ 		}
+ 	      return;
+ 	    }
+ 	  if (GET_CODE (i2) == JUMP_INSN)
+ 	    break;
+ 	  if (reg_set_p (dst, PATTERN (i2)))
+ 	    break;
+ 	  /* If DST is still live at CURRENT_INSN, check if it is used for
+ 	     any reload.  */
+ 	  if (i2 == current_insn)
+ 	    {
+ 	      for (j = n_reloads - 1; j >= 0; j--)
+ 		if ((reload_reg_rtx[j] == dst && reload_inherited[j])
+ 		    || reload_override_in[j] == dst)
+ 		  return;
+ 	      /* ??? We can't finish the loop here, because dst might be
+ 		 allocated to a pseudo in this block if no reload in this
+ 		 block needs any of the clsses containing DST - see
+ 		 spill_hard_reg.  There is no easy way to tell this, so we
+ 		 have to scan till the end of the basic block.  */
+ 	    }
+ 	}
+     }
+   delete_address_reloads_1 (prev, SET_SRC (set), current_insn);
+   reg_reloaded_contents[REGNO (dst)] = -1;
+   /* Can't use delete_insn here because PREV might be a basic block head.  */
+   PUT_CODE (prev, NOTE);
+   NOTE_LINE_NUMBER (prev) = NOTE_INSN_DELETED;
+   NOTE_SOURCE_FILE (prev) = 0;
  }
  
  /* Output reload-insns to reload VALUE into RELOADREG.
     VALUE is an autoincrement or autodecrement RTX whose operand
     is a register or memory location;
     so reloading involves incrementing that location.
+    IN is either identical to VALUE, or some cheaper place to reload from.
  
     INC_AMOUNT is the number to increment or decrement by (always positive).
!    This cannot be deduced from VALUE.
  
!    Return the instruction that stores into RELOADREG.  */
! 
! static rtx
! inc_for_reload (reloadreg, in, value, inc_amount)
       rtx reloadreg;
!      rtx in, value;
       int inc_amount;
  {
    /* REG or MEM to be copied and incremented.  */
*************** inc_for_reload (reloadreg, value, inc_am
*** 7627,7632 ****
--- 8252,8259 ----
    rtx inc;
    rtx add_insn;
    int code;
+   rtx store;
+   rtx real_in = in == value ? XEXP (in, 0) : in;
  
    /* No hard register is equivalent to this register after
       inc/dec operation.  If REG_LAST_RELOAD_REG were non-zero,
*************** inc_for_reload (reloadreg, value, inc_am
*** 7641,7676 ****
    inc = GEN_INT (inc_amount);
  
    /* If this is post-increment, first copy the location to the reload reg.  */
!   if (post)
!     emit_insn (gen_move_insn (reloadreg, incloc));
  
!   /* See if we can directly increment INCLOC.  Use a method similar to that
!      in gen_reload.  */
  
!   last = get_last_insn ();
!   add_insn = emit_insn (gen_rtx_SET (VOIDmode, incloc,
! 				     gen_rtx_PLUS (GET_MODE (incloc),
! 						   incloc, inc)));
  							  
!   code = recog_memoized (add_insn);
!   if (code >= 0)
!     {
!       insn_extract (add_insn);
!       if (constrain_operands (code, 1))
  	{
! 	  /* If this is a pre-increment and we have incremented the value
! 	     where it lives, copy the incremented value to RELOADREG to
! 	     be used as an address.  */
  
! 	  if (! post)
! 	    emit_insn (gen_move_insn (reloadreg, incloc));
  
! 	  return;
  	}
      }
  
-   delete_insns_since (last);
- 
    /* If couldn't do the increment directly, must increment in RELOADREG.
       The way we do this depends on whether this is pre- or post-increment.
       For pre-increment, copy INCLOC to the reload register, increment it
--- 8268,8305 ----
    inc = GEN_INT (inc_amount);
  
    /* If this is post-increment, first copy the location to the reload reg.  */
!   if (post && real_in != reloadreg)
!     emit_insn (gen_move_insn (reloadreg, real_in));
  
!   if (in == value)
!     {
!       /* See if we can directly increment INCLOC.  Use a method similar to
! 	 that in gen_reload.  */
  
!       last = get_last_insn ();
!       add_insn = emit_insn (gen_rtx_SET (VOIDmode, incloc,
! 					 gen_rtx_PLUS (GET_MODE (incloc),
! 						       incloc, inc)));
  							  
!       code = recog_memoized (add_insn);
!       if (code >= 0)
  	{
! 	  insn_extract (add_insn);
! 	  if (constrain_operands (code, 1))
! 	    {
! 	      /* If this is a pre-increment and we have incremented the value
! 		 where it lives, copy the incremented value to RELOADREG to
! 		 be used as an address.  */
  
! 	      if (! post)
! 		emit_insn (gen_move_insn (reloadreg, incloc));
  
! 	      return add_insn;
! 	    }
  	}
+       delete_insns_since (last);
      }
  
    /* If couldn't do the increment directly, must increment in RELOADREG.
       The way we do this depends on whether this is pre- or post-increment.
       For pre-increment, copy INCLOC to the reload register, increment it
*************** inc_for_reload (reloadreg, value, inc_am
*** 7678,7686 ****
  
    if (! post)
      {
!       emit_insn (gen_move_insn (reloadreg, incloc));
        emit_insn (gen_add2_insn (reloadreg, inc));
!       emit_insn (gen_move_insn (incloc, reloadreg));
      }
    else
      {
--- 8307,8316 ----
  
    if (! post)
      {
!       if (in != reloadreg)
! 	emit_insn (gen_move_insn (reloadreg, real_in));
        emit_insn (gen_add2_insn (reloadreg, inc));
!       store = emit_insn (gen_move_insn (incloc, reloadreg));
      }
    else
      {
*************** inc_for_reload (reloadreg, value, inc_am
*** 7689,7704 ****
  	 may not be available after the insn in an input reload, we must do
  	 the incrementation before the insn being reloaded for.
  
! 	 We have already copied INCLOC to RELOADREG.  Increment the copy in
  	 RELOADREG, save that back, then decrement RELOADREG so it has
  	 the original value.  */
  
        emit_insn (gen_add2_insn (reloadreg, inc));
!       emit_insn (gen_move_insn (incloc, reloadreg));
        emit_insn (gen_add2_insn (reloadreg, GEN_INT (-inc_amount)));
      }
  
!   return;
  }
  
  /* Return 1 if we are certain that the constraint-string STRING allows
--- 8319,8334 ----
  	 may not be available after the insn in an input reload, we must do
  	 the incrementation before the insn being reloaded for.
  
! 	 We have already copied IN to RELOADREG.  Increment the copy in
  	 RELOADREG, save that back, then decrement RELOADREG so it has
  	 the original value.  */
  
        emit_insn (gen_add2_insn (reloadreg, inc));
!       store = emit_insn (gen_move_insn (incloc, reloadreg));
        emit_insn (gen_add2_insn (reloadreg, GEN_INT (-inc_amount)));
      }
  
!   return store;
  }
  
  /* Return 1 if we are certain that the constraint-string STRING allows
*************** count_occurrences (x, find)
*** 7777,7782 ****
--- 8407,8416 ----
      case CC0:
        return 0;
  
+     case MEM:
+       if (GET_CODE (find) == MEM && rtx_equal_p (x, find))
+ 	return 1;
+       break;
      case SET:
        if (SET_DEST (x) == find)
  	return count_occurrences (SET_SRC (x), find);


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