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.

Reply via email to