Patchwork Fix postreload problems

login
register
mail settings
Submitter Bernd Schmidt
Date July 21, 2010, 10:48 p.m.
Message ID <4C47793F.8040500@codesourcery.com>
Download mbox | patch
Permalink /patch/59515/
State New
Headers show

Comments

Bernd Schmidt - July 21, 2010, 10:48 p.m.
There are still some reports of bootstrap failures and other problems
after my postreload patch last week.  The patch below should fix these.
 IainS has been very helpful in providing a testcase.  While I didn't
have a testcase I stared the code for a long time; this also produced
some fixes, even in the old code.

The main problem was that the new code could mess up lifetime
information by rescanning a previously encountered insn with
reload_combine_note_use.  This could add uses for registers that are set
between the current point and the old use.

In the old optimization, reload_combine_recognize_pattern, we can
sometimes allocate a new register.  This code wasn't checking whether
it's actually safe to do so; I've copied a range of typical checks from
elsewhere.  Some of them are likely already covered by the life
information we compute, others (like the df_regs_ever_live_p check and
the call to hard_regno_scratch_ok) seem necessary.

Some remnants of my first attempt to fix the DEBUG_INSN problem
remained; I've removed those.

Bootstrapped, tested on x86_64-linux and i686-linux (where I only saw
the failure from PR45005), and committed.


Bernd
PR bootstrap/44970
	PR middle-end/45009
	* postreload.c: Include "target.h".
	(reload_combine_closest_single_use): Don't take DEBUG_INSNs
	into account.
	(fixup_debug_insns): Don't copy the rtx.
	(reload_combine_recognize_const_pattern): DEBUG_INSNs can't
	have uses.  Don't copy when replacing.  Call fixup_debug_insns
	in the case where we merged one add with another.
	(reload_combine_recognize_pattern): Fail if there aren't any
	uses.  Try harder to determine whether we're picking a valid
	index register.  Don't set store_ruid for an insn we're going
	to scan in the next iteration.
	(reload_combine): Remove unused code.
	(reload_combine_note_use): When updating use information for
	an old insn, ignore a use that occurs after store_ruid.
	* Makefile.in (postreload.o): Update dependencies.

Patch

Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c	(revision 162372)
+++ gcc/postreload.c	(working copy)
@@ -44,6 +44,7 @@  along with GCC; see the file COPYING3.  
 #include "toplev.h"
 #include "except.h"
 #include "tree.h"
+#include "target.h"
 #include "timevar.h"
 #include "tree-pass.h"
 #include "df.h"
@@ -816,8 +817,7 @@  reload_combine_purge_reg_uses_after_ruid
 
 /* Find the use of REGNO with the ruid that is highest among those
    lower than RUID_LIMIT, and return it if it is the only use of this
-   reg in the insn (or if the insn is a debug insn).  Return NULL
-   otherwise.  */
+   reg in the insn.  Return NULL otherwise.  */
 
 static struct reg_use *
 reload_combine_closest_single_use (unsigned regno, int ruid_limit)
@@ -838,9 +838,9 @@  reload_combine_closest_single_use (unsig
       if (this_ruid > best_ruid)
 	{
 	  best_ruid = this_ruid;
-	  retval = reg_state[regno].reg_use + i;
+	  retval = use;
 	}
-      else if (this_ruid == best_ruid && !DEBUG_INSN_P (use->insn))
+      else if (this_ruid == best_ruid)
 	retval = NULL;
     }
   if (last_label_ruid >= best_ruid)
@@ -866,7 +866,7 @@  fixup_debug_insns (rtx reg, rtx replacem
 	continue;
       
       t = INSN_VAR_LOCATION_LOC (insn);
-      t = simplify_replace_rtx (t, reg, copy_rtx (replacement));
+      t = simplify_replace_rtx (t, reg, replacement);
       validate_change (insn, &INSN_VAR_LOCATION_LOC (insn), t, 0);
     }
 }
@@ -938,10 +938,6 @@  reload_combine_recognize_const_pattern (
 	/* Start the search for the next use from here.  */
 	from_ruid = use->ruid;
 
-      /* We'll fix up DEBUG_INSNs after we're done.  */
-      if (use && DEBUG_INSN_P (use->insn))
-	continue;
-
       if (use && GET_MODE (*use->usep) == Pmode)
 	{
 	  rtx use_insn = use->insn;
@@ -972,7 +968,7 @@  reload_combine_recognize_const_pattern (
 	      int old_cost = address_cost (oldaddr, GET_MODE (mem), as, speed);
 	      int new_cost;
 
-	      newaddr = simplify_replace_rtx (oldaddr, reg, copy_rtx (src));
+	      newaddr = simplify_replace_rtx (oldaddr, reg, src);
 	      if (memory_address_addr_space_p (GET_MODE (mem), newaddr, as))
 		{
 		  XEXP (mem, 0) = newaddr;
@@ -1008,8 +1004,7 @@  reload_combine_recognize_const_pattern (
 		  int old_cost = rtx_cost (SET_SRC (new_set), SET, speed);
 
 		  gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg));
-		  new_src = simplify_replace_rtx (SET_SRC (new_set), reg,
-						  copy_rtx (src));
+		  new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src);
 
 		  if (rtx_cost (new_src, SET, speed) <= old_cost
 		      && validate_change (use_insn, &SET_SRC (new_set),
@@ -1024,6 +1019,7 @@  reload_combine_recognize_const_pattern (
 			  /* See if that took care of the add insn.  */
 			  if (rtx_equal_p (SET_DEST (new_set), reg))
 			    {
+			      fixup_debug_insns (reg, src, insn, use_insn);
 			      delete_insn (insn);
 			      return true;
 			    }
@@ -1102,6 +1098,8 @@  reload_combine_recognize_pattern (rtx in
       && REG_P (XEXP (src, 1))
       && rtx_equal_p (XEXP (src, 0), reg)
       && !rtx_equal_p (XEXP (src, 1), reg)
+      && reg_state[regno].use_index >= 0
+      && reg_state[regno].use_index < RELOAD_COMBINE_MAX_USES
       && last_label_ruid < reg_state[regno].use_ruid)
     {
       rtx base = XEXP (src, 1);
@@ -1134,7 +1132,11 @@  reload_combine_recognize_pattern (rtx in
 	      if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i)
 		  && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
 		  && reg_state[i].store_ruid <= reg_state[regno].use_ruid
-		  && hard_regno_nregs[i][GET_MODE (reg)] == 1)
+		  && (call_used_regs[i] || df_regs_ever_live_p (i))
+		  && (!frame_pointer_needed || i != HARD_FRAME_POINTER_REGNUM)
+		  && !fixed_regs[i] && !global_regs[i]
+		  && hard_regno_nregs[i][GET_MODE (reg)] == 1
+		  && targetm.hard_regno_scratch_ok (regno))
 		{
 		  index_reg = gen_rtx_REG (GET_MODE (reg), i);
 		  reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base);
@@ -1150,7 +1152,6 @@  reload_combine_recognize_pattern (rtx in
 	  && prev_set
 	  && CONST_INT_P (SET_SRC (prev_set))
 	  && rtx_equal_p (SET_DEST (prev_set), reg)
-	  && reg_state[regno].use_index >= 0
 	  && (reg_state[REGNO (base)].store_ruid
 	      <= reg_state[regno].use_ruid))
 	{
@@ -1201,8 +1202,6 @@  reload_combine_recognize_pattern (rtx in
 		remove_reg_equal_equiv_notes (prev);
 
 	      reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
-	      reg_state[REGNO (index_reg)].store_ruid
-		= reload_combine_ruid;
 	      return true;
 	    }
 	}
@@ -1244,14 +1243,6 @@  reload_combine (void)
 	}
     }
 
-#if 0
-  /* If reg+reg can be used in offsetable memory addresses, the main chunk of
-     reload has already used it where appropriate, so there is no use in
-     trying to generate it now.  */
-  if (double_reg_address_ok || last_index_reg == -1)
-    return;
-#endif
-
   /* Set up LABEL_LIVE and EVER_LIVE_AT_START.  The register lifetime
      information is a bit fuzzy immediately after reload, but it's
      still good enough to determine which registers are live at a jump
@@ -1511,6 +1502,11 @@  reload_combine_note_use (rtx *xp, rtx in
 	    return;
 	  }
 
+	/* We may be called to update uses in previously seen insns.
+	   Don't add uses beyond the last store we saw.  */
+	if (ruid < reg_state[regno].store_ruid)
+	  return;
+
 	/* If this register is already used in some unknown fashion, we
 	   can't do anything.
 	   If we decrement the index from zero to -1, we can't store more
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 162372)
+++ Makefile.in	(working copy)
@@ -3288,7 +3288,7 @@  postreload.o : postreload.c $(CONFIG_H) 
    $(RTL_H) $(FLAGS_H) $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) \
    hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) output.h \
    $(FUNCTION_H) $(TOPLEV_H) $(DIAGNOSTIC_CORE_H) cselib.h $(TM_P_H) $(EXCEPT_H) $(TREE_H) $(MACHMODE_H) \
-   $(OBSTACK_H) $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H)
+   $(OBSTACK_H) $(TARGET_H) $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H)
 postreload-gcse.o : postreload-gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
    $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h $(TOPLEV_H) $(DIAGNOSTIC_CORE_H) \