On Tue, Dec 12, 2017 at 12:54:13AM -0200, Alexandre Oliva wrote:
> +/* Check whether BLOCK, a lexical block, is nested within OUTER, or is
> + OUTER itself. If BOTHWAYS, check not only that BLOCK can reach
> + OUTER through BLOCK_SUPERCONTEXT links, but also that there is a
> + path from OUTER to BLOCK through BLOCK_SUBBLOCKs and
> + BLOCK_FRAGMENT_ORIGIN links. */
> +static bool
> +block_within_block_p (tree block, tree outer, bool bothways)
> +{
> + if (block == outer)
> + return true;
> +
> + /* Quickly check that OUTER is up BLOCK's supercontext chain. */
> + for (tree context = BLOCK_SUPERCONTEXT (block);
> + context != outer;
> + context = BLOCK_SUPERCONTEXT (context))
> + if (!context || TREE_CODE (context) != BLOCK)
> + return false;
> +
> + if (!bothways)
> + return true;
> +
> + /* Now check that each block is actually referenced by its
> + parent. */
> + for (tree context = BLOCK_SUPERCONTEXT (block); ;
> + context = BLOCK_SUPERCONTEXT (context))
> + {
> + if (BLOCK_FRAGMENT_ORIGIN (context))
> + {
> + gcc_assert (!BLOCK_SUBBLOCKS (context));
> + context = BLOCK_FRAGMENT_ORIGIN (context);
> + }
> + for (tree sub = BLOCK_SUBBLOCKS (context);
> + sub != block;
> + sub = BLOCK_CHAIN (sub))
> + if (!sub)
> + return false;
> + if (context == outer)
> + return true;
> + else
> + block = context;
> + }
> +}
> +
> +/* Called during final while assembling the marker of the entry point
> + for an inlined function. */
> +
> +static void
> +dwarf2out_inline_entry (tree block)
> +{
> + gcc_assert (DECL_P (block_ultimate_origin (block)));
> +
> + /* Sanity check the block tree. This would catch a case in which
> + BLOCK got removed from the tree reachable from the outermost
> + lexical block, but got retained in markers. It would still link
> + back to its parents, but some ancestor would be missing a link
> + down the path to the sub BLOCK. If the block got removed, its
> + BLOCK_NUMBER will not be a usable value. */
> + gcc_checking_assert (block_within_block_p (block,
> + DECL_INITIAL
> + (current_function_decl),
> + true));
I think this asks for
if (flag_checking)
gcc_assert (block_within_block_p (block,
DECL_INITIAL (current_function_decl),
true));
> --- a/gcc/tree-ssa-live.c
> +++ b/gcc/tree-ssa-live.c
> @@ -520,6 +520,11 @@ remove_unused_scope_block_p (tree scope, bool
> in_ctor_dtor_block)
> else if (!BLOCK_SUPERCONTEXT (scope)
> || TREE_CODE (BLOCK_SUPERCONTEXT (scope)) == FUNCTION_DECL)
> unused = false;
> + /* Preserve the block, it is referenced by at least the inline
> + entry point marker. */
> + else if (debug_nonbind_markers_p
> + && inlined_function_outer_scope_p (scope))
> + unused = false;
> /* Innermost blocks with no live variables nor statements can be always
> eliminated. */
> else if (!nsubblocks)
> @@ -548,11 +553,13 @@ remove_unused_scope_block_p (tree scope, bool
> in_ctor_dtor_block)
> }
> else if (BLOCK_VARS (scope) || BLOCK_NUM_NONLOCALIZED_VARS (scope))
> unused = false;
> - /* See if this block is important for representation of inlined function.
> - Inlined functions are always represented by block with
> - block_ultimate_origin being set to FUNCTION_DECL and
> DECL_SOURCE_LOCATION
> - set... */
> - else if (inlined_function_outer_scope_p (scope))
> + /* See if this block is important for representation of inlined
> + function. Inlined functions are always represented by block
> + with block_ultimate_origin being set to FUNCTION_DECL and
> + DECL_SOURCE_LOCATION set, unless they expand to nothing... But
> + see above for the case of statement frontiers. */
> + else if (!debug_nonbind_markers_p
> + && inlined_function_outer_scope_p (scope))
> unused = false;
Wonder what the above hunks will do for LTO memory consumption. We'll see.
Otherwise the patch looks reasonable to me, but I think it depends on the
7/9.
Jakub