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