On Thu, Sep 10, 2020 at 04:09:24PM +0200, Richard Biener wrote: > So we're usually streaming the bits and the tree portion of SCCs > separately so I really wonder how we can end up with recursion here? > For stmts they should only refer to BLOCKs also in the BLOCK tree > which is streamed in before we stream in the stmts(?). > > So - isn't this an undetected stmt/tree references BLOCK not in > BLOCK tree bug? See verify_location which might or might not > handle all locations "correctly" though it looks like it obviously > verifies all stmts locations this way. So the question is whether > the function would pass verification at stream-out time ...
Looking at that align-3.C testcase on the trunk, I also see the recursive lto_output_location_1 calls as well. First on block: $18 = <block 0x7fffea738480> which is in the block tree from what I can see just fine (see the end of mail). Now, output_function has code that should stream the BLOCK tree leafs: /* Output DECL_INITIAL for the function, which contains the tree of lexical scopes. */ stream_write_tree (ob, DECL_INITIAL (function), true); /* As we do not recurse into BLOCK_SUBBLOCKS but only BLOCK_SUPERCONTEXT collect block tree leafs and stream those. */ auto_vec<tree> block_tree_leafs; if (DECL_INITIAL (function)) collect_block_tree_leafs (DECL_INITIAL (function), block_tree_leafs); streamer_write_uhwi (ob, block_tree_leafs.length ()); for (unsigned i = 0; i < block_tree_leafs.length (); ++i) stream_write_tree (ob, block_tree_leafs[i], true); static void collect_block_tree_leafs (tree root, vec<tree> &leafs) { for (root = BLOCK_SUBBLOCKS (root); root; root = BLOCK_CHAIN (root)) if (! BLOCK_SUBBLOCKS (root)) leafs.safe_push (root); else collect_block_tree_leafs (BLOCK_SUBBLOCKS (root), leafs); } but the problem is that it is broken, it doesn't cover all block leafs, but only leafs with an odd depth from DECL_INITIAL (and only some of those). The following patch fixes that, but I guess we are going to stream at that point significantly more blocks than before (though I guess most of the time we'd stream them later on when streaming the gimple_locations that refer to them). 2020-09-10 Jakub Jelinek <ja...@redhat.com> * lto-streamer-out.c (collect_block_tree_leafs): Recurse on root rather than BLOCK_SUBBLOCKS (root). --- gcc/lto-streamer-out.c.jj 2020-09-10 15:52:36.401413518 +0200 +++ gcc/lto-streamer-out.c 2020-09-10 17:14:24.934503237 +0200 @@ -2294,7 +2294,7 @@ collect_block_tree_leafs (tree root, vec if (! BLOCK_SUBBLOCKS (root)) leafs.safe_push (root); else - collect_block_tree_leafs (BLOCK_SUBBLOCKS (root), leafs); + collect_block_tree_leafs (root, leafs); } /* This performs function body modifications that are needed for streaming (gdb) p debug_tree (((tree)0x7fffea71d700)->decl_common.initial) <block 0x7fffea6f9ea0 used tree_0 supercontext <function_decl 0x7fffea71d700 main type <function_type 0x7fffea8259d8 type <integer_type 0x7fffea8145e8 int> QI size <integer_cst 0x7fffea7f5f60 constant 8> unit-size <integer_cst 0x7fffea7f5f78 constant 1> align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffea8259d8 arg-types <tree_list 0x7fffea80a8e8 value <void_type 0x7fffea814f18 void>>> addressable nothrow public static function-specific-target function-specific-opt decl_5 QI /usr/src/gcc-10/gcc/testsuite/g++.dg/ubsan/align-3.C:23:1 align:8 warn_if_not_align:0 context <translation_unit_decl 0x7fffea803168 /usr/src/gcc-10/gcc/testsuite/g++.dg/ubsan/align-3.C> initial <block 0x7fffea6f9ea0> result <result_decl 0x7fffea70de10 D.6516 type <integer_type 0x7fffea8145e8 int> ignored SI /usr/src/gcc-10/gcc/testsuite/g++.dg/ubsan/align-3.C:23:11 size <integer_cst 0x7fffea8170c0 constant 32> unit-size <integer_cst 0x7fffea8170d8 constant 4> align:32 warn_if_not_align:0 context <function_decl 0x7fffea71d700 main>> struct-function 0x7fffea714840 chain <var_decl 0x7fffea719120 s type <record_type 0x7fffea71a0a8 S> addressable used public static read BLK /usr/src/gcc-10/gcc/testsuite/g++.dg/ubsan/align-3.C:20:69 size <integer_cst 0x7fffea817330 constant 192> unit-size <integer_cst 0x7fffea817300 constant 24> align:128 warn_if_not_align:0 context <translation_unit_decl 0x7fffea803168 /usr/src/gcc-10/gcc/testsuite/g++.dg/ubsan/align-3.C> chain <type_decl 0x7fffea718098 S>>> subblocks <block 0x7fffea7384e0 used supercontext <block 0x7fffea6f9ea0> subblocks <block 0x7fffea738540 used supercontext <block 0x7fffea7384e0> subblocks <block 0x7fffea7385a0 used supercontext <block 0x7fffea738540> abstract_origin <block 0x7fffea6f9a80 used supercontext <function_decl 0x7fffea713b00 __ct >>> abstract_origin <block 0x7fffea6f9a80>> chain <block 0x7fffea7383c0 used supercontext <block 0x7fffea6f9ea0> subblocks <block 0x7fffea738480 used supercontext <block 0x7fffea7383c0> ^^^^^^^^^^^^^^ HERE abstract_origin <block 0x7fffea6f9c00 used supercontext <function_decl 0x7fffea713c00 __dt >>> chain <block 0x7fffea7381e0 used supercontext <block 0x7fffea6f9ea0> subblocks <block 0x7fffea738240 used supercontext <block 0x7fffea7381e0> subblocks <block 0x7fffea7382a0 used supercontext <block 0x7fffea738240> abstract_origin <block 0x7fffea6f9a80>> abstract_origin <block 0x7fffea6f9a80>> chain <block 0x7fffea6f9f00 used supercontext <block 0x7fffea6f9ea0> subblocks <block 0x7fffea738000 used supercontext <block 0x7fffea6f9f00> abstract_origin <block 0x7fffea6f9c00>> abstract_origin <function_decl 0x7fffea717200 __dt_base >> abstract_origin <function_decl 0x7fffea713b00 __ct >> abstract_origin <function_decl 0x7fffea717200 __dt_base >> abstract_origin <function_decl 0x7fffea713b00 __ct type <method_type 0x7fffea711498> addressable asm_written used nothrow public static abstract external weak autoinline decl_5 QI defer-output /usr/src/gcc-10/gcc/testsuite/g++.dg/ubsan/align-3.C:14:3 align:16 warn_if_not_align:0 context <translation_unit_decl 0x7fffea803168 /usr/src/gcc-10/gcc/testsuite/g++.dg/ubsan/align-3.C> initial <error_mark 0x7fffea7f5e58> chain <function_decl 0x7fffea717000 __ct_base >>>> Jakub