]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rtl-ssa: Avoid dangling phi uses [PR118562]
authorRichard Sandiford <richard.sandiford@arm.com>
Thu, 23 Jan 2025 13:57:02 +0000 (13:57 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Thu, 23 Jan 2025 13:57:02 +0000 (13:57 +0000)
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.

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
gcc/testsuite/gcc.dg/torture/pr118562.c [new file with mode: 0644]

index e175f8ce46054ea1a45efb037446e420cdd52338..953fd9e516ed60e3970592c2bf9693fdc4c12132 100644 (file)
@@ -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 (file)
index 0000000..82161e7
--- /dev/null
@@ -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;
+  }
+}