On 12/8/20 7:57 PM, Bernd Edlinger wrote: > On 12/8/20 11:35 AM, Richard Biener wrote: >> >> + { >> + /* Remove a nonbind marker when the outer scope of the >> + inline function is completely removed. */ >> + if (gimple_debug_nonbind_marker_p (stmt) >> + && BLOCK_ABSTRACT_ORIGIN (b)) >> + { >> + while (TREE_CODE (b) == BLOCK >> + && !inlined_function_outer_scope_p (b)) >> + b = BLOCK_SUPERCONTEXT (b); >> >> So given we never remove a inlined_function_outer_scope_p BLOCK from >> the block tree can we assert that we find such a BLOCK? If we never >> elide those BLOCKs how can it happen that we elide it in the end?
We can remove inlined function outer scope when they have no subblocks any more, or only unused subblocks, and there is an exception from the rule when no debug info is generated, that is due to this: > else if (!flag_auto_profile && debug_info_level == DINFO_LEVEL_NONE > && !optinfo_wants_inlining_info_p ()) > { > /* Even for -g0 don't prune outer scopes from artificial > functions, otherwise diagnostics using tree_nonartificial_location > will not be emitted properly. */ > if (inlined_function_outer_scope_p (scope)) > { > tree ao = BLOCK_ORIGIN (scope); > if (ao > && TREE_CODE (ao) == FUNCTION_DECL > && DECL_DECLARED_INLINE_P (ao) > && lookup_attribute ("artificial", DECL_ATTRIBUTES (ao))) > unused = false; > } > } > I instrumented the remove_unused_scope_block_p now as follows, to better understand what happens here: diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index 9ea24a1..3dd859c 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -525,9 +525,15 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block) *t = BLOCK_SUBBLOCKS (*t); while (BLOCK_CHAIN (*t)) { + gcc_assert (TREE_USED (*t)); + if (debug_info_level != DINFO_LEVEL_NONE) + gcc_assert (!inlined_function_outer_scope_p (BLOCK_SUPERCONTEXT (*t))); BLOCK_SUPERCONTEXT (*t) = supercontext; t = &BLOCK_CHAIN (*t); } + gcc_assert (TREE_USED (*t)); + if (debug_info_level != DINFO_LEVEL_NONE) + gcc_assert (!inlined_function_outer_scope_p (BLOCK_SUPERCONTEXT (*t))); BLOCK_CHAIN (*t) = next; BLOCK_SUPERCONTEXT (*t) = supercontext; t = &BLOCK_CHAIN (*t); This survives a bootstrap, but I consider that just as an experiment... This means that the BLOCK_SUPERCONTEXT pointers never skip an inlined_function_outer_scope_p, *except* when no debug info is generated, but then it is fine, as there are either no debug_nonbind_marker_p, or it would not matter, if an outer scope is missed. After the above loop runs, the BLOCK_SUBBLOCKS->BLOCK_CHAIN have only Blocks with TREE_USED Blocks with !TREE_USED are removed from the SUBBLOCKS->CHAIN list, but have still a valid BLOCK_SUPERCONTEXT. However BLOCK_CHAIN and BLOCK_SUBBLOCKS are not used any more, and could theoretically misused for something, but fortunately that is not necessary. I think that result suggests that the proposed patch does the right thing, already as-is. Do you agree? Thanks Bernd.