https://gcc.gnu.org/g:9e7c7e567704bd12d65b01246a655d8628bb521d

commit r13-9683-g9e7c7e567704bd12d65b01246a655d8628bb521d
Author: Richard Biener <rguent...@suse.de>
Date:   Mon Feb 17 15:53:11 2025 +0100

    tree-optimization/98845 - ICE with tail-merging and DCE/DSE disabled
    
    The following shows that tail-merging will make dead SSA defs live
    in paths where it wasn't before, possibly introducing UB or as
    in this case, uses of abnormals that eventually fail coalescing
    later.  The fix is to register such defs for stmt comparison.
    
            PR tree-optimization/98845
            * tree-ssa-tail-merge.cc (stmt_local_def): Consider a
            def with no uses not local.
    
            * gcc.dg/pr98845.c: New testcase.
            * gcc.dg/pr81192.c: Adjust.
    
    (cherry picked from commit 6b8a8c9fd68c5dabaec5ddbc25efeade44f37a14)

Diff:
---
 gcc/testsuite/gcc.dg/pr81192.c | 68 ++++++++++++++++++++++++++++++++++++------
 gcc/testsuite/gcc.dg/pr98845.c | 33 ++++++++++++++++++++
 gcc/tree-ssa-tail-merge.cc     |  8 +++++
 3 files changed, 100 insertions(+), 9 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/pr81192.c b/gcc/testsuite/gcc.dg/pr81192.c
index 6cab60565585..87a7a7a19c80 100644
--- a/gcc/testsuite/gcc.dg/pr81192.c
+++ b/gcc/testsuite/gcc.dg/pr81192.c
@@ -1,5 +1,62 @@
-/* { dg-options "-Os -fdump-tree-pre-details -fdisable-tree-evrp 
-fno-tree-dse" } */
+/* { dg-options "-Os -fgimple -fdump-tree-pre-details -fdisable-tree-evrp 
-fno-tree-dse" } */
 
+#if __SIZEOF_INT__ == 2
+#define unsigned __UINT32_TYPE__
+#define int __INT32_TYPE__
+#endif
+
+unsigned a;
+int b, c;
+
+void __GIMPLE(ssa, startwith("pre")) fn2   ()
+{
+  int b_lsm6;
+  int j;
+  int c0_1;
+  int iftmp2_8;
+
+  __BB(2):
+  a = _Literal (unsigned)30;
+  c0_1 = c;
+  b_lsm6_9 = b;
+  goto __BB7;
+
+  __BB(3):
+  if (j_6(D) != _Literal (int)2147483647)
+    goto __BB4;
+  else
+    goto __BB9;
+
+  __BB(4):
+  iftmp2_8 = j_6(D) + _Literal (int)1;
+  goto __BB5;
+
+  __BB(9):
+  iftmp2_8 = j_6(D) + _Literal (int)1;
+  goto __BB5;
+
+  __BB(5):
+  b_lsm6_10 = _Literal (int)2147483647;
+  goto __BB6;
+
+  __BB(6):
+  if (c0_1 != _Literal (int) 0)
+    goto __BB3;
+  else
+    goto __BB8;
+
+  __BB(8):
+  goto __BB7;
+
+  __BB(7):
+  goto __BB6;
+
+}
+
+#if 0
+/* This used to be a C based testcase but ccp3 would now would remove
+   the setting of iftmp2_8 (in the above gimple) which would cause PRE
+   not to test what PRE was doing incorrectly. The original code is below. */
 /* Disable tree-evrp because the new version of evrp sees
 <bb 3> :
   if (j_8(D) != 2147483647)
@@ -18,14 +75,6 @@ which causes the situation being tested to dissapear before 
we get to PRE.  */
 
 /* Likewise disable DSE which also elides the tail merging "opportunity".  */
 
-#if __SIZEOF_INT__ == 2
-#define unsigned __UINT32_TYPE__
-#define int __INT32_TYPE__
-#endif
-
-unsigned a;
-int b, c;
-
 static int
 fn1 (int p1, int p2)
 {
@@ -41,5 +90,6 @@ fn2 (void)
     for (; c; b = fn1 (j, 1))
       ;
 }
+#endif
 
 /* { dg-final { scan-tree-dump-times "(?n)find_duplicates: <bb .*> duplicate 
of <bb .*>" 1 "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/pr98845.c b/gcc/testsuite/gcc.dg/pr98845.c
new file mode 100644
index 000000000000..074c979678f9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr98845.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-dce -fno-tree-dse" } */
+
+int n;
+
+__attribute__ ((returns_twice)) void
+foo (void);
+
+void
+bar (void);
+
+void
+quux (int x)
+{
+  if (x)
+    ++x;
+  else
+    {
+      if (n)
+        {
+          x = 1;
+          foo ();
+        }
+      else
+        bar ();
+
+      if (n)
+        {
+          ++x;
+          ++n;
+        }
+    }
+}
diff --git a/gcc/tree-ssa-tail-merge.cc b/gcc/tree-ssa-tail-merge.cc
index 33acb649d5d6..a94108da9f48 100644
--- a/gcc/tree-ssa-tail-merge.cc
+++ b/gcc/tree-ssa-tail-merge.cc
@@ -336,10 +336,13 @@ stmt_local_def (gimple *stmt)
 
   def_bb = gimple_bb (stmt);
 
+  bool any_use = false;
   FOR_EACH_IMM_USE_FAST (use_p, iter, val)
     {
       if (is_gimple_debug (USE_STMT (use_p)))
        continue;
+
+      any_use = true;
       bb = gimple_bb (USE_STMT (use_p));
       if (bb == def_bb)
        continue;
@@ -351,6 +354,11 @@ stmt_local_def (gimple *stmt)
       return false;
     }
 
+  /* When there is no use avoid making the stmt live on other paths.
+     This can happen with DCE disabled or not done as seen in PR98845.  */
+  if (!any_use)
+    return false;
+
   return true;
 }

Reply via email to