aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2024-08-15 16:54:02 +0100
committerRichard Sandiford <richard.sandiford@arm.com>2024-08-15 16:54:02 +0100
commit70ae0daeb76f28a3135f4a74d6e440fb1d9821fa (patch)
tree144403e8da4f7b75f8d8c09f27117a65db9b8a10
parentdbf4c574b92bc692a0380a2b5ee25028321e735f (diff)
downloadgcc-70ae0daeb76f28a3135f4a74d6e440fb1d9821fa.zip
gcc-70ae0daeb76f28a3135f4a74d6e440fb1d9821fa.tar.gz
gcc-70ae0daeb76f28a3135f4a74d6e440fb1d9821fa.tar.bz2
late-combine: Preserve INSN_CODE when modifying notes [PR116343]
When it removes a definition, late-combine tries to update all uses in notes. It does this using the same insn_propagation class that it uses for patterns. However, insn_propagation uses validate_change, which in turn resets the INSN_CODE. This is inefficient in the best case, since it forces the pattern to be rerecognised even though changing a note can't affect the INSN_CODE. But in the PR it's a correctness problem: resetting INSN_CODE means we lose the NOOP_INSN_MOVE_CODE, which in turn means that rtl-ssa doesn't queue it for deletion. This patch adds a routine specifically for propagating into notes. A belt-and-braces fix would be to rerecognise noop moves in function_info::change_insns, but I can't think of a good reason why that would be necessary, and it could paper over latent bugs. gcc/ PR testsuite/116343 * recog.h (insn_propagation::apply_to_note): Declare. * recog.cc (insn_propagation::apply_to_note): New function. * late-combine.cc (insn_combination::substitute_note): Use apply_to_note instead of apply_to_rvalue. * rtl-ssa/changes.cc (rtl_ssa::changes_are_worthwhile): Improve dumping of costs for noop moves. gcc/testsuite/ PR testsuite/116343 * gcc.dg/torture/pr116343.c: New test.
-rw-r--r--gcc/late-combine.cc2
-rw-r--r--gcc/recog.cc13
-rw-r--r--gcc/recog.h1
-rw-r--r--gcc/rtl-ssa/changes.cc5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr116343.c18
5 files changed, 37 insertions, 2 deletions
diff --git a/gcc/late-combine.cc b/gcc/late-combine.cc
index 2b62e29..1d81b38 100644
--- a/gcc/late-combine.cc
+++ b/gcc/late-combine.cc
@@ -338,7 +338,7 @@ insn_combination::substitute_note (insn_info *use_insn, rtx note,
|| REG_NOTE_KIND (note) == REG_EQUIV)
{
insn_propagation prop (use_insn->rtl (), m_dest, m_src);
- return (prop.apply_to_rvalue (&XEXP (note, 0))
+ return (prop.apply_to_note (&XEXP (note, 0))
&& (can_propagate || prop.num_replacements == 0));
}
return true;
diff --git a/gcc/recog.cc b/gcc/recog.cc
index 23e4820..615aaab 100644
--- a/gcc/recog.cc
+++ b/gcc/recog.cc
@@ -1469,6 +1469,19 @@ insn_propagation::apply_to_rvalue (rtx *loc)
return res;
}
+/* Like apply_to_rvalue, but specifically for the case where *LOC is in
+ a note. This never changes the INSN_CODE. */
+
+bool
+insn_propagation::apply_to_note (rtx *loc)
+{
+ auto old_code = INSN_CODE (insn);
+ bool res = apply_to_rvalue (loc);
+ if (INSN_CODE (insn) != old_code)
+ INSN_CODE (insn) = old_code;
+ return res;
+}
+
/* Check whether INSN matches a specific alternative of an .md pattern. */
bool
diff --git a/gcc/recog.h b/gcc/recog.h
index 87a5803..1dccce7 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -121,6 +121,7 @@ public:
insn_propagation (rtx_insn *, rtx, rtx, bool = true);
bool apply_to_pattern (rtx *);
bool apply_to_rvalue (rtx *);
+ bool apply_to_note (rtx *);
/* Return true if we should accept a substitution into the address of
memory expression MEM. Undoing changes OLD_NUM_CHANGES and up restores
diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index a30f000..0476296 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -228,7 +228,10 @@ rtl_ssa::changes_are_worthwhile (array_slice<insn_change *const> changes,
for (const insn_change *change : changes)
if (!change->is_deletion ())
{
- fprintf (dump_file, " %c %d", sep, change->new_cost);
+ if (INSN_CODE (change->rtl ()) == NOOP_MOVE_INSN_CODE)
+ fprintf (dump_file, " %c nop", sep);
+ else
+ fprintf (dump_file, " %c %d", sep, change->new_cost);
sep = '+';
}
if (weighted_new_cost != 0)
diff --git a/gcc/testsuite/gcc.dg/torture/pr116343.c b/gcc/testsuite/gcc.dg/torture/pr116343.c
new file mode 100644
index 0000000..ad13f0f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr116343.c
@@ -0,0 +1,18 @@
+// { dg-additional-options "-fschedule-insns -fno-thread-jumps -fno-dce" }
+
+int a, b, c;
+volatile int d;
+int e(int f, int g) { return g > 1 ? 1 : f >> g; }
+int main() {
+ int *i = &a;
+ long j[1];
+ if (a)
+ while (1) {
+ a ^= 1;
+ if (*i)
+ while (1)
+ ;
+ b = c && e((d, 1) >= 1, j[0]);
+ }
+ return 0;
+}