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]
Other format: [Raw text]

Re: RFC: remove find_replacement. (pr24912 / pr25335)


Ulrich Weigand wrote:

The culprit appears to be not reload inheritance proper, but this last-

minute attempt in emit_input_reload_insns:

/* If reloading from memory, see if there is a register
that already holds the same value. If so, reload from there.
We can pass 0 as the reload_reg_p argument because
any other reload has either already been emitted,
in which case find_equiv_reg will see the reload-insn,
or has yet to be emitted, in which case it doesn't matter
because we will use this equiv reg right away. */



Does the attached patch work for you?


2006-02-07  J"orn Rennecke <joern.rennecke@st.com>

	* reload1.c (reload_as_needed): Call subst_reloads before
	emit_reload_insns.
	(gen_reload): Don't call find_replacement.
	* reload.c (find_replacement): Remove.
	* reload.h (find_replacement): Don't declare.
	* expr.c (emit_move_multi_word): Don't use find_replacement.
	* alpha.c (get_aligned_mem, get_unaligned_address): Likewise.
	* s390.c (s390_expand_plus_operand): Likewise.
	* s390.md (reload_outti, reload_outdi, reload_outdf): Likewise.
	* m68k.c (emit_move_sequence): Likewise.
	* arm.c (arm_reload_in_hi, arm_reload_out_hi): Likewise.
	* pa.c (emit_move_sequence): Likewise.

	* reload1.c (reconsider_reload_override) New function, broken out of:
	(emit_input_reload_insns).
	(reload_by_redirect): Likewise.
	(reconsider_reload_regs): New function.
	(reload_as_needed): Call it.

Index: reload.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L reload.c	(revision 110699) -L reload.c	(working copy) .svn/text-base/reload.c.svn-base reload.c
--- reload.c	(revision 110699)
+++ reload.c	(working copy)
@@ -6122,69 +6122,6 @@ move_replacements (rtx *x, rtx *y)
       }
 }
 
-/* If LOC was scheduled to be replaced by something, return the replacement.
-   Otherwise, return *LOC.  */
-
-rtx
-find_replacement (rtx *loc)
-{
-  struct replacement *r;
-
-  for (r = &replacements[0]; r < &replacements[n_replacements]; r++)
-    {
-      rtx reloadreg = rld[r->what].reg_rtx;
-
-      if (reloadreg && r->where == loc)
-	{
-	  if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
-	    reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg));
-
-	  return reloadreg;
-	}
-      else if (reloadreg && r->subreg_loc == loc)
-	{
-	  /* RELOADREG must be either a REG or a SUBREG.
-
-	     ??? Is it actually still ever a SUBREG?  If so, why?  */
-
-	  if (REG_P (reloadreg))
-	    return gen_rtx_REG (GET_MODE (*loc),
-				(REGNO (reloadreg) +
-				 subreg_regno_offset (REGNO (SUBREG_REG (*loc)),
-						      GET_MODE (SUBREG_REG (*loc)),
-						      SUBREG_BYTE (*loc),
-						      GET_MODE (*loc))));
-	  else if (GET_MODE (reloadreg) == GET_MODE (*loc))
-	    return reloadreg;
-	  else
-	    {
-	      int final_offset = SUBREG_BYTE (reloadreg) + SUBREG_BYTE (*loc);
-
-	      /* When working with SUBREGs the rule is that the byte
-		 offset must be a multiple of the SUBREG's mode.  */
-	      final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (*loc)));
-	      final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (*loc)));
-	      return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg),
-				     final_offset);
-	    }
-	}
-    }
-
-  /* If *LOC is a PLUS, MINUS, or MULT, see if a replacement is scheduled for
-     what's inside and make a new rtl if so.  */
-  if (GET_CODE (*loc) == PLUS || GET_CODE (*loc) == MINUS
-      || GET_CODE (*loc) == MULT)
-    {
-      rtx x = find_replacement (&XEXP (*loc, 0));
-      rtx y = find_replacement (&XEXP (*loc, 1));
-
-      if (x != XEXP (*loc, 0) || y != XEXP (*loc, 1))
-	return gen_rtx_fmt_ee (GET_CODE (*loc), GET_MODE (*loc), x, y);
-    }
-
-  return *loc;
-}
-
 /* Return nonzero if register in range [REGNO, ENDREGNO)
    appears either explicitly or implicitly in X
    other than being stored into (except for earlyclobber operands).
Index: reload.h
===================================================================
/usr/bin/diff -p -d -F^( -u -L reload.h	(revision 110699) -L reload.h	(working copy) .svn/text-base/reload.h.svn-base reload.h
--- reload.h	(revision 110699)
+++ reload.h	(working copy)
@@ -300,10 +300,6 @@ extern void copy_replacements (rtx, rtx)
 /* Change any replacements being done to *X to be done to *Y */
 extern void move_replacements (rtx *x, rtx *y);
 
-/* If LOC was scheduled to be replaced by something, return the replacement.
-   Otherwise, return *LOC.  */
-extern rtx find_replacement (rtx *);
-
 /* Nonzero if modifying X will affect IN.  */
 extern int reg_overlap_mentioned_for_reload_p (rtx, rtx);
 
Index: expr.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L expr.c	(revision 110699) -L expr.c	(working copy) .svn/text-base/expr.c.svn-base expr.c
--- expr.c	(revision 110699)
+++ expr.c	(working copy)
@@ -3046,7 +3046,7 @@ static rtx
 emit_move_multi_word (enum machine_mode mode, rtx x, rtx y)
 {
   rtx last_insn = 0;
-  rtx seq, inner;
+  rtx seq;
   bool need_clobber;
   int i;
       
@@ -3057,15 +3057,6 @@ emit_move_multi_word (enum machine_mode 
   if (push_operand (x, mode))
     x = emit_move_resolve_push (mode, x);
 
-  /* If we are in reload, see if either operand is a MEM whose address
-     is scheduled for replacement.  */
-  if (reload_in_progress && MEM_P (x)
-      && (inner = find_replacement (&XEXP (x, 0))) != XEXP (x, 0))
-    x = replace_equiv_address_nv (x, inner);
-  if (reload_in_progress && MEM_P (y)
-      && (inner = find_replacement (&XEXP (y, 0))) != XEXP (y, 0))
-    y = replace_equiv_address_nv (y, inner);
-
   start_sequence ();
 
   need_clobber = false;
Index: config/alpha/alpha.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/alpha/alpha.c	(revision 110699) -L config/alpha/alpha.c	(working copy) config/alpha/.svn/text-base/alpha.c.svn-base config/alpha/alpha.c
--- config/alpha/alpha.c	(revision 110699)
+++ config/alpha/alpha.c	(working copy)
@@ -1509,7 +1509,7 @@ get_aligned_mem (rtx ref, rtx *paligned_
   if (reload_in_progress
       && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
     {
-      base = find_replacement (&XEXP (ref, 0));
+      base = XEXP (ref, 0);
       gcc_assert (memory_address_p (GET_MODE (ref), base));
     }
   else
@@ -1554,7 +1554,7 @@ get_unaligned_address (rtx ref, int extr
   if (reload_in_progress
       && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
     {
-      base = find_replacement (&XEXP (ref, 0));
+      base = XEXP (ref, 0);
 
       gcc_assert (memory_address_p (GET_MODE (ref), base));
     }
Index: config/s390/s390.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/s390/s390.c	(revision 110699) -L config/s390/s390.c	(working copy) config/s390/.svn/text-base/s390.c.svn-base config/s390/s390.c
--- config/s390/s390.c	(revision 110699)
+++ config/s390/s390.c	(working copy)
@@ -2667,8 +2667,8 @@ s390_expand_plus_operand (rtx target, rt
   /* Check if any of the two operands is already scheduled
      for replacement by reload.  This can happen e.g. when
      float registers occur in an address.  */
-  sum1 = find_replacement (&XEXP (src, 0));
-  sum2 = find_replacement (&XEXP (src, 1));
+  sum1 = XEXP (src, 0);
+  sum2 = XEXP (src, 1);
   src = gen_rtx_PLUS (Pmode, sum1, sum2);
 
   /* If the address is already strictly valid, there's nothing to do.  */
@@ -2691,8 +2691,7 @@ s390_expand_plus_operand (rtx target, rt
 
       /* According to the way these invalid addresses are generated
          in reload.c, it should never happen (at least on s390) that
-         *neither* of the PLUS components, after find_replacements
-         was applied, is an address register.  */
+         *neither* of the PLUS components is an address register.  */
       if (sum1 == scratch && sum2 == scratch)
 	{
 	  debug_rtx (src);
Index: config/s390/s390.md
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/s390/s390.md	(revision 110699) -L config/s390/s390.md	(working copy) config/s390/.svn/text-base/s390.md.svn-base config/s390/s390.md
--- config/s390/s390.md	(revision 110699)
+++ config/s390/s390.md	(working copy)
@@ -883,7 +883,7 @@ (define_expand "reload_outti"
   "TARGET_64BIT"
 {
   gcc_assert (MEM_P (operands[0]));
-  s390_load_address (operands[2], find_replacement (&XEXP (operands[0], 0)));
+  s390_load_address (operands[2], XEXP (operands[0], 0));
   operands[0] = replace_equiv_address (operands[0], operands[2]);
   emit_move_insn (operands[0], operands[1]);
   DONE;
@@ -1078,7 +1078,7 @@ (define_expand "reload_outdi"
   "!TARGET_64BIT"
 {
   gcc_assert (MEM_P (operands[0]));
-  s390_load_address (operands[2], find_replacement (&XEXP (operands[0], 0)));
+  s390_load_address (operands[2], XEXP (operands[0], 0));
   operands[0] = replace_equiv_address (operands[0], operands[2]);
   emit_move_insn (operands[0], operands[1]);
   DONE;
@@ -1686,7 +1686,7 @@ (define_expand "reload_outdf"
   "!TARGET_64BIT"
 {
   gcc_assert (MEM_P (operands[0]));
-  s390_load_address (operands[2], find_replacement (&XEXP (operands[0], 0)));
+  s390_load_address (operands[2], XEXP (operands[0], 0));
   operands[0] = replace_equiv_address (operands[0], operands[2]);
   emit_move_insn (operands[0], operands[1]);
   DONE;
Index: config/m68k/m68k.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/m68k/m68k.c	(revision 110699) -L config/m68k/m68k.c	(working copy) config/m68k/.svn/text-base/m68k.c.svn-base config/m68k/m68k.c
--- config/m68k/m68k.c	(revision 110699)
+++ config/m68k/m68k.c	(working copy)
@@ -2387,11 +2387,11 @@ emit_move_sequence (rtx *operands, enum 
     }
 
   if (scratch_reg && reload_in_progress && GET_CODE (operand0) == MEM
-      && ((tem = find_replacement (&XEXP (operand0, 0)))
+      && ((tem = XEXP (operand0, 0))
 	  != XEXP (operand0, 0)))
     operand0 = gen_rtx_MEM (GET_MODE (operand0), tem);
   if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM
-      && ((tem = find_replacement (&XEXP (operand1, 0)))
+      && ((tem = XEXP (operand1, 0))
 	  != XEXP (operand1, 0)))
     operand1 = gen_rtx_MEM (GET_MODE (operand1), tem);
 
Index: config/arm/arm.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/arm/arm.c	(revision 110699) -L config/arm/arm.c	(working copy) config/arm/.svn/text-base/arm.c.svn-base config/arm/arm.c
--- config/arm/arm.c	(revision 110699)
+++ config/arm/arm.c	(working copy)
@@ -6827,14 +6827,14 @@ arm_reload_in_hi (rtx *operands)
       if (reg_equiv_mem[REGNO (ref)])
 	{
 	  ref = reg_equiv_mem[REGNO (ref)];
-	  base = find_replacement (&XEXP (ref, 0));
+	  base = XEXP (ref, 0);
 	}
       else
 	/* The slot is out of range, or was dressed up in a SUBREG.  */
 	base = reg_equiv_address[REGNO (ref)];
     }
   else
-    base = find_replacement (&XEXP (ref, 0));
+    base = XEXP (ref, 0);
 
   /* Handle the case where the address is too complex to be offset by 1.  */
   if (GET_CODE (base) == MINUS
@@ -6944,14 +6944,14 @@ arm_reload_out_hi (rtx *operands)
       if (reg_equiv_mem[REGNO (ref)])
 	{
 	  ref = reg_equiv_mem[REGNO (ref)];
-	  base = find_replacement (&XEXP (ref, 0));
+	  base = XEXP (ref, 0);
 	}
       else
 	/* The slot is out of range, or was dressed up in a SUBREG.  */
 	base = reg_equiv_address[REGNO (ref)];
     }
   else
-    base = find_replacement (&XEXP (ref, 0));
+    base = XEXP (ref, 0);
 
   scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
 
Index: config/pa/pa.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/pa/pa.c	(revision 110699) -L config/pa/pa.c	(working copy) config/pa/.svn/text-base/pa.c.svn-base config/pa/pa.c
--- config/pa/pa.c	(revision 110699)
+++ config/pa/pa.c	(working copy)
@@ -1389,12 +1389,12 @@ emit_move_sequence (rtx *operands, enum 
     }
 
   if (scratch_reg && reload_in_progress && GET_CODE (operand0) == MEM
-      && ((tem = find_replacement (&XEXP (operand0, 0)))
+      && ((tem = XEXP (operand0, 0))
 	  != XEXP (operand0, 0)))
     operand0 = replace_equiv_address (operand0, tem);
 
   if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM
-      && ((tem = find_replacement (&XEXP (operand1, 0)))
+      && ((tem = XEXP (operand1, 0))
 	  != XEXP (operand1, 0)))
     operand1 = replace_equiv_address (operand1, tem);
 
Index: reload1.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L reload1.c	(revision 110699) -L reload1.c	(working copy) .svn/text-base/reload1.c.svn-base reload1.c
--- reload1.c	(revision 110699)
+++ reload1.c	(working copy)
@@ -420,6 +420,9 @@ static int set_reload_reg (int, int);
 static void choose_reload_regs_init (struct insn_chain *, rtx *);
 static void choose_reload_regs (struct insn_chain *);
 static void merge_assigned_reloads (rtx);
+static void reconsider_reload_regs (rtx insn);
+static void reconsider_reload_override (rtx, struct reload *, rtx, int);
+static bool reload_by_redirect (rtx, struct reload *, rtx, int, bool);
 static void emit_input_reload_insns (struct insn_chain *, struct reload *,
 				     rtx, int);
 static void emit_output_reload_insns (struct insn_chain *, struct reload *,
@@ -3965,16 +3968,24 @@ reload_as_needed (int live_known)
 	      if (SMALL_REGISTER_CLASSES)
 		merge_assigned_reloads (insn);
 
-	      /* Generate the insns to reload operands into or out of
-		 their reload regs.  */
-	      emit_reload_insns (chain);
+	      reconsider_reload_regs (insn);
 
 	      /* Substitute the chosen reload regs from reload_reg_rtx
-		 into the insn's body (or perhaps into the bodies of other
-		 load and store insn that we just made for reloading
-		 and that we moved the structure into).  */
+		 into the insn's body, or perhaps into information about
+		 the reloads that we are about to emit.
+		 It's for the sake of the latter that we do this before
+		 emitting the actual reload insns; this allows us to
+		 check reload insns for validity in gen_reload.  */
 	      subst_reloads (insn);
 
+	      /* ??? We should try to call reload_by_redirect from here.
+		 Since the substitutions have already been done, multiple
+		 reloaded occurences should pose no problem.  */
+
+	      /* Generate the insns to reload operands into or out of
+		 their reload regs.  */
+	      emit_reload_insns (chain);
+
 	      /* Adjust the exception region notes for loads and stores.  */
 	      if (flag_non_call_exceptions && !CALL_P (insn))
 		fixup_eh_region_note (insn, prev, next);
@@ -5715,6 +5726,7 @@ choose_reload_regs (struct insn_chain *c
 			 there.  */
 		      gcc_assert (GET_CODE (equiv) == SUBREG);
 		      regno = subreg_regno (equiv);
+		      /* ??? We should take SUBREG_BYTE into account!  */
 		      equiv = gen_rtx_REG (rld[r].mode, regno);
 		      /* If we choose EQUIV as the reload register, but the
 			 loop below decides to cancel the inheritance, we'll
@@ -6276,54 +6288,38 @@ reload_adjust_reg_for_icode (rtx *reload
 				     new_class, new_mode);
 }
 
-/* Generate insns to perform reload RL, which is for the insn in CHAIN and
-   has the number J.  OLD contains the value to be used as input.  */
-
+/* Try some more reload inheritance for INSN after merging assigned reloads.  */
 static void
-emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
-			 rtx old, int j)
+reconsider_reload_regs (rtx insn)
 {
-  rtx insn = chain->insn;
-  rtx reloadreg = rl->reg_rtx;
-  rtx oldequiv_reg = 0;
-  rtx oldequiv = 0;
-  int special = 0;
-  enum machine_mode mode;
-  rtx *where;
-
-  /* Determine the mode to reload in.
-     This is very tricky because we have three to choose from.
-     There is the mode the insn operand wants (rl->inmode).
-     There is the mode of the reload register RELOADREG.
-     There is the intrinsic mode of the operand, which we could find
-     by stripping some SUBREGs.
-     It turns out that RELOADREG's mode is irrelevant:
-     we can change that arbitrarily.
-
-     Consider (SUBREG:SI foo:QI) as an operand that must be SImode;
-     then the reload reg may not support QImode moves, so use SImode.
-     If foo is in memory due to spilling a pseudo reg, this is safe,
-     because the QImode value is in the least significant part of a
-     slot big enough for a SImode.  If foo is some other sort of
-     memory reference, then it is impossible to reload this case,
-     so previous passes had better make sure this never happens.
-
-     Then consider a one-word union which has SImode and one of its
-     members is a float, being fetched as (SUBREG:SF union:SI).
-     We must fetch that as SFmode because we could be loading into
-     a float-only register.  In this case OLD's mode is correct.
+  int j;
 
-     Consider an immediate integer: it has VOIDmode.  Here we need
-     to get a mode from something else.
+  if (!optimize)
+    return;
+  for (j = 0; j < n_reloads; j++)
+    {
+      struct reload *rl = &rld[j];
+      rtx old = rl->in_reg && MEM_P (rl->in_reg) ? rl->in_reg : rl->in_reg;
 
-     In some cases, there is a fourth mode, the operand's
-     containing mode.  If the insn specifies a containing mode for
-     this operand, it overrides all others.
+      if (!old
+	  || reload_inherited[j]
+	  || ! rtx_equal_p (rl->reg_rtx, old)
+	  || ! rl->reg_rtx != 0)
+	continue;
+      if (reload_by_redirect (insn, rl, old, j, false))
+	continue;
+      reconsider_reload_override (insn, rl, old, j);
+    }
+}
 
-     I am not sure whether the algorithm here is always right,
-     but it does the right things in those cases.  */
+/* RL is a reload of INSN which reloads the input OLD, and has number J.
+   Try to find an equivalence to set reload_override_in.  */
+static void
+reconsider_reload_override (rtx insn, struct reload *rl, rtx old, int j)
+{
+  enum machine_mode mode = GET_MODE (old);
+  rtx oldequiv = 0;
 
-  mode = GET_MODE (old);
   if (mode == VOIDmode)
     mode = rl->inmode;
 
@@ -6333,8 +6329,7 @@ emit_input_reload_insns (struct insn_cha
      register.  */
 
   if (rl->secondary_in_reload >= 0
-      && rl->secondary_in_icode == CODE_FOR_nothing
-      && optimize)
+      && rl->secondary_in_icode == CODE_FOR_nothing)
     oldequiv
       = find_equiv_reg (old, insn,
 			rld[rl->secondary_in_reload].class,
@@ -6348,7 +6343,7 @@ emit_input_reload_insns (struct insn_cha
      or has yet to be emitted, in which case it doesn't matter
      because we will use this equiv reg right away.  */
 
-  if (oldequiv == 0 && optimize
+  if (oldequiv == 0
       && (MEM_P (old)
 	  || (REG_P (old)
 	      && REGNO (old) >= FIRST_PSEUDO_REGISTER
@@ -6385,24 +6380,159 @@ emit_input_reload_insns (struct insn_cha
 	      ))
 	oldequiv = 0;
     }
+  if (oldequiv)
+    {
+      if (GET_CODE (oldequiv) == SUBREG)
+	oldequiv
+	  = simplify_subreg (mode, SUBREG_REG (oldequiv),
+			     GET_MODE (SUBREG_REG (oldequiv)),
+			     SUBREG_BYTE (oldequiv));
+      gcc_assert (REG_P (oldequiv));
+      rl->in = reload_override_in[j] = oldequiv;
+    }
+}
+
+/* RL is a reload of INSN which reloads the input OLD, and has number J.
+   Try to get the right value into the reload reg by changing a preceding
+   insn.  If SUBSTED is true, reload registers have already been substituted
+   into INSN.  Return true for success.  */
+static bool
+reload_by_redirect (rtx insn, struct reload *rl, rtx old, int j, bool substed)
+{
+  rtx reloadreg = rl->reg_rtx;
+
+  /* If we are reloading a pseudo-register that was set by the previous
+     insn, see if we can get rid of that pseudo-register entirely
+     by redirecting the previous insn into our reload register.  */
+
+  old = reload_override_in[j] ? rl->in_reg : old;
+  if (REG_P (old)
+      && REGNO (old) >= FIRST_PSEUDO_REGISTER
+      && dead_or_set_p (insn, old)
+      /* This is unsafe if some other reload
+	 uses the same reg first.  */
+      && ! conflicts_with_override (reloadreg)
+      && free_for_value_p (REGNO (reloadreg), rl->mode, rl->opnum,
+			   rl->when_needed, old, rl->out, j, 0))
+    {
+      rtx temp = PREV_INSN (insn);
+      while (temp && NOTE_P (temp))
+	temp = PREV_INSN (temp);
+      if (temp
+	  && NONJUMP_INSN_P (temp)
+	  && GET_CODE (PATTERN (temp)) == SET
+	  && SET_DEST (PATTERN (temp)) == old
+	  /* Make sure we can access insn_operand_constraint.  */
+	  && asm_noperands (PATTERN (temp)) < 0
+	  /* This is unsafe if operand occurs more than once in current
+	     insn.  Perhaps some occurrences aren't reloaded.
+	     If we are running after subst_reloads, all reloaded
+	     occurences will have been replaced.  */
+	  && count_occurrences (PATTERN (insn), old, 0) == substed ? 0 : 1)
+	{
+	  rtx old = SET_DEST (PATTERN (temp));
+	  /* Store into the reload register instead of the pseudo.  */
+	  SET_DEST (PATTERN (temp)) = reloadreg;
+
+	  /* Verify that resulting insn is valid.  */
+	  extract_insn (temp);
+	  if (constrain_operands (1))
+	    {
+	      /* If the previous insn is an output reload, the source is
+		 a reload register, and its spill_reg_store entry will
+		 contain the previous destination.  This is now
+		 invalid.  */
+	      if (REG_P (SET_SRC (PATTERN (temp)))
+		  && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER)
+		{
+		  spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0;
+		  spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0;
+		}
+
+	      /* If these are the only uses of the pseudo reg,
+		 pretend for GDB it lives in the reload reg we used.  */
+	      if (REG_N_DEATHS (REGNO (old)) == 1
+		  && REG_N_SETS (REGNO (old)) == 1)
+		{
+		  reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx);
+		  alter_reg (REGNO (old), -1);
+		}
+	      reload_inherited[j] = 1;
+	      reload_inheritance_insn[j] = temp;
+	      return true;
+	    }
+	  else
+	    {
+	      SET_DEST (PATTERN (temp)) = old;
+	    }
+	}
+    }
+  return false;
+}
+
+/* Generate insns to perform reload RL, which is for the insn in CHAIN and
+   has the number J.  OLD contains the value to be used as input.  */
+
+static void
+emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
+			 rtx old, int j)
+{
+  rtx insn = chain->insn;
+  rtx reloadreg = rl->reg_rtx;
+  rtx oldequiv_reg = 0;
+  rtx oldequiv = 0;
+  int special = 0;
+  enum machine_mode mode;
+  rtx *where;
+
+  /* Determine the mode to reload in.
+     This is very tricky because we have three to choose from.
+     There is the mode the insn operand wants (rl->inmode).
+     There is the mode of the reload register RELOADREG.
+     There is the intrinsic mode of the operand, which we could find
+     by stripping some SUBREGs.
+     It turns out that RELOADREG's mode is irrelevant:
+     we can change that arbitrarily.
+
+     Consider (SUBREG:SI foo:QI) as an operand that must be SImode;
+     then the reload reg may not support QImode moves, so use SImode.
+     If foo is in memory due to spilling a pseudo reg, this is safe,
+     because the QImode value is in the least significant part of a
+     slot big enough for a SImode.  If foo is some other sort of
+     memory reference, then it is impossible to reload this case,
+     so previous passes had better make sure this never happens.
+
+     Then consider a one-word union which has SImode and one of its
+     members is a float, being fetched as (SUBREG:SF union:SI).
+     We must fetch that as SFmode because we could be loading into
+     a float-only register.  In this case OLD's mode is correct.
+
+     Consider an immediate integer: it has VOIDmode.  Here we need
+     to get a mode from something else.
+
+     In some cases, there is a fourth mode, the operand's
+     containing mode.  If the insn specifies a containing mode for
+     this operand, it overrides all others.
+
+     I am not sure whether the algorithm here is always right,
+     but it does the right things in those cases.  */
+
+  mode = GET_MODE (old);
+  if (mode == VOIDmode)
+    mode = rl->inmode;
 
   /* 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]
+  if (reload_override_in[j]
       && REG_P (rl->in_reg))
     {
       oldequiv = old;
       old = rl->in_reg;
     }
-  if (oldequiv == 0)
+  else
     oldequiv = old;
-  else if (REG_P (oldequiv))
-    oldequiv_reg = oldequiv;
-  else if (GET_CODE (oldequiv) == SUBREG)
-    oldequiv_reg = SUBREG_REG (oldequiv);
 
   /* If we are reloading from a register that was recently stored in
      with an output-reload, see if we can prove there was
@@ -6498,69 +6628,7 @@ emit_input_reload_insns (struct insn_cha
 			  rl->inc);
     }
 
-  /* If we are reloading a pseudo-register that was set by the previous
-     insn, see if we can get rid of that pseudo-register entirely
-     by redirecting the previous insn into our reload register.  */
-
-  else if (optimize && REG_P (old)
-	   && REGNO (old) >= FIRST_PSEUDO_REGISTER
-	   && dead_or_set_p (insn, old)
-	   /* This is unsafe if some other reload
-	      uses the same reg first.  */
-	   && ! conflicts_with_override (reloadreg)
-	   && free_for_value_p (REGNO (reloadreg), rl->mode, rl->opnum,
-				rl->when_needed, old, rl->out, j, 0))
-    {
-      rtx temp = PREV_INSN (insn);
-      while (temp && NOTE_P (temp))
-	temp = PREV_INSN (temp);
-      if (temp
-	  && NONJUMP_INSN_P (temp)
-	  && GET_CODE (PATTERN (temp)) == SET
-	  && SET_DEST (PATTERN (temp)) == old
-	  /* Make sure we can access insn_operand_constraint.  */
-	  && asm_noperands (PATTERN (temp)) < 0
-	  /* This is unsafe if operand occurs more than once in current
-	     insn.  Perhaps some occurrences aren't reloaded.  */
-	  && count_occurrences (PATTERN (insn), old, 0) == 1)
-	{
-	  rtx old = SET_DEST (PATTERN (temp));
-	  /* Store into the reload register instead of the pseudo.  */
-	  SET_DEST (PATTERN (temp)) = reloadreg;
-
-	  /* Verify that resulting insn is valid.  */
-	  extract_insn (temp);
-	  if (constrain_operands (1))
-	    {
-	      /* If the previous insn is an output reload, the source is
-		 a reload register, and its spill_reg_store entry will
-		 contain the previous destination.  This is now
-		 invalid.  */
-	      if (REG_P (SET_SRC (PATTERN (temp)))
-		  && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER)
-		{
-		  spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0;
-		  spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0;
-		}
-
-	      /* If these are the only uses of the pseudo reg,
-		 pretend for GDB it lives in the reload reg we used.  */
-	      if (REG_N_DEATHS (REGNO (old)) == 1
-		  && REG_N_SETS (REGNO (old)) == 1)
-		{
-		  reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx);
-		  alter_reg (REGNO (old), -1);
-		}
-	      special = 1;
-	    }
-	  else
-	    {
-	      SET_DEST (PATTERN (temp)) = old;
-	    }
-	}
-    }
-
-  /* We can't do that, so output an insn to load RELOADREG.  */
+  /* Otherwise, output an insn to load RELOADREG.  */
 
   /* If we have a secondary reload, pick up the secondary register
      and icode, if any.  If OLDEQUIV and OLD are different or
@@ -7646,12 +7714,7 @@ gen_reload (rtx out, rtx in, int opnum, 
 
      This entire process is made complex because reload will never
      process the insns we generate here and so we must ensure that
-     they will fit their constraints and also by the fact that parts of
-     IN might be being reloaded separately and replaced with spill registers.
-     Because of this, we are, in some sense, just guessing the right approach
-     here.  The one listed above seems to work.
-
-     ??? At some point, this whole thing needs to be rethought.  */
+     they will fit their constraints.  */
 
   if (GET_CODE (in) == PLUS
       && (REG_P (XEXP (in, 0))
@@ -7678,8 +7741,8 @@ gen_reload (rtx out, rtx in, int opnum, 
       rtx op0, op1, tem, insn;
       int code;
 
-      op0 = find_replacement (&XEXP (in, 0));
-      op1 = find_replacement (&XEXP (in, 1));
+      op0 = XEXP (in, 0);
+      op1 = XEXP (in, 1);
 
       /* Since constraint checking is strict, commutativity won't be
 	 checked, so we need to do that here to avoid spurious failure

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