[PATCH] combine: Delete EQ* notes when pseudo mode changes (PR60818)
Segher Boessenkool
segher@kernel.crashing.org
Fri Feb 19 09:45:00 GMT 2016
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
More information about the Gcc-patches
mailing list