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.

Reply via email to