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

Reply via email to