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 <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to