diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2024-08-15 16:54:02 +0100 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2024-08-15 16:54:02 +0100 |
commit | 70ae0daeb76f28a3135f4a74d6e440fb1d9821fa (patch) | |
tree | 144403e8da4f7b75f8d8c09f27117a65db9b8a10 | |
parent | dbf4c574b92bc692a0380a2b5ee25028321e735f (diff) | |
download | gcc-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.cc | 2 | ||||
-rw-r--r-- | gcc/recog.cc | 13 | ||||
-rw-r--r-- | gcc/recog.h | 1 | ||||
-rw-r--r-- | gcc/rtl-ssa/changes.cc | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr116343.c | 18 |
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; +} |