https://gcc.gnu.org/g:7d15248d41dc45a4ba2d38ff532b672a5c0651d0

commit r15-4355-g7d15248d41dc45a4ba2d38ff532b672a5c0651d0
Author: Richard Biener <rguent...@suse.de>
Date:   Sun Oct 13 12:44:04 2024 +0200

    tree-optimization/116907 - stale BLOCK reference from DECL_VALUE_EXPR
    
    When we remove unused BLOCKs we fail to clean references to them
    from DECL_VALUE_EXPRs of variables in other BLOCKs which in the
    PR causes LTO streaming to walk into pointers to GGC freed blocks.
    
    There's the question of whether such DECL_VALUE_EXPRs should keep
    variables and blocks referenced live (it doesn't seem to do that)
    and whether such DECL_VALUE_EXPRs should have survived in the
    first place.
    
            PR tree-optimization/116907
            * tree-ssa-live.cc (clear_unused_block_pointer_in_block): New
            helper.
            (clear_unused_block_pointer): Call it.

Diff:
---
 gcc/tree-ssa-live.cc | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/gcc/tree-ssa-live.cc b/gcc/tree-ssa-live.cc
index 0739faa022ef..484698899cfe 100644
--- a/gcc/tree-ssa-live.cc
+++ b/gcc/tree-ssa-live.cc
@@ -612,6 +612,22 @@ clear_unused_block_pointer_1 (tree *tp, int *, void *)
   return NULL_TREE;
 }
 
+/* Clear references to unused BLOCKs from DECL_VALUE_EXPRs of variables
+   in BLOCK.  */
+
+static void
+clear_unused_block_pointer_in_block (tree block)
+{
+  for (tree t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
+    if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t))
+      {
+       tree val = DECL_VALUE_EXPR (t);
+       walk_tree (&val, clear_unused_block_pointer_1, NULL, NULL);
+      }
+  for (tree t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
+    clear_unused_block_pointer_in_block (t);
+}
+
 /* Set all block pointer in debug or clobber stmt to NULL if the block
    is unused, so that they will not be streamed out.  */
 
@@ -667,6 +683,10 @@ clear_unused_block_pointer (void)
          walk_tree (gimple_op_ptr (stmt, i), clear_unused_block_pointer_1,
                     NULL, NULL);
       }
+
+  /* Walk all variables mentioned in the functions BLOCK tree and clear
+     DECL_VALUE_EXPR from unused blocks where present.  */
+  clear_unused_block_pointer_in_block (DECL_INITIAL (current_function_decl));
 }
 
 /* Dump scope blocks starting at SCOPE to FILE.  INDENT is the

Reply via email to