[gcc r16-9412] tree-cfgcleanup: Don't remove forwarder blocks (with phis) with phis that have abnormal uses [PR1253

Andrea Pinski via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:6933427282a2f1a22d0e967e16f41b419f83c11e

commit r16-9412-g6933427282a2f1a22d0e967e16f41b419f83c11e
Author: Andrew Pinski <[email protected]>
Date:   Wed May 20 13:20:15 2026 -0700

    tree-cfgcleanup: Don't remove forwarder blocks (with phis) with phis that have abnormal uses [PR125396]
    
    This was a latent bug in the checks for removing of a forwarder block which has a phi.
    
    Take:
          <bb 15> [local count: 182536112]:
          # arr1$0_32 = PHI <arr1$0_36(ab)(11)>
    
          <bb 14> [local count: 206998870]:
          # arr1$0_43(ab) = PHI <arr1$0_25(ab)(13), 9(15)>
          # sj12_44(ab) = PHI <sj12_31(ab)(13), arr1$0_32(15)>
          f8 ();
    
    Here bb 15 predecessor is a normal edge.
    So when merging the forwarder bb 15 into bb14 we end up with:
          <bb 12> [local count: 206998870]:
          # arr1$0_42(ab) = PHI <arr1$0_24(ab)(11), 9(9)>
          # sj12_43(ab) = PHI <sj12_30(ab)(11), arr1$0_35(ab)(9)>
          f8 ();
    and now there is an overlap of live range of arr1$0_35 and arr1$0_42.
    So we need to reject the case where we have phis and the phi arguments that
    use abnormal uses.
    
    Changes since v1:
    * v2: Look at phi arguments of the forwarder block rather than the dest bb
          having an abnormal edge out.
    * v3: Fix bb_phis_references_abnormal_uses to use the gimple_phi_num_args to
          search over the phi arguments. Also fix the commit message which was wrong.
    
    Bootstrapped and tested on x86_64-linux-gnu.
    
            PR tree-optimization/125396
    
    gcc/ChangeLog:
    
            * tree-cfgcleanup.cc (bb_phis_references_abnormal_uses): New function.
            (maybe_remove_forwarder_block): Check to make sure the
            forwarder block does not have a phi that references ssa name that has
            abnormal uses.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/torture/pr125396-1.c: New test.
    
    Signed-off-by: Andrew Pinski <[email protected]>
    (cherry picked from commit ec79b0779b6eeb9ef3b8a45f46a596cbb75a7844)

Diff:
---
 gcc/testsuite/gcc.dg/torture/pr125396-1.c | 38 +++++++++++++++++++++++++++++++
 gcc/tree-cfgcleanup.cc                    | 27 ++++++++++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/torture/pr125396-1.c b/gcc/testsuite/gcc.dg/torture/pr125396-1.c
new file mode 100644
index 000000000000..b0557d2f03f0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr125396-1.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* PR tree-optimization/125396 */
+
+
+char g7;
+int g13, g26;
+int g() __attribute__((returns_twice));
+void f8()
+{
+    int arr1[2];
+    int c2, c4;
+    char v6;
+    int sj12;
+    int sj14;
+lbl_br1:
+    if (g13) goto lbl_br3;
+    if (c4)
+    {
+        c4 = 0;
+        goto lbl_br6;
+    }
+    switch (v6)
+    case 1:
+        c4 = 1;
+    sj14 = g();
+    g13 = sj12;
+lbl_br3:
+    arr1[0] = 0;
+    sj12 = g();
+    c2 = g7;
+    g26 = 5;
+    if (c2) __builtin_unreachable();
+lbl_br6:
+    sj12 = arr1[0];
+    arr1[0] = 9;
+    if (g26) f8();
+    goto lbl_br1;
+}
diff --git a/gcc/tree-cfgcleanup.cc b/gcc/tree-cfgcleanup.cc
index 6f0ae0b08de7..7fe2b7ad5cbb 100644
--- a/gcc/tree-cfgcleanup.cc
+++ b/gcc/tree-cfgcleanup.cc
@@ -464,6 +464,28 @@ move_debug_stmts_from_forwarder (basic_block src,
     }
 }
 
+/* Returns true if a phi of the basic block BB has an
+   use of a ssa name that is used in an abnormal edge.  */
+
+static bool
+bb_phis_references_abnormal_uses (basic_block bb)
+{
+  auto phis = phi_nodes (bb);
+  gimple_stmt_iterator i;
+  for (i = gsi_start (phis); !gsi_end_p (i); gsi_next (&i))
+    {
+      gphi *phi = as_a<gphi*>(*i);
+      for (unsigned indx = 0; indx < gimple_phi_num_args (phi); indx++)
+	{
+	  tree value = gimple_phi_arg_def (phi, indx);
+	  if (TREE_CODE (value) == SSA_NAME
+	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (value))
+	    return true;
+	}
+    }
+  return false;
+}
+
 /* Return true if basic block BB does nothing except pass control
    flow to another block and that we can safely insert a label at
    the start of the successor block and was removed.
@@ -550,6 +572,11 @@ maybe_remove_forwarder_block (basic_block bb, bool can_split = false)
   if (has_phi && gimple_seq_empty_p (phi_nodes (dest)))
     return false;
 
+  /* When we have phi, make sure the phi does not have any uses of
+     names used in abnormal phis.  */
+  if (has_phi && bb_phis_references_abnormal_uses (bb))
+    return false;
+
   /* Now walk through the statements backward.  We can ignore labels,
      anything else means this is not a forwarder block.  */
   for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.