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]

[PATCH] combine: Delete EQ* notes when pseudo mode changes (PR60818)


For some modifications combine does it changes the mode of a pseudo
because of SELECT_CC_MODE.  For example, it changes "unsigned >= 0" to
"unsigned != 0", and on some targets GTU and NE use different CC_MODEs.

Changing the mode of a pseudo has effect globally, so this changes any
REG_EQUAL and REG_EQUIV notes referring to the pseudo as well, which
makes them invalid.  This patch finds such notes and deletes them in
these cases.

Testing on powerpc64-linux; will also test on x86_64-linux before
committing.


Segher


2016-02-19  Segher Boessenkool  <segher@kernel.crashing.org>

	PR 60818/rtl-optimization
	* combine.c (combine_remove_reg_equal_equiv_notes_for_regno):
	New function.
	(try_combine): Call it when SELECT_CC_MODE makes us change the
	mode of a pseudo.

---
 gcc/combine.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/gcc/combine.c b/gcc/combine.c
index 24dcefa..d3b69ac 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -2553,6 +2553,32 @@ can_split_parallel_of_n_reg_sets (rtx_insn *insn, int n)
   return true;
 }
 
+/* Remove all REG_EQUAL and REG_EQUIV notes referring to REGNO.  This is
+   like rtlanal's remove_reg_equal_equiv_notes_for_regno but with some big
+   differences, because combine does not keep the DF info up-to-date.
+   We do however never add or move these notes during combine, so we can
+   still use the DF info as it was at the start of combine to find all
+   such notes.  */
+
+static void
+combine_remove_reg_equal_equiv_notes_for_regno (unsigned int regno)
+{
+  gcc_assert (df);
+
+  rtx reg = regno_reg_rtx[regno];
+
+  for (df_ref eq_use = DF_REG_EQ_USE_CHAIN (regno);
+       eq_use;
+       eq_use = DF_REF_NEXT_REG (eq_use))
+    {
+      rtx_insn *insn = DF_REF_INSN (eq_use);
+      rtx note = find_reg_equal_equiv_note (insn);
+
+      if (note && reg_overlap_mentioned_p (reg, XEXP (note, 0)))
+	remove_note (insn, note);
+    }
+}
+
 /* Try to combine the insns I0, I1 and I2 into I3.
    Here I0, I1 and I2 appear earlier than I3.
    I0 and I1 can be zero; then we combine just I2 into I3, or I1 and I2 into
@@ -3184,6 +3210,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
 		    newpat_dest = gen_rtx_REG (compare_mode, regno);
 		  else
 		    {
+		      combine_remove_reg_equal_equiv_notes_for_regno (regno);
+
 		      SUBST_MODE (regno_reg_rtx[regno], compare_mode);
 		      newpat_dest = regno_reg_rtx[regno];
 		    }
@@ -6638,6 +6666,12 @@ simplify_set (rtx x)
 		new_dest = gen_rtx_REG (compare_mode, regno);
 	      else
 		{
+		  /* We change the mode of the result pseudo.  The expression
+		     in REG_EQ* notes refering to that pseudo will likely no
+		     longer make sense, so delete those notes.
+		     This is PR60818.  */
+		  combine_remove_reg_equal_equiv_notes_for_regno (regno);
+
 		  SUBST_MODE (regno_reg_rtx[regno], compare_mode);
 		  new_dest = regno_reg_rtx[regno];
 		}
-- 
1.9.3


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