rtl-ssa uses degenerate phis to maintain an RPO list of accesses in which every use is of the RPO-previous definition. Thus, if it finds that a phi is always equal to a particular value V, it sometimes needs to keep the phi and make V the single input, rather than replace all uses of the phi with V.
The code to do that rerouted the phi's first input to the single value V. But as this PR shows, it failed to unlink the uses of the other inputs. The specific problem in the PR was that we had: x = PHI<x(a), V(b)> The code replaced the first input with V and removed the second input from the phi, but it didn't unlink the use of V associated with that second input. Bootstrapped & regression-tested on aarch64-linux-gnu. Also spot-checked on a riscv64-linux-gnu cross-compiler. OK to install? Richard gcc/ PR rtl-optimization/118562 * rtl-ssa/blocks.cc (function_info::replace_phi): When converting to a degenerate phi, make sure to remove all uses of the previous inputs. gcc/testsuite/ PR rtl-optimization/118562 * gcc.dg/torture/pr118562.c: New test. --- gcc/rtl-ssa/blocks.cc | 19 +++++++++++++++---- gcc/testsuite/gcc.dg/torture/pr118562.c | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr118562.c diff --git a/gcc/rtl-ssa/blocks.cc b/gcc/rtl-ssa/blocks.cc index e175f8ce460..953fd9e516e 100644 --- a/gcc/rtl-ssa/blocks.cc +++ b/gcc/rtl-ssa/blocks.cc @@ -424,14 +424,25 @@ function_info::replace_phi (phi_info *phi, set_info *new_value) { // We need to keep the phi around for its local uses. // Turn it into a degenerate phi, if it isn't already. - use_info *use = phi->input_use (0); - if (use->def () != new_value) - update_use (use); + use_info *single_use = nullptr; + for (auto *use : phi->inputs ()) + if (!single_use) + single_use = use; + else if (use->def () == new_value) + { + remove_use (single_use); + single_use = use; + } + else + remove_use (use); + + if (single_use->def () != new_value) + update_use (single_use); if (phi->is_degenerate ()) return; - phi->make_degenerate (use); + phi->make_degenerate (single_use); // Redirect all phi users to NEW_VALUE. while (use_info *phi_use = phi->last_phi_use ()) diff --git a/gcc/testsuite/gcc.dg/torture/pr118562.c b/gcc/testsuite/gcc.dg/torture/pr118562.c new file mode 100644 index 00000000000..82161e76015 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr118562.c @@ -0,0 +1,18 @@ +/* { dg-additional-options "-march=rv64gv -mabi=lp64" { target { rv64 } } } */ + +float b[2], c[2]; +void d(); +int h1(); +void e(float * __restrict h) { + int f; + for (int f = 0; f < 4; f++) { + if (h1()) + d(); + } + for (int g = 0; g < 4; g++) { + c[0] = h[0] - b[0]; + c[1] = h[1] - b[1]; + d(); + h += 1; + } +} -- 2.25.1