https://gcc.gnu.org/g:a1de16a8e523de2ba928f7b5251059329eef0dc6

commit r16-5084-ga1de16a8e523de2ba928f7b5251059329eef0dc6
Author: Andrew Pinski <[email protected]>
Date:   Thu Nov 6 12:04:30 2025 -0800

    forwprop: Handle already true/false branchs in optimize_unreachable 
[PR122588]
    
    When optimize_unreachable was moved from fab to forwprop, I missed that due 
to
    the integrated copy prop, we might end up with an already true branch 
leading
    to a __builtin_unreachable block. optimize_unreachable would switch around
    the if and things go down hill from there since the other edge was already
    marked as non-executable, forwprop didn't process those blocks and didn't
    do copy prop into that block and the original assignment statement was 
removed.
    
    This fixes the problem by having optimize_unreachable not touch the if
    statement was already changed to true/false.
    
    Note I placed the testcase in gcc.c-torture/compile as gcc.dg/torture
    is NOT currently testing -Og (see PR 122450 for that).
    
    Changes since v1:
     * v2: Add gimple testcase.
    
    Bootstrapped and tested on x86_64-linux-gnu.
    
            PR tree-optimization/122588
    
    gcc/ChangeLog:
    
            * tree-ssa-forwprop.cc (optimize_unreachable): Don't touch
            if the condition was already true or false.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.c-torture/compile/pr122588-1.c: New test.
            * gcc.dg/tree-ssa/pr122588-1.c: New test.
    
    Signed-off-by: Andrew Pinski <[email protected]>

Diff:
---
 gcc/testsuite/gcc.c-torture/compile/pr122588-1.c | 25 ++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c       | 30 ++++++++++++++++++++++++
 gcc/tree-ssa-forwprop.cc                         |  7 +++++-
 3 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.c-torture/compile/pr122588-1.c 
b/gcc/testsuite/gcc.c-torture/compile/pr122588-1.c
new file mode 100644
index 000000000000..43ec621512c5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr122588-1.c
@@ -0,0 +1,25 @@
+/* Disable warnings about __sync_nand_and_fetch. */
+/* { dg-options "-w" } */
+/* PR tree-optimization/122588 */
+
+int i;
+char c;
+
+static inline __attribute__((__always_inline__))
+void foo0 (int a)
+{
+l5:
+  __sync_nand_and_fetch (&i, 0);
+  int x = __builtin_memcmp_eq (&a, 0, 4);
+  if (__builtin_iseqsig (x, 0.))
+    goto l5;
+  if (a)
+    __builtin_unreachable ();
+  c = a;
+}
+
+int
+main ()
+{
+  foo0 (1);
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c
new file mode 100644
index 000000000000..2c214c905765
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fgimple" } */
+/* PR tree-optimization/122588 */
+
+/* The removal of unreachable blocks should not
+   change blocks which have already become true/false.
+   The function below was is an example of that. And
+   forwprop does not go into non-executable blocks
+   so the statement `t = _1;` was still holding the
+   old reference.  */
+
+int t;
+
+__GIMPLE(ssa,startwith("forwprop4")) void g(void)
+{
+  int _1;
+  __BB(2):
+  _1 = 1;
+  if (_1 != 0)
+    goto __BB3;
+  else
+    goto __BB4;
+
+  __BB(3):
+  __builtin_unreachable ();
+
+  __BB(4):
+  t = _1;
+  return;
+}
diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index ae7f0e770ba2..9f8d4ad3b443 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -5080,7 +5080,12 @@ optimize_unreachable (basic_block bb)
       stmt = gsi_stmt (gsi);
       if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
        {
-         if (e->flags & EDGE_TRUE_VALUE)
+         /* If the condition is already true/false
+            ignore it. This can happen during copy prop of forwprop. */
+         if (gimple_cond_true_p (cond_stmt)
+             || gimple_cond_false_p (cond_stmt))
+           continue;
+         else if (e->flags & EDGE_TRUE_VALUE)
            gimple_cond_make_false (cond_stmt);
          else if (e->flags & EDGE_FALSE_VALUE)
            gimple_cond_make_true (cond_stmt);

Reply via email to