https://gcc.gnu.org/g:735eb662ba370ff8740ec3819ec363bda3d83d77

commit r16-5410-g735eb662ba370ff8740ec3819ec363bda3d83d77
Author: Jakub Jelinek <[email protected]>
Date:   Wed Nov 19 09:36:51 2025 +0100

    tree-ssa-live: Fix .DEFERRED_INIT handling [PR122184]
    
    remove_unused_locals ignores clobbers in the initial phase (and
    some debug stmts) and this has been copied for .DEFERRED_INIT
    as well:
              if (gimple_clobber_p (stmt))
                {
                  have_local_clobbers = true;
                  continue;
                }
    
              if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
                {
                  have_local_clobbers = true;
                  continue;
                }
    This is so that the second phase can then drop clobbers that
    clobber unused local vars and ditto for .DEFERRED_INIT.
    Except, for clobbers it does
                    /* Remove clobbers referencing unused vars, or clobbers
                       with MEM_REF lhs referencing uninitialized pointers.  */
                    if ((VAR_P (base) && !is_used_p (base))
                        || (TREE_CODE (lhs) == MEM_REF
                            && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME
                            && SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (lhs, 0))
                            && (TREE_CODE (SSA_NAME_VAR (TREE_OPERAND (lhs, 0)))
                                != PARM_DECL)))
    so handles both the var = {CLOBBER}; case where var is unused local,
    or *SSA_NAME = {CLOBBER} where SSA_NAME is default definition of
    non-PARM_DECL, but for .DEFERRED_INIT it doesn't:
                    if (DECL_P (base) && !is_used_p (base))
    On the following case, we have *SSA_NAME(D) = .DEFERRED_INIT (...);
    and because of the former we don't mark the SSA_NAME as used and
    because of the latter we keep the .DEFERRED_INIT call, so the SSA_NAME
    is freed and later on we ICE because the SSA_NAME in the freelist doesn't
    have SSA_NAME_DEF_STMT.
    
    The following patch fixes it by handling .DEFERRED_INIT like clobbers
    and dropping them also when it has a MEM_REF with default definition
    of SSA_NAME for non-PARM_DECL on the lhs.
    
    2025-11-19  Jakub Jelinek  <[email protected]>
    
            PR tree-optimization/122184
            * tree-ssa-live.cc (remove_unused_locals): Drop .DEFERRED_INIT
            calls with MEM_REF lhs based on uninitialized SSA_NAME.
    
            * g++.dg/opt/pr122184-1.C: New test.
            * g++.dg/opt/pr122184-2.C: New test.

Diff:
---
 gcc/testsuite/g++.dg/opt/pr122184-1.C | 12 ++++++++++++
 gcc/testsuite/g++.dg/opt/pr122184-2.C | 12 ++++++++++++
 gcc/tree-ssa-live.cc                  |  7 ++++++-
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/g++.dg/opt/pr122184-1.C 
b/gcc/testsuite/g++.dg/opt/pr122184-1.C
new file mode 100644
index 000000000000..50f8639f6fd9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr122184-1.C
@@ -0,0 +1,12 @@
+// PR tree-optimization/122184
+// { dg-do compile }
+// { dg-require-stack-check "generic" }
+// { dg-options "-O2 -fstack-check=generic" }
+
+void
+foo ()
+{
+  goto fail;
+  char var[41];
+fail:;
+}
diff --git a/gcc/testsuite/g++.dg/opt/pr122184-2.C 
b/gcc/testsuite/g++.dg/opt/pr122184-2.C
new file mode 100644
index 000000000000..b5dd6fcbd3b1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr122184-2.C
@@ -0,0 +1,12 @@
+// PR tree-optimization/122184
+// { dg-do compile }
+// { dg-require-stack-check "generic" }
+// { dg-options "-O2 -fstack-check=generic -ftrivial-auto-var-init=zero" }
+
+void
+foo ()
+{
+  goto fail;
+  char var[41];
+fail:;
+}
diff --git a/gcc/tree-ssa-live.cc b/gcc/tree-ssa-live.cc
index 5e0891361dc7..46543a1c865b 100644
--- a/gcc/tree-ssa-live.cc
+++ b/gcc/tree-ssa-live.cc
@@ -926,7 +926,12 @@ remove_unused_locals (void)
              {
                tree lhs = gimple_call_lhs (stmt);
                tree base = get_base_address (lhs);
-               if (DECL_P (base) && !is_used_p (base))
+               if ((DECL_P (base) && !is_used_p (base))
+                   || (TREE_CODE (lhs) == MEM_REF
+                       && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME
+                       && SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (lhs, 0))
+                       && (TREE_CODE (SSA_NAME_VAR (TREE_OPERAND (lhs, 0)))
+                           != PARM_DECL)))
                  {
                    unlink_stmt_vdef (stmt);
                    gsi_remove (&gsi, true);

Reply via email to