On Thu, Jan 23, 2025 at 2:05 PM Richard Sandiford <richard.sandif...@arm.com> wrote: > > 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?
OK. Richard. > 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 >