https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118790
--- Comment #28 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
--- gcc/tree-ssa-live.cc.jj 2025-02-12 11:03:53.607556187 +0100
+++ gcc/tree-ssa-live.cc 2025-02-12 11:54:34.779131237 +0100
@@ -369,9 +369,17 @@ mark_all_vars_used_1 (tree *tp, int *wal
{
/* When a global var becomes used for the first time also walk its
initializer (non global ones don't have any). */
- if (set_is_used (t) && is_global_var (t)
- && DECL_CONTEXT (t) == current_function_decl)
- mark_all_vars_used (&DECL_INITIAL (t));
+ if (set_is_used (t))
+ {
+ if (is_global_var (t)
+ && DECL_CONTEXT (t) == current_function_decl)
+ mark_all_vars_used (&DECL_INITIAL (t));
+ if (DECL_HAS_VALUE_EXPR_P (t))
+ {
+ tree dve = DECL_VALUE_EXPR (t);
+ mark_all_vars_used (&dve);
+ }
+ }
}
/* remove_unused_scope_block_p requires information about labels
which are not DECL_IGNORED_P to tell if they might be used in the IL. */
@@ -389,7 +397,9 @@ mark_all_vars_used_1 (tree *tp, int *wal
}
/* Mark the scope block SCOPE and its subblocks unused when they can be
- possibly eliminated if dead. */
+ possibly eliminated if dead. Also, as remove_unused_scope_block_p is going
+ to keep all BLOCK_VARS VAR_DECLs with DECL_HAS_VALUE_EXPR_P, mark all vars
+ their DECL_VALUE_EXPR refers to. */
static void
mark_scope_block_unused (tree scope)
@@ -398,6 +408,12 @@ mark_scope_block_unused (tree scope)
TREE_USED (scope) = false;
if (!(*debug_hooks->ignore_block) (scope))
TREE_USED (scope) = true;
+ for (t = BLOCK_VARS (scope); t; t = DECL_CHAIN (t))
+ if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t))
+ {
+ tree dve = DECL_VALUE_EXPR (t);
+ mark_all_vars_used (&dve);
+ }
for (t = BLOCK_SUBBLOCKS (scope); t ; t = BLOCK_CHAIN (t))
mark_scope_block_unused (t);
}
@@ -792,9 +808,10 @@ remove_unused_locals (void)
timevar_push (TV_REMOVE_UNUSED);
+ usedvars = BITMAP_ALLOC (NULL);
+
mark_scope_block_unused (DECL_INITIAL (current_function_decl));
- usedvars = BITMAP_ALLOC (NULL);
auto_bitmap useddebug;
/* Walk the CFG marking all referenced symbols. */
@@ -819,7 +836,7 @@ remove_unused_locals (void)
{
if (gimple_debug_bind_p (stmt))
{
- tree var = gimple_debug_bind_get_var (stmt);
+ tree var = gimple_debug_bind_get_var (stmt);
if (VAR_P (var))
{
if (!gimple_debug_bind_get_value (stmt))
preserves it in local_decls where it was earlier removed.
This keeps DECL_VALUE_EXPR (id_string.55) working until the expand pass.
That throws the VAR_DECL from local_decls again in expand_used_vars, e.g.
expand_one_var doesn't do anything for DECL_HAS_VALUE_EXPR_P VAR_DECLs.
And then instantiate_decls even vec_frees the whole cfun->local_decls (though
by that time DECL_VALUE_EXPR (id_string.55) has been garbage collected already.
So perhaps instead we want to move such vars from local_decls to BLOCK_VARS of
the outermost block or something? But how to find out if it wasn't there
already?
Note, normally these VLA addresses don't have DECL_VALUE_EXPR and so are
usually used in the IL. It is just that tree-nested.cc in this case added
DECL_VALUE_EXPR on those because they are (or were) referenced from nested
function.