On Sun, 13 Oct 2024, Richard Biener wrote:
> 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.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu, OK?
I've applied this now, cleaning is required unless the DECL_VALUE_EXPR
itself shouldn't be there in which case it is harmless in general.
We do stream DECL_VALUE_EXPR to LTO so some are definitely expected.
Richard.
> Thanks,
> Richard.
>
> PR tree-optimization/116907
> * tree-ssa-live.cc (clear_unused_block_pointer_in_block): New
> helper.
> (clear_unused_block_pointer): Call it.
> ---
> 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 0739faa022e..484698899cf 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
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)