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);
