https://gcc.gnu.org/g:0d34e73b71ce199f52de227c4101256484feaa78
commit r16-3331-g0d34e73b71ce199f52de227c4101256484feaa78 Author: Richard Sandiford <richard.sandif...@arm.com> Date: Thu Aug 21 16:16:02 2025 +0100 rtl-ssa: Add missing live-out uses [PR121619] This PR is another bug in the rtl-ssa code to manage live-out uses. It seems that this didn't get much coverage until recently. In the testcase, late-combine first removed a register-to-register move by substituting into all uses, some of which were in other EBBs. This was done after checking make_uses_available, which (as expected) says that single dominating definitions are available everywhere that the definition dominates. But the update failed to add appropriate live-out uses, so a later parallelisation attempt tried to move the new destination into a later block. gcc/ PR rtl-optimization/121619 * rtl-ssa/functions.h (function_info::commit_make_use_available): Declare. * rtl-ssa/blocks.cc (function_info::commit_make_use_available): New function. * rtl-ssa/changes.cc (function_info::apply_changes_to_insn): Use it. gcc/testsuite/ PR rtl-optimization/121619 * gcc.dg/pr121619.c: New test. Diff: --- gcc/rtl-ssa/blocks.cc | 35 +++++++++++++++++++++++++++++++++++ gcc/rtl-ssa/changes.cc | 6 +++++- gcc/rtl-ssa/functions.h | 1 + gcc/testsuite/gcc.dg/pr121619.c | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/gcc/rtl-ssa/blocks.cc b/gcc/rtl-ssa/blocks.cc index a57b9e15f13c..568f96585402 100644 --- a/gcc/rtl-ssa/blocks.cc +++ b/gcc/rtl-ssa/blocks.cc @@ -359,6 +359,41 @@ function_info::live_out_value (bb_info *bb, set_info *set) return set; } +// Make USE's definition available at USE, if it isn't already. Assume that +// the caller has properly used make_use_available to check that this is +// possible. +void +function_info::commit_make_use_available (use_info *use) +{ + // We only need to handle single dominating definitions here. + // Other cases are handled by degenerate phis, with create_degenerate_phi + // creating any necessary live-out uses. + set_info *def = use->def (); + if (def + && use->is_reg () + && is_single_dominating_def (def) + && use->ebb () != def->ebb ()) + { + // If USE's EBB has DEF's EBB as its single predecessor, it's enough + // to add a live-out use to the former's predecessor block. Otherwise, + // conservatively add a live-out use at the end of DEF's block, so that + // DEF cannot move further down. Doing a minimal yet accurate update + // would be an O(n.log(n)) operation in the worst case. + auto ebb_cfg_bb = def->ebb ()->first_bb ()->cfg_bb (); + if (single_pred_p (ebb_cfg_bb)) + { + bb_info *pred_bb = this->bb (single_pred (ebb_cfg_bb)); + if (pred_bb->ebb () == def->ebb ()) + { + add_live_out_use (pred_bb, def); + return; + } + } + add_live_out_use (def->bb (), def); + return; + } +} + // Add PHI to EBB and enter it into the function's hash table. void function_info::append_phi (ebb_info *ebb, phi_info *phi) diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc index 00e6c3185644..f2fc9826c4f1 100644 --- a/gcc/rtl-ssa/changes.cc +++ b/gcc/rtl-ssa/changes.cc @@ -713,7 +713,11 @@ function_info::apply_changes_to_insn (insn_change &change, // Add all uses, now that their position is final. for (use_info *use : change.new_uses) - add_use (use); + { + if (use->def ()) + commit_make_use_available (use); + add_use (use); + } // Copy the uses and definitions. unsigned int num_defs = change.new_defs.size (); diff --git a/gcc/rtl-ssa/functions.h b/gcc/rtl-ssa/functions.h index 27cbc18178a7..ba805072ba4f 100644 --- a/gcc/rtl-ssa/functions.h +++ b/gcc/rtl-ssa/functions.h @@ -309,6 +309,7 @@ private: void add_live_out_use (bb_info *, set_info *); set_info *live_out_value (bb_info *, set_info *); + void commit_make_use_available (use_info *); void append_phi (ebb_info *, phi_info *); void remove_phi (phi_info *); diff --git a/gcc/testsuite/gcc.dg/pr121619.c b/gcc/testsuite/gcc.dg/pr121619.c new file mode 100644 index 000000000000..a63896d244af --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr121619.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -fno-gcse -fno-tree-ter -fno-guess-branch-probability -fno-forward-propagate" } */ + +int printf(const char *, ...); +long a, c, d; +char b; +int main() { +f : { + short g = 100; + int h = 1; + while (1) { + char i = 0; + if (a) + i = h = -b; + short j = g; + c = h ^ g; + g = ~(-h / c + 1); + if (b > 6) { + a = g && -1; + goto f; + } + if (j < 100) + printf("%ld\n", d); + if (g - 1) + break; + b = i; + } + int k = 2L % g; + if (k) + goto f; + } + return 0; +}