* [PATCH] keep scope blocks for all inlined functions (PR 98664) @ 2021-01-14 19:13 Martin Sebor 2021-01-15 7:44 ` Richard Biener 0 siblings, 1 reply; 12+ messages in thread From: Martin Sebor @ 2021-01-14 19:13 UTC (permalink / raw) To: Jeff Law, Jakub Jelinek, gcc-patches [-- Attachment #1: Type: text/plain, Size: 983 bytes --] One aspect of PR 98465 - Bogus warning stringop-overread for std::string is the inconsistency between -g and -g0 which turns out to be due to GCC eliminating apparently unused scope blocks from inlined functions that aren't explicitly declared inline and artificial. PR 98664 tracks just this part of PR 98465. To resolve just the PR 98664 subset the attached change has the tree-ssa-live.c pass preserve these blocks for all inlined functions, not just artificial ones. Besides avoiding the interaction between -g and warnings it also seems to improve the inlining context by including more inlined call sites. This can be seen in the adjusted tests. (Its effect on PR 98465 is that the false positive is issued consistently, regardless of -g. Avoiding the false positive is my next step.) Jakub, you raised a concern yesterday in PR 98465 c#13 about the memory footprint of this change. Can you please comment on whether it's in line with what you were suggesting? Martin [-- Attachment #2: gcc-98664.diff --] [-- Type: text/x-patch, Size: 9687 bytes --] PR middle-end/98664 - inconsistent -Wfree-nonheap-object for inlined calls to system headers gcc/ChangeLog: PR middle-end/98664 * tree-ssa-live.c (remove_unused_scope_block_p): Keep scopes for all functions, even if they're not declared artificial or inline. * tree.c (tree_inlined_location): Use macro expansion location only if scope traversal fails to expose one. gcc/testsuite/ChangeLog: PR middle-end/98664 * gcc.dg/Wvla-larger-than-4.c: Adjust expected output. * gcc.dg/plugin/diagnostic-test-inlining-3.c: Same. * g++.dg/warn/Wfree-nonheap-object-5.C: New test. * gcc.dg/Wfree-nonheap-object-4.c: New test. diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-5.C b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-5.C new file mode 100644 index 00000000000..742dba0cf58 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-5.C @@ -0,0 +1,129 @@ +/* PR middle-end/98664 - inconsistent --Wfree-nonheap-object for inlined + calls to system headers + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +# 7 "Wfree-nonheap-object-5.h" 1 3 + +struct A0 +{ + void *p; + + void f0 (void *q) { p = q; } + void g0 (void) { + __builtin_free (p); // { dg-warning "\\\[-Wfree-nonheap-object" } + } +}; + +struct A1 +{ + void *p; + + void f0 (void *q) { p = q; } + void f1 (void *q) { f0 (q); } + + void g0 (void) { + __builtin_free (p); // { dg-warning "\\\[-Wfree-nonheap-object" } + } + void g1 (void) { g0 (); } +}; + +struct A2 +{ + void *p; + + void f0 (void *q) { p = q; } + void f1 (void *q) { f0 (q); } + void f2 (void *q) { f1 (q); } + + void g0 (void) { + __builtin_free (p); // { dg-warning "\\\[-Wfree-nonheap-object" } + } + void g1 (void) { g0 (); } + void g2 (void) { g1 (); } +}; + +# 47 "Wfree-nonheap-object-5.C" + +#define NOIPA __attribute__ ((noipa)) + +extern int array[]; + +/* Verify the warning is issued even for calls in a system header inlined + into a function outside the header. */ + +NOIPA void warn_g0 (struct A0 *p) +{ + int *q = array + 1; + + p->f0 (q); + p->g0 (); +} + +// { dg-message "inlined from 'void warn_g0\\(A0\\*\\)'" "" { target *-*-* } 0 } + + +/* Also verify the warning can be suppressed. */ + +NOIPA void nowarn_g0 (struct A0 *p) +{ + int *q = array + 2; + + p->f0 (q); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" + p->g0 (); +#pragma GCC diagnostic pop +} + + +NOIPA void warn_g1 (struct A1 *p) +{ + int *q = array + 3; + + p->f1 (q); + p->g1 (); +} + +// { dg-message "inlined from 'void A1::g1\\(\\)'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'void warn_g1\\(A1\\*\\)'" "" { target *-*-* } 0 } + + +NOIPA void nowarn_g1 (struct A2 *p) +{ + int *q = array + 4; + + p->f1 (q); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" + p->g1 (); +#pragma GCC diagnostic pop +} + + +NOIPA void warn_g2 (struct A2 *p) +{ + int *q = array + 5; + + p->f2 (q); + p->g2 (); +} + +// { dg-message "inlined from 'void A2::g1\\(\\)'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'void A2::g2\\(\\)'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'void warn_g2\\(A2\\*\\)'" "" { target *-*-* } 0 } + + +NOIPA void nowarn_g2 (struct A2 *p) +{ + int *q = array + 6; + + p->f2 (q); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" + p->g2 (); +#pragma GCC diagnostic pop +} diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c new file mode 100644 index 00000000000..a7d921248c4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c @@ -0,0 +1,107 @@ +/* PR middle-end/98664 - inconsistent --Wfree-nonheap-object for inlined + calls to system headers + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +# 7 "Wfree-nonheap-object-4.h" 1 3 + +struct A +{ + void *p; +}; + +void f0 (struct A *p, void *q) { p->p = q; } +void f1 (struct A *p, void *q) { f0 (p, q); } +void f2 (struct A *p, void *q) { f1 (p, q); } + +void g0 (struct A *p) +{ + __builtin_free (p->p); // { dg-warning "\\\[-Wfree-nonheap-object" } +} + +void g1 (struct A *p) { g0 (p); } +void g2 (struct A *p) { g1 (p); } + +# 26 "Wfree-nonheap-object-4.c" + +#define NOIPA __attribute__ ((noipa)) + +extern int array[]; + +/* Verify the warning is issued even for calls in a system header inlined + into a function outside the header. */ + +NOIPA void warn_g0 (struct A *p) +{ + int *q = array + 1; + + f0 (p, q); + g0 (p); +} + +// { dg-message "inlined from 'warn_g0'" "" { target *-*-* } 0 } + + +/* Also verify the warning can be suppressed. */ + +NOIPA void nowarn_g0 (struct A *p) +{ + int *q = array + 2; + + f0 (p, q); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" + g0 (p); +#pragma GCC diagnostic pop +} + + +NOIPA void warn_g1 (struct A *p) +{ + int *q = array + 3; + + f1 (p, q); + g1 (p); +} + +// { dg-message "inlined from 'g1'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'warn_g1'" "" { target *-*-* } 0 } + + +NOIPA void nowarn_g1 (struct A *p) +{ + int *q = array + 4; + + f1 (p, q); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" + g1 (p); +#pragma GCC diagnostic pop +} + + +NOIPA void warn_g2 (struct A *p) +{ + int *q = array + 5; + + f2 (p, q); + g2 (p); +} + +// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 } + + +NOIPA void nowarn_g2 (struct A *p) +{ + int *q = array + 6; + + f2 (p, q); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" + g2 (p); +#pragma GCC diagnostic pop +} diff --git a/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c b/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c index de99afbe56e..7d27829736f 100644 --- a/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c +++ b/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c @@ -17,14 +17,14 @@ static inline void inline_use_vla (unsigned n) static inline void use_inlined_vla (unsigned n) { inline_use_vla (n); // this call is okay - inline_use_vla (n + 1); // this one is not + inline_use_vla (n + 1); // this one is not (line 20) } void call_inline (void) { - use_inlined_vla (31); + use_inlined_vla (31); // line 25 } /* Verify that the inlining context is included and that it points to the correct line number in the inlined function: - { dg-message "function 'inline_use_vla'..*inlined from 'call_inline' .*:20:" "" { target *-*-* } 0 } */ + { dg-message "function 'inline_use_vla'.*inlined from 'use_inlined_vla'.*:20:.*inlined from 'call_inline' .*:25:" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c index e1a4fca2cb4..b7df063c52c 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c @@ -35,7 +35,8 @@ int main() This test case captures this behavior. */ /* { dg-regexp "In function 'foo'," "" } */ -/* { dg-regexp " inlined from 'main' at .+/diagnostic-test-inlining-3.c:15:3:" "" } */ +/* { dg-regexp " inlined from 'bar' at .+/diagnostic-test-inlining-3.c:15:3:" "" } */ +/* { dg-regexp " inlined from 'main' at .+/diagnostic-test-inlining-3.c:20:3:" "" } */ /* { dg-warning "3: message" "" { target *-*-* } 9 } */ /* { dg-begin-multiline-output "" } __emit_warning ("message"); diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index 02a7a56f0f9..a7464369d73 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -558,16 +558,13 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block) 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. */ + /* Even for -g0 don't prune outer scopes from inlined functions, + otherwise late diagnostics from such functions will not be + emitted or suppressed 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))) + if (ao && TREE_CODE (ao) == FUNCTION_DECL) unused = false; } } diff --git a/gcc/tree.c b/gcc/tree.c index e0a1d512019..909551a73f9 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -12626,19 +12626,22 @@ tree_inlined_location (tree exp, bool system_header /* = true */) && BLOCK_ABSTRACT_ORIGIN (block)) { tree ao = BLOCK_ABSTRACT_ORIGIN (block); - if (TREE_CODE (ao) == FUNCTION_DECL) - loc = BLOCK_SOURCE_LOCATION (block); - else if (TREE_CODE (ao) != BLOCK) - break; + if (TREE_CODE (ao) == FUNCTION_DECL) + loc = BLOCK_SOURCE_LOCATION (block); + else if (TREE_CODE (ao) != BLOCK) + break; block = BLOCK_SUPERCONTEXT (block); } if (loc == UNKNOWN_LOCATION) - loc = EXPR_LOCATION (exp); - - if (system_header) - return expansion_point_location_if_in_system_header (loc); + { + loc = EXPR_LOCATION (exp); + if (system_header) + /* Only consider macro expansion when the block traversal failed + to find a location. Otherwise it's not relevant. */ + return expansion_point_location_if_in_system_header (loc); + } return loc; } ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] keep scope blocks for all inlined functions (PR 98664) 2021-01-14 19:13 [PATCH] keep scope blocks for all inlined functions (PR 98664) Martin Sebor @ 2021-01-15 7:44 ` Richard Biener 2021-01-17 0:46 ` Martin Sebor 0 siblings, 1 reply; 12+ messages in thread From: Richard Biener @ 2021-01-15 7:44 UTC (permalink / raw) To: Martin Sebor; +Cc: Jeff Law, Jakub Jelinek, gcc-patches On Thu, Jan 14, 2021 at 8:13 PM Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > One aspect of PR 98465 - Bogus warning stringop-overread for std::string > is the inconsistency between -g and -g0 which turns out to be due to > GCC eliminating apparently unused scope blocks from inlined functions > that aren't explicitly declared inline and artificial. PR 98664 tracks > just this part of PR 98465. > > To resolve just the PR 98664 subset the attached change has > the tree-ssa-live.c pass preserve these blocks for all inlined > functions, not just artificial ones. Besides avoiding the interaction > between -g and warnings it also seems to improve the inlining context > by including more inlined call sites. This can be seen in the adjusted > tests. (Its effect on PR 98465 is that the false positive is issued > consistently, regardless of -g. Avoiding the false positive is my > next step.) > > Jakub, you raised a concern yesterday in PR 98465 c#13 about the memory > footprint of this change. Can you please comment on whether it's in > line with what you were suggesting? { tree ao = BLOCK_ABSTRACT_ORIGIN (block); - if (TREE_CODE (ao) == FUNCTION_DECL) - loc = BLOCK_SOURCE_LOCATION (block); - else if (TREE_CODE (ao) != BLOCK) - break; + if (TREE_CODE (ao) == FUNCTION_DECL) + loc = BLOCK_SOURCE_LOCATION (block); + else if (TREE_CODE (ao) != BLOCK) + break; you are replacing tabs with spaces? @@ -558,16 +558,13 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block) 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. */ + /* Even for -g0 don't prune outer scopes from inlined functions, + otherwise late diagnostics from such functions will not be + emitted or suppressed 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))) + if (ao && TREE_CODE (ao) == FUNCTION_DECL) unused = false; } } so which inlined_function_outer_scope_p are you _not_ marking now? BLOCK_ORIGIN is never NULL and all inlined scopes should have an abstract origin - I believe always a FUNCTIN_DECL. Which means you could have simplified it further? And yes, the main reason for the code above is memory use for C++ with lots of inlining. I suggest to try the patch on tramp3d for example (there's about 10 inline instances per emitted assembly op). Richard. > Martin ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] keep scope blocks for all inlined functions (PR 98664) 2021-01-15 7:44 ` Richard Biener @ 2021-01-17 0:46 ` Martin Sebor 2021-01-18 13:25 ` Richard Biener 0 siblings, 1 reply; 12+ messages in thread From: Martin Sebor @ 2021-01-17 0:46 UTC (permalink / raw) To: Richard Biener; +Cc: Jeff Law, Jakub Jelinek, gcc-patches [-- Attachment #1: Type: text/plain, Size: 5555 bytes --] On 1/15/21 12:44 AM, Richard Biener wrote: > On Thu, Jan 14, 2021 at 8:13 PM Martin Sebor via Gcc-patches > <gcc-patches@gcc.gnu.org> wrote: >> >> One aspect of PR 98465 - Bogus warning stringop-overread for std::string >> is the inconsistency between -g and -g0 which turns out to be due to >> GCC eliminating apparently unused scope blocks from inlined functions >> that aren't explicitly declared inline and artificial. PR 98664 tracks >> just this part of PR 98465. >> >> To resolve just the PR 98664 subset the attached change has >> the tree-ssa-live.c pass preserve these blocks for all inlined >> functions, not just artificial ones. Besides avoiding the interaction >> between -g and warnings it also seems to improve the inlining context >> by including more inlined call sites. This can be seen in the adjusted >> tests. (Its effect on PR 98465 is that the false positive is issued >> consistently, regardless of -g. Avoiding the false positive is my >> next step.) >> >> Jakub, you raised a concern yesterday in PR 98465 c#13 about the memory >> footprint of this change. Can you please comment on whether it's in >> line with what you were suggesting? > > { > tree ao = BLOCK_ABSTRACT_ORIGIN (block); > - if (TREE_CODE (ao) == FUNCTION_DECL) > - loc = BLOCK_SOURCE_LOCATION (block); > - else if (TREE_CODE (ao) != BLOCK) > - break; > + if (TREE_CODE (ao) == FUNCTION_DECL) > + loc = BLOCK_SOURCE_LOCATION (block); > + else if (TREE_CODE (ao) != BLOCK) > + break; > > you are replacing tabs with spaces? > > @@ -558,16 +558,13 @@ remove_unused_scope_block_p (tree scope, bool > in_ctor_dtor_block) > 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. */ > + /* Even for -g0 don't prune outer scopes from inlined functions, > + otherwise late diagnostics from such functions will not be > + emitted or suppressed 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))) > + if (ao && TREE_CODE (ao) == FUNCTION_DECL) > unused = false; > } > } > > so which inlined_function_outer_scope_p are you _not_ marking now? > BLOCK_ORIGIN is never NULL and all inlined scopes should have > an abstract origin - I believe always a FUNCTIN_DECL. Which means > you could have simplified it further? Quite possibly. I could find no documentation for these macros so I tried to keep my changes conservative. I did put together some notes to document what I saw the macros evaluate to in my testing (below). If/when it's close to accurate I'd like to add them to tree.h and to the internals manual. > And yes, the main reason for the code above is memory use for > C++ with lots of inlining. I suggest to try the patch on tramp3d > for example (there's about 10 inline instances per emitted > assembly op). This one: https://github.com/llvm-mirror/test-suite/tree/master/MultiSource/Benchmarks/tramp3d-v4 ? With the patch, 69,022 more blocks with distinct numbers are kept than without it. I see some small differences in -fmem-report and -ftime-report output: Total: 286 -> 288M 210 -> 211M 3993 -> 4019k I'm not really sure what to look at so I attach the two reports for you to judge for yourself. I also attach an updated patch with the slight simplification you suggested. Martin PS Here are my notes on the macros and the two related functions: BLOCK: Denotes a lexical scope. Contains BLOCK_VARS of variables declared in it, BLOCK_SUBBLOCKS of scopes nested in it, and BLOCK_CHAIN pointing to the next BLOCK. Its BLOCK_SUPERCONTEXT point to the BLOCK of the enclosing scope. May have a BLOCK_ABSTRACT_ORIGIN and a BLOCK_SOURCE_LOCATION. BLOCK_SUPERCONTEXT: The scope of the enclosing block, or FUNCTION_DECL for the "outermost" function scope. Inlined functions are chained by this so that given expression E and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope (BLOCK) in which E has been made or into which E has been inlined. In the latter case, BLOCK_ORIGIN(B) evaluates either to the enclosing BLOCK or to the enclosing function DECL. It's never null. BLOCK_ABSTRACT_ORIGIN(B) is the FUNCTION_DECL of the function into which it has been inlined, or null if B is not inlined. BLOCK_ABSTRACT_ORIGIN: A BLOCK, or FUNCTION_DECL of the function into which a block has been inlined. In a BLOCK immediately enclosing an inlined leaf expression points to the outermost BLOCK into which it has been inlined (thus bypassing all intermediate BLOCK_SUPERCONTEXTs). BLOCK_FRAGMENT_ORIGIN: ??? BLOCK_FRAGMENT_CHAIN: ??? bool inlined_function_outer_scope_p(BLOCK) [tree.h] Returns true if a BLOCK has a source location. True for all but the innermost (no SUBBLOCKs?) and outermost blocks into which an expression has been inlined. (Is this always true?) tree block_ultimate_origin(BLOCK) [tree.c] Returns BLOCK_ABSTRACT_ORIGIN(BLOCK), AO, after asserting that (DECL_P(AO) && DECL_ORIGIN(AO) == AO) || BLOCK_ORIGIN(AO) == AO). [-- Attachment #2: tramp3d-v4.report.baseline --] [-- Type: text/plain, Size: 22715 bytes --] $ /build/gcc-master/gcc/xg++ -B /build/gcc-master/gcc -nostdinc++ -I /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu -I /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include -I /src/gcc/master/libstdc++-v3/libsupc++ -I /src/gcc/master/libstdc++-v3/include/backward -I /src/gcc/master/libstdc++-v3/testsuite/util -L /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs -O2 -c -fdump-tree-cfg=tramp3d-v4.keep_blocks.cfg /src/tramp3d-v4.cpp -fmem-report -ftime-report ################################################################################ # Final # ################################################################################ Number of expanded macros: 18928 Average number of tokens per macro expansion: 7 Line Table allocations during the compilation process Number of ordinary maps used: 915 Ordinary map used size: 21k Number of ordinary maps allocated: 1365 Ordinary maps allocated size: 31k Number of macro maps used: 16k Macro maps used size: 525k Macro maps locations size: 1124k Macro maps size: 1650k Duplicated maps locations size: 378k Total allocated maps size: 3204k Total used maps size: 1671k Ad-hoc table size: 12M Ad-hoc table entries used: 472k optimized_ranges: 1171k unoptimized_ranges: 134k Memory still allocated at the end of the compilation process Size Allocated Used Overhead 8 116k 95k 3480 16 4120k 2271k 88k 32 23M 11M 418k 64 10M 8427k 166k 256 30M 25M 423k 512 1500k 1166k 20k 1024 3856k 1708k 52k 2048 5040k 4986k 68k 4096 148k 148k 2072 8192 48k 48k 336 16384 64k 64k 224 32768 128k 128k 224 65536 384k 384k 336 131072 128k 128k 56 262144 768k 768k 168 524288 512k 512k 56 1048576 2048k 2048k 112 2097152 2048k 2048k 56 16777216 16M 16M 56 24 11M 5294k 208k 40 25M 17M 413k 48 14M 6606k 236k 56 4812k 1825k 75k 72 3276k 775k 44k 80 596k 217k 8344 88 364k 177k 5096 96 11M 6110k 154k 112 3492k 2075k 47k 120 6172k 4542k 84k 152 16M 15M 237k 128 30M 26M 430k 144 6484k 1881k 88k 168 42M 40M 601k 184 3348k 2045k 45k 104 1176k 1036k 16k 272 3536k 904k 48k 280 164k 103k 2296 Total 286M 210M 3993k String pool entries: 79454 identifiers: 34933 (43.97%) slots: 131072 deleted: 36676 GGC bytes: 2620k table size: 1024k coll/search: 0.8217 ins/search: 0.1222 avg. entry: 33.77 bytes (+/- 71.45) longest entry: 496 (No per-node statistics) Type hash: size 131071, 67199 elements, 1.112287 collisions DECL_DEBUG_EXPR hash: size 1021, 0 elements, 0.856842 collisions DECL_VALUE_EXPR hash: size 1021, 30 elements, 0.146046 collisions decl_specializations: size 131071, 50624 elements, 1.386344 collisions type_specializations: size 32749, 23184 elements, 2.504205 collisions No GIMPLE statistics No RTX statistics -------------------------------------------------------------------------------------------------------------------------------------------- Heap vectors sizeof(T) Leak Peak Times Leak items Peak items -------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------- Heap vectors sizeof(T) Leak Peak Times Leak items Peak items -------------------------------------------------------------------------------------------------------------------------------------------- Total 0 0 0 -------------------------------------------------------------------------------------------------------------------------------------------- Alias oracle query stats: refs_may_alias_p: 2798174 disambiguations, 3068078 queries ref_maybe_used_by_call_p: 23818 disambiguations, 2836845 queries call_may_clobber_ref_p: 2754 disambiguations, 2764 queries nonoverlapping_component_refs_p: 0 disambiguations, 3493 queries nonoverlapping_refs_since_match_p: 376 disambiguations, 9008 must overlaps, 9415 queries aliasing_component_refs_p: 807 disambiguations, 30842 queries TBAA oracle: 1041789 disambiguations 1976625 queries 189831 are in alias set 0 513994 queries asked about the same object 0 queries asked about the same alias set 0 access volatile 230715 are dependent in the DAG 296 are aritificially in conflict with void * Modref stats: modref use: 537 disambiguations, 6371 queries modref clobber: 37429 disambiguations, 352194 queries 119124 tbaa queries (0.338234 per modref query) 21518 base compares (0.061097 per modref query) PTA query stats: pt_solution_includes: 559296 disambiguations, 744735 queries pt_solutions_intersect: 154078 disambiguations, 422490 queries Time variable usr sys wall GGC phase setup : 0.00 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 1554k ( 0%) phase parsing : 4.56 ( 4%) 0.60 ( 21%) 5.16 ( 5%) 213M ( 20%) phase lang. deferred : 4.29 ( 4%) 0.29 ( 10%) 4.59 ( 4%) 189M ( 17%) phase opt and generate : 97.18 ( 91%) 2.00 ( 69%) 99.38 ( 91%) 687M ( 63%) phase finalize : 0.27 ( 0%) 0.01 ( 0%) 0.28 ( 0%) 0 ( 0%) |name lookup : 0.88 ( 1%) 0.08 ( 3%) 0.76 ( 1%) 13M ( 1%) |overload resolution : 2.36 ( 2%) 0.23 ( 8%) 2.42 ( 2%) 110M ( 10%) garbage collection : 3.26 ( 3%) 0.01 ( 0%) 3.27 ( 3%) 0 ( 0%) dump files : 0.29 ( 0%) 0.02 ( 1%) 0.49 ( 0%) 2945k ( 0%) callgraph construction : 1.30 ( 1%) 0.14 ( 5%) 1.43 ( 1%) 37M ( 3%) callgraph optimization : 0.73 ( 1%) 0.03 ( 1%) 0.83 ( 1%) 154k ( 0%) callgraph functions expansion : 67.29 ( 63%) 0.69 ( 24%) 68.12 ( 62%) 362M ( 33%) callgraph ipa passes : 26.35 ( 25%) 0.98 ( 34%) 27.39 ( 25%) 226M ( 21%) ipa function summary : 0.23 ( 0%) 0.00 ( 0%) 0.23 ( 0%) 4663k ( 0%) ipa dead code removal : 0.08 ( 0%) 0.01 ( 0%) 0.08 ( 0%) 56 ( 0%) ipa devirtualization : 0.01 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 4944 ( 0%) ipa cp : 0.55 ( 1%) 0.01 ( 0%) 0.52 ( 0%) 4862k ( 0%) ipa inlining heuristics : 0.70 ( 1%) 0.02 ( 1%) 0.83 ( 1%) 22M ( 2%) ipa function splitting : 0.19 ( 0%) 0.01 ( 0%) 0.18 ( 0%) 705k ( 0%) ipa comdats : 0.00 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 0 ( 0%) ipa reference : 0.02 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 0 ( 0%) ipa profile : 0.02 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 0 ( 0%) ipa pure const : 0.14 ( 0%) 0.01 ( 0%) 0.22 ( 0%) 437k ( 0%) ipa icf : 0.16 ( 0%) 0.00 ( 0%) 0.16 ( 0%) 44k ( 0%) ipa SRA : 0.24 ( 0%) 0.01 ( 0%) 0.22 ( 0%) 6229k ( 1%) ipa free lang data : 0.03 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 0 ( 0%) ipa free inline summary : 0.04 ( 0%) 0.00 ( 0%) 0.04 ( 0%) 0 ( 0%) ipa modref : 0.11 ( 0%) 0.00 ( 0%) 0.11 ( 0%) 1858k ( 0%) cfg construction : 0.06 ( 0%) 0.00 ( 0%) 0.06 ( 0%) 1187k ( 0%) cfg cleanup : 0.45 ( 0%) 0.01 ( 0%) 0.35 ( 0%) 1464k ( 0%) CFG verifier : 4.15 ( 4%) 0.18 ( 6%) 4.37 ( 4%) 0 ( 0%) trivially dead code : 0.10 ( 0%) 0.00 ( 0%) 0.09 ( 0%) 0 ( 0%) df scan insns : 0.29 ( 0%) 0.00 ( 0%) 0.23 ( 0%) 43k ( 0%) df reaching defs : 0.32 ( 0%) 0.00 ( 0%) 0.38 ( 0%) 0 ( 0%) df live regs : 1.02 ( 1%) 0.00 ( 0%) 0.96 ( 1%) 0 ( 0%) df live&initialized regs : 0.35 ( 0%) 0.00 ( 0%) 0.28 ( 0%) 0 ( 0%) df must-initialized regs : 0.05 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 0 ( 0%) df use-def / def-use chains : 0.15 ( 0%) 0.00 ( 0%) 0.20 ( 0%) 0 ( 0%) df reg dead/unused notes : 0.43 ( 0%) 0.00 ( 0%) 0.41 ( 0%) 4205k ( 0%) register information : 0.08 ( 0%) 0.00 ( 0%) 0.12 ( 0%) 0 ( 0%) alias analysis : 0.29 ( 0%) 0.00 ( 0%) 0.37 ( 0%) 11M ( 1%) alias stmt walking : 4.25 ( 4%) 0.04 ( 1%) 4.36 ( 4%) 1366k ( 0%) register scan : 0.03 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 117k ( 0%) rebuild jump labels : 0.03 ( 0%) 0.00 ( 0%) 0.06 ( 0%) 0 ( 0%) preprocessing : 0.32 ( 0%) 0.10 ( 3%) 0.39 ( 0%) 5611k ( 1%) parser (global) : 0.60 ( 1%) 0.23 ( 8%) 0.76 ( 1%) 57M ( 5%) parser struct body : 0.73 ( 1%) 0.03 ( 1%) 0.69 ( 1%) 37M ( 3%) parser enumerator list : 0.03 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 357k ( 0%) parser function body : 0.39 ( 0%) 0.02 ( 1%) 0.37 ( 0%) 9857k ( 1%) parser inl. func. body : 0.24 ( 0%) 0.01 ( 0%) 0.25 ( 0%) 5970k ( 1%) parser inl. meth. body : 0.43 ( 0%) 0.11 ( 4%) 0.71 ( 1%) 25M ( 2%) template instantiation : 4.92 ( 5%) 0.38 ( 13%) 5.35 ( 5%) 261M ( 24%) constant expression evaluation : 0.09 ( 0%) 0.01 ( 0%) 0.14 ( 0%) 1563k ( 0%) early inlining heuristics : 0.33 ( 0%) 0.01 ( 0%) 0.35 ( 0%) 10M ( 1%) inline parameters : 0.53 ( 0%) 0.05 ( 2%) 0.71 ( 1%) 15M ( 1%) integration : 2.03 ( 2%) 0.07 ( 2%) 2.14 ( 2%) 126M ( 12%) tree gimplify : 0.53 ( 0%) 0.07 ( 2%) 0.51 ( 0%) 38M ( 4%) tree eh : 0.15 ( 0%) 0.00 ( 0%) 0.22 ( 0%) 10M ( 1%) tree CFG construction : 0.15 ( 0%) 0.01 ( 0%) 0.18 ( 0%) 17M ( 2%) tree CFG cleanup : 1.05 ( 1%) 0.03 ( 1%) 1.32 ( 1%) 625k ( 0%) tree tail merge : 0.05 ( 0%) 0.00 ( 0%) 0.07 ( 0%) 1772k ( 0%) tree VRP : 2.20 ( 2%) 0.02 ( 1%) 2.26 ( 2%) 14M ( 1%) tree Early VRP : 1.53 ( 1%) 0.06 ( 2%) 1.46 ( 1%) 12M ( 1%) tree copy propagation : 0.31 ( 0%) 0.00 ( 0%) 0.26 ( 0%) 188k ( 0%) tree PTA : 1.90 ( 2%) 0.05 ( 2%) 2.16 ( 2%) 5309k ( 0%) tree PHI insertion : 0.03 ( 0%) 0.00 ( 0%) 0.04 ( 0%) 1826k ( 0%) tree SSA rewrite : 0.46 ( 0%) 0.01 ( 0%) 0.45 ( 0%) 15M ( 1%) tree SSA other : 0.12 ( 0%) 0.02 ( 1%) 0.16 ( 0%) 1597k ( 0%) tree SSA incremental : 0.42 ( 0%) 0.03 ( 1%) 0.43 ( 0%) 3434k ( 0%) tree operand scan : 0.82 ( 1%) 0.05 ( 2%) 0.77 ( 1%) 43M ( 4%) dominator optimization : 2.53 ( 2%) 0.04 ( 1%) 2.60 ( 2%) 12M ( 1%) backwards jump threading : 0.13 ( 0%) 0.00 ( 0%) 0.14 ( 0%) 347k ( 0%) tree SRA : 0.26 ( 0%) 0.00 ( 0%) 0.25 ( 0%) 1084k ( 0%) isolate eroneous paths : 0.03 ( 0%) 0.00 ( 0%) 0.06 ( 0%) 1584 ( 0%) tree CCP : 1.43 ( 1%) 0.03 ( 1%) 1.74 ( 2%) 4451k ( 0%) tree split crit edges : 0.04 ( 0%) 0.00 ( 0%) 0.05 ( 0%) 1578k ( 0%) tree reassociation : 0.08 ( 0%) 0.00 ( 0%) 0.07 ( 0%) 18k ( 0%) tree PRE : 2.07 ( 2%) 0.03 ( 1%) 1.87 ( 2%) 11M ( 1%) tree FRE : 2.57 ( 2%) 0.02 ( 1%) 2.82 ( 3%) 6890k ( 1%) tree code sinking : 0.06 ( 0%) 0.00 ( 0%) 0.09 ( 0%) 1307k ( 0%) tree linearize phis : 0.17 ( 0%) 0.00 ( 0%) 0.20 ( 0%) 993k ( 0%) tree backward propagate : 0.01 ( 0%) 0.00 ( 0%) 0.05 ( 0%) 0 ( 0%) tree forward propagate : 0.93 ( 1%) 0.04 ( 1%) 0.80 ( 1%) 2244k ( 0%) tree phiprop : 0.02 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 19k ( 0%) tree conservative DCE : 0.24 ( 0%) 0.00 ( 0%) 0.23 ( 0%) 449k ( 0%) tree aggressive DCE : 0.39 ( 0%) 0.00 ( 0%) 0.39 ( 0%) 12M ( 1%) tree buildin call DCE : 0.01 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 3504 ( 0%) tree DSE : 1.16 ( 1%) 0.00 ( 0%) 1.08 ( 1%) 339k ( 0%) PHI merge : 0.05 ( 0%) 0.00 ( 0%) 0.08 ( 0%) 128k ( 0%) tree loop optimization : 0.00 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 0 ( 0%) tree loop invariant motion : 0.32 ( 0%) 0.00 ( 0%) 0.25 ( 0%) 117k ( 0%) tree canonical iv : 0.24 ( 0%) 0.00 ( 0%) 0.14 ( 0%) 2168k ( 0%) scev constant prop : 0.03 ( 0%) 0.00 ( 0%) 0.09 ( 0%) 537k ( 0%) complete unrolling : 1.56 ( 1%) 0.01 ( 0%) 1.32 ( 1%) 14M ( 1%) tree loop distribution : 0.33 ( 0%) 0.00 ( 0%) 0.35 ( 0%) 3488k ( 0%) tree iv optimization : 1.42 ( 1%) 0.01 ( 0%) 1.38 ( 1%) 19M ( 2%) tree copy headers : 0.11 ( 0%) 0.00 ( 0%) 0.10 ( 0%) 1438k ( 0%) tree SSA uncprop : 0.05 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 0 ( 0%) tree NRV optimization : 0.01 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 1824 ( 0%) tree SSA verifier : 11.24 ( 11%) 0.29 ( 10%) 12.00 ( 11%) 0 ( 0%) tree STMT verifier : 17.17 ( 16%) 0.27 ( 9%) 16.90 ( 15%) 0 ( 0%) tree switch conversion : 0.04 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 0 ( 0%) tree switch lowering : 0.04 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 0 ( 0%) gimple CSE sin/cos : 0.02 ( 0%) 0.00 ( 0%) 0.00 ( 0%) 0 ( 0%) gimple widening/fma detection : 0.05 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 13k ( 0%) tree strlen optimization : 0.63 ( 1%) 0.00 ( 0%) 0.55 ( 1%) 4021k ( 0%) tree modref : 0.24 ( 0%) 0.00 ( 0%) 0.33 ( 0%) 5652k ( 1%) callgraph verifier : 0.58 ( 1%) 0.02 ( 1%) 0.53 ( 0%) 0 ( 0%) dominance frontiers : 0.00 ( 0%) 0.00 ( 0%) 0.07 ( 0%) 0 ( 0%) dominance computation : 1.19 ( 1%) 0.00 ( 0%) 1.36 ( 1%) 0 ( 0%) control dependences : 0.02 ( 0%) 0.00 ( 0%) 0.06 ( 0%) 0 ( 0%) out of ssa : 0.11 ( 0%) 0.00 ( 0%) 0.10 ( 0%) 60k ( 0%) expand vars : 0.19 ( 0%) 0.00 ( 0%) 0.09 ( 0%) 3108k ( 0%) expand : 0.59 ( 1%) 0.00 ( 0%) 0.68 ( 1%) 30M ( 3%) post expand cleanups : 0.08 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 2280k ( 0%) varconst : 0.03 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 16k ( 0%) lower subreg : 0.00 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 21k ( 0%) jump : 0.02 ( 0%) 0.00 ( 0%) 0.00 ( 0%) 0 ( 0%) forward prop : 0.59 ( 1%) 0.00 ( 0%) 0.69 ( 1%) 284k ( 0%) CSE : 0.53 ( 0%) 0.01 ( 0%) 0.59 ( 1%) 1772k ( 0%) dead code elimination : 0.11 ( 0%) 0.00 ( 0%) 0.05 ( 0%) 0 ( 0%) dead store elim1 : 0.19 ( 0%) 0.00 ( 0%) 0.17 ( 0%) 2756k ( 0%) dead store elim2 : 0.36 ( 0%) 0.00 ( 0%) 0.34 ( 0%) 3976k ( 0%) loop analysis : 0.04 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 0 ( 0%) loop init : 1.85 ( 2%) 0.02 ( 1%) 1.81 ( 2%) 25M ( 2%) loop invariant motion : 0.10 ( 0%) 0.00 ( 0%) 0.08 ( 0%) 145k ( 0%) loop fini : 0.05 ( 0%) 0.01 ( 0%) 0.05 ( 0%) 14k ( 0%) CPROP : 0.51 ( 0%) 0.01 ( 0%) 0.64 ( 1%) 4218k ( 0%) PRE : 0.47 ( 0%) 0.00 ( 0%) 0.56 ( 1%) 1545k ( 0%) CSE 2 : 0.25 ( 0%) 0.00 ( 0%) 0.38 ( 0%) 736k ( 0%) branch prediction : 0.37 ( 0%) 0.03 ( 1%) 0.34 ( 0%) 3272k ( 0%) combiner : 0.84 ( 1%) 0.01 ( 0%) 0.71 ( 1%) 7613k ( 1%) if-conversion : 0.05 ( 0%) 0.00 ( 0%) 0.04 ( 0%) 312k ( 0%) integrated RA : 2.17 ( 2%) 0.03 ( 1%) 2.15 ( 2%) 44M ( 4%) LRA non-specific : 0.54 ( 1%) 0.00 ( 0%) 0.54 ( 0%) 4028k ( 0%) LRA virtuals elimination : 0.16 ( 0%) 0.01 ( 0%) 0.14 ( 0%) 2129k ( 0%) LRA reload inheritance : 0.13 ( 0%) 0.00 ( 0%) 0.14 ( 0%) 391k ( 0%) LRA create live ranges : 0.49 ( 0%) 0.00 ( 0%) 0.60 ( 1%) 417k ( 0%) LRA hard reg assignment : 0.10 ( 0%) 0.00 ( 0%) 0.09 ( 0%) 0 ( 0%) LRA rematerialization : 0.15 ( 0%) 0.00 ( 0%) 0.07 ( 0%) 2128 ( 0%) reload : 0.00 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 0 ( 0%) reload CSE regs : 0.57 ( 1%) 0.00 ( 0%) 0.68 ( 1%) 4376k ( 0%) ree : 0.04 ( 0%) 0.00 ( 0%) 0.04 ( 0%) 48k ( 0%) thread pro- & epilogue : 0.44 ( 0%) 0.01 ( 0%) 0.29 ( 0%) 2591k ( 0%) if-conversion 2 : 0.02 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 11k ( 0%) combine stack adjustments : 0.04 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 0 ( 0%) peephole 2 : 0.08 ( 0%) 0.00 ( 0%) 0.07 ( 0%) 479k ( 0%) hard reg cprop : 0.18 ( 0%) 0.01 ( 0%) 0.16 ( 0%) 36k ( 0%) scheduling 2 : 1.49 ( 1%) 0.00 ( 0%) 1.37 ( 1%) 1902k ( 0%) machine dep reorg : 0.08 ( 0%) 0.00 ( 0%) 0.07 ( 0%) 0 ( 0%) reorder blocks : 0.16 ( 0%) 0.00 ( 0%) 0.17 ( 0%) 1340k ( 0%) shorten branches : 0.05 ( 0%) 0.00 ( 0%) 0.06 ( 0%) 0 ( 0%) final : 0.13 ( 0%) 0.01 ( 0%) 0.18 ( 0%) 6736k ( 1%) variable output : 0.01 ( 0%) 0.00 ( 0%) 0.00 ( 0%) 196k ( 0%) symout : 0.01 ( 0%) 0.00 ( 0%) 0.00 ( 0%) 0 ( 0%) tree if-combine : 0.00 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 17k ( 0%) if to switch conversion : 0.04 ( 0%) 0.00 ( 0%) 0.06 ( 0%) 0 ( 0%) straight-line strength reduction : 0.12 ( 0%) 0.00 ( 0%) 0.07 ( 0%) 56k ( 0%) store merging : 0.38 ( 0%) 0.00 ( 0%) 0.29 ( 0%) 1107k ( 0%) initialize rtl : 0.01 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 12k ( 0%) address lowering : 0.07 ( 0%) 0.01 ( 0%) 0.12 ( 0%) 1586k ( 0%) early local passes : 0.02 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 0 ( 0%) unaccounted optimizations : 0.00 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 0 ( 0%) rest of compilation : 0.82 ( 1%) 0.02 ( 1%) 0.94 ( 1%) 4036k ( 0%) remove unused locals : 0.35 ( 0%) 0.01 ( 0%) 0.26 ( 0%) 30k ( 0%) address taken : 0.22 ( 0%) 0.02 ( 1%) 0.26 ( 0%) 0 ( 0%) verify loop closed : 0.02 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 0 ( 0%) verify RTL sharing : 1.71 ( 2%) 0.04 ( 1%) 1.54 ( 1%) 0 ( 0%) rebuild frequencies : 0.02 ( 0%) 0.00 ( 0%) 0.05 ( 0%) 31k ( 0%) repair loop structures : 0.17 ( 0%) 0.00 ( 0%) 0.19 ( 0%) 9456 ( 0%) TOTAL : 106.30 2.90 109.42 1092M Extra diagnostic checks enabled; compiler may run slowly. Configure with --enable-checking=release to disable checks. [-- Attachment #3: tramp3d-v4.report.keep_blocks --] [-- Type: text/plain, Size: 23017 bytes --] $ keep_blocks=1 /build/gcc-master/gcc/xg++ -B /build/gcc-master/gcc -nostdinc++ -I /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu -I /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include -I /src/gcc/master/libstdc++-v3/libsupc++ -I /src/gcc/master/libstdc++-v3/include/backward -I /src/gcc/master/libstdc++-v3/testsuite/util -L /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs -O2 -c -fdump-tree-cfg=tramp3d-v4.keep_blocks.cfg /src/tramp3d-v4.cpp -fmem-report -ftime-report ################################################################################ # Final # ################################################################################ Number of expanded macros: 18928 Average number of tokens per macro expansion: 7 Line Table allocations during the compilation process Number of ordinary maps used: 915 Ordinary map used size: 21k Number of ordinary maps allocated: 1365 Ordinary maps allocated size: 31k Number of macro maps used: 16k Macro maps used size: 525k Macro maps locations size: 1124k Macro maps size: 1650k Duplicated maps locations size: 378k Total allocated maps size: 3204k Total used maps size: 1671k Ad-hoc table size: 12M Ad-hoc table entries used: 473k optimized_ranges: 1171k unoptimized_ranges: 134k Memory still allocated at the end of the compilation process Size Allocated Used Overhead 8 116k 95k 3480 16 4056k 2271k 87k 32 23M 11M 417k 64 10M 8427k 167k 256 30M 25M 424k 512 1504k 1166k 20k 1024 3852k 1708k 52k 2048 5040k 4986k 68k 4096 148k 148k 2072 8192 48k 48k 336 16384 64k 64k 224 32768 128k 128k 224 65536 320k 320k 280 131072 128k 128k 56 262144 1024k 1024k 224 524288 512k 512k 56 1048576 2048k 2048k 112 2097152 2048k 2048k 56 16777216 16M 16M 56 24 11M 5294k 209k 40 26M 17M 416k 48 14M 6606k 236k 56 4828k 1825k 75k 72 3288k 775k 44k 80 600k 217k 8400 88 360k 177k 5040 96 12M 7050k 174k 112 3492k 2075k 47k 120 6172k 4542k 84k 152 17M 15M 238k 128 30M 26M 429k 144 6516k 1881k 89k 168 43M 40M 602k 184 3340k 2045k 45k 104 1164k 1036k 15k 272 3520k 904k 48k 280 172k 103k 2408 Total 288M 211M 4019k String pool entries: 79453 identifiers: 34933 (43.97%) slots: 131072 deleted: 36683 GGC bytes: 2620k table size: 1024k coll/search: 0.8234 ins/search: 0.1222 avg. entry: 33.77 bytes (+/- 71.45) longest entry: 496 (No per-node statistics) Type hash: size 131071, 67199 elements, 1.112279 collisions DECL_DEBUG_EXPR hash: size 1021, 0 elements, 0.859474 collisions DECL_VALUE_EXPR hash: size 1021, 30 elements, 0.148597 collisions decl_specializations: size 131071, 50624 elements, 1.386344 collisions type_specializations: size 32749, 23184 elements, 2.504205 collisions No GIMPLE statistics No RTX statistics -------------------------------------------------------------------------------------------------------------------------------------------- Heap vectors sizeof(T) Leak Peak Times Leak items Peak items -------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------- Heap vectors sizeof(T) Leak Peak Times Leak items Peak items -------------------------------------------------------------------------------------------------------------------------------------------- Total 0 0 0 -------------------------------------------------------------------------------------------------------------------------------------------- Alias oracle query stats: refs_may_alias_p: 2798174 disambiguations, 3068078 queries ref_maybe_used_by_call_p: 23818 disambiguations, 2836845 queries call_may_clobber_ref_p: 2754 disambiguations, 2764 queries nonoverlapping_component_refs_p: 0 disambiguations, 3493 queries nonoverlapping_refs_since_match_p: 376 disambiguations, 9008 must overlaps, 9415 queries aliasing_component_refs_p: 807 disambiguations, 30842 queries TBAA oracle: 1041789 disambiguations 1976625 queries 189831 are in alias set 0 513994 queries asked about the same object 0 queries asked about the same alias set 0 access volatile 230715 are dependent in the DAG 296 are aritificially in conflict with void * Modref stats: modref use: 537 disambiguations, 6371 queries modref clobber: 37429 disambiguations, 352194 queries 119124 tbaa queries (0.338234 per modref query) 21518 base compares (0.061097 per modref query) PTA query stats: pt_solution_includes: 559296 disambiguations, 744735 queries pt_solutions_intersect: 154078 disambiguations, 422490 queries Time variable usr sys wall GGC phase setup : 0.00 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 1554k ( 0%) phase parsing : 4.52 ( 4%) 0.60 ( 21%) 5.12 ( 5%) 213M ( 19%) phase lang. deferred : 4.33 ( 4%) 0.28 ( 10%) 4.63 ( 4%) 189M ( 17%) phase opt and generate : 98.18 ( 91%) 2.00 ( 69%) 100.38 ( 91%) 692M ( 63%) phase last asm : 0.00 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 32k ( 0%) phase finalize : 0.29 ( 0%) 0.01 ( 0%) 0.29 ( 0%) 0 ( 0%) |name lookup : 0.73 ( 1%) 0.04 ( 1%) 0.68 ( 1%) 13M ( 1%) |overload resolution : 2.29 ( 2%) 0.22 ( 8%) 2.39 ( 2%) 110M ( 10%) garbage collection : 3.34 ( 3%) 0.02 ( 1%) 3.32 ( 3%) 0 ( 0%) dump files : 0.50 ( 0%) 0.05 ( 2%) 0.43 ( 0%) 2945k ( 0%) callgraph construction : 1.26 ( 1%) 0.11 ( 4%) 1.39 ( 1%) 37M ( 3%) callgraph optimization : 0.80 ( 1%) 0.06 ( 2%) 0.81 ( 1%) 154k ( 0%) callgraph functions expansion : 68.01 ( 63%) 0.68 ( 24%) 68.84 ( 62%) 365M ( 33%) callgraph ipa passes : 26.57 ( 25%) 1.03 ( 36%) 27.65 ( 25%) 228M ( 21%) ipa function summary : 0.26 ( 0%) 0.01 ( 0%) 0.21 ( 0%) 4663k ( 0%) ipa dead code removal : 0.10 ( 0%) 0.00 ( 0%) 0.11 ( 0%) 56 ( 0%) ipa inheritance graph : 0.01 ( 0%) 0.00 ( 0%) 0.00 ( 0%) 20k ( 0%) ipa virtual call target : 0.00 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 3264 ( 0%) ipa cp : 0.55 ( 1%) 0.00 ( 0%) 0.48 ( 0%) 4862k ( 0%) ipa inlining heuristics : 0.80 ( 1%) 0.00 ( 0%) 0.81 ( 1%) 22M ( 2%) ipa function splitting : 0.20 ( 0%) 0.01 ( 0%) 0.24 ( 0%) 724k ( 0%) ipa comdats : 0.03 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 0 ( 0%) ipa reference : 0.01 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 0 ( 0%) ipa profile : 0.02 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 0 ( 0%) ipa pure const : 0.23 ( 0%) 0.01 ( 0%) 0.14 ( 0%) 437k ( 0%) ipa icf : 0.17 ( 0%) 0.00 ( 0%) 0.17 ( 0%) 44k ( 0%) ipa SRA : 0.24 ( 0%) 0.00 ( 0%) 0.24 ( 0%) 6229k ( 1%) ipa free lang data : 0.05 ( 0%) 0.00 ( 0%) 0.04 ( 0%) 0 ( 0%) ipa free inline summary : 0.03 ( 0%) 0.01 ( 0%) 0.03 ( 0%) 0 ( 0%) ipa modref : 0.11 ( 0%) 0.00 ( 0%) 0.10 ( 0%) 1858k ( 0%) cfg construction : 0.03 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 1187k ( 0%) cfg cleanup : 0.36 ( 0%) 0.00 ( 0%) 0.53 ( 0%) 1464k ( 0%) CFG verifier : 3.90 ( 4%) 0.04 ( 1%) 4.71 ( 4%) 0 ( 0%) trivially dead code : 0.12 ( 0%) 0.00 ( 0%) 0.16 ( 0%) 0 ( 0%) df scan insns : 0.31 ( 0%) 0.02 ( 1%) 0.22 ( 0%) 43k ( 0%) df reaching defs : 0.31 ( 0%) 0.00 ( 0%) 0.30 ( 0%) 0 ( 0%) df live regs : 0.89 ( 1%) 0.01 ( 0%) 0.95 ( 1%) 0 ( 0%) df live&initialized regs : 0.48 ( 0%) 0.00 ( 0%) 0.33 ( 0%) 0 ( 0%) df must-initialized regs : 0.01 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 0 ( 0%) df use-def / def-use chains : 0.25 ( 0%) 0.00 ( 0%) 0.16 ( 0%) 0 ( 0%) df reg dead/unused notes : 0.43 ( 0%) 0.00 ( 0%) 0.47 ( 0%) 4205k ( 0%) register information : 0.15 ( 0%) 0.00 ( 0%) 0.12 ( 0%) 0 ( 0%) alias analysis : 0.39 ( 0%) 0.01 ( 0%) 0.40 ( 0%) 11M ( 1%) alias stmt walking : 4.37 ( 4%) 0.06 ( 2%) 4.22 ( 4%) 1366k ( 0%) register scan : 0.05 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 373k ( 0%) rebuild jump labels : 0.05 ( 0%) 0.00 ( 0%) 0.04 ( 0%) 0 ( 0%) preprocessing : 0.29 ( 0%) 0.14 ( 5%) 0.52 ( 0%) 5611k ( 0%) parser (global) : 0.53 ( 0%) 0.13 ( 4%) 0.77 ( 1%) 57M ( 5%) parser struct body : 0.76 ( 1%) 0.03 ( 1%) 0.84 ( 1%) 37M ( 3%) parser enumerator list : 0.00 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 357k ( 0%) parser function body : 0.35 ( 0%) 0.08 ( 3%) 0.30 ( 0%) 9857k ( 1%) parser inl. func. body : 0.21 ( 0%) 0.02 ( 1%) 0.27 ( 0%) 5970k ( 1%) parser inl. meth. body : 0.56 ( 1%) 0.05 ( 2%) 0.58 ( 1%) 25M ( 2%) template instantiation : 4.89 ( 5%) 0.41 ( 14%) 5.22 ( 5%) 261M ( 24%) constant expression evaluation : 0.12 ( 0%) 0.01 ( 0%) 0.13 ( 0%) 1563k ( 0%) early inlining heuristics : 0.28 ( 0%) 0.00 ( 0%) 0.29 ( 0%) 10M ( 1%) inline parameters : 0.55 ( 1%) 0.03 ( 1%) 0.70 ( 1%) 15M ( 1%) integration : 1.70 ( 2%) 0.09 ( 3%) 2.05 ( 2%) 130M ( 12%) tree gimplify : 0.63 ( 1%) 0.04 ( 1%) 0.64 ( 1%) 38M ( 4%) tree eh : 0.27 ( 0%) 0.01 ( 0%) 0.11 ( 0%) 10M ( 1%) tree CFG construction : 0.10 ( 0%) 0.02 ( 1%) 0.18 ( 0%) 17M ( 2%) tree CFG cleanup : 1.23 ( 1%) 0.00 ( 0%) 1.46 ( 1%) 633k ( 0%) tree tail merge : 0.17 ( 0%) 0.00 ( 0%) 0.12 ( 0%) 1772k ( 0%) tree VRP : 2.34 ( 2%) 0.01 ( 0%) 2.53 ( 2%) 14M ( 1%) tree Early VRP : 1.63 ( 2%) 0.08 ( 3%) 1.44 ( 1%) 12M ( 1%) tree copy propagation : 0.39 ( 0%) 0.00 ( 0%) 0.34 ( 0%) 189k ( 0%) tree PTA : 1.71 ( 2%) 0.06 ( 2%) 1.81 ( 2%) 5305k ( 0%) tree PHI insertion : 0.04 ( 0%) 0.00 ( 0%) 0.06 ( 0%) 1826k ( 0%) tree SSA rewrite : 0.42 ( 0%) 0.02 ( 1%) 0.42 ( 0%) 15M ( 1%) tree SSA other : 0.23 ( 0%) 0.00 ( 0%) 0.17 ( 0%) 1597k ( 0%) tree SSA incremental : 0.50 ( 0%) 0.00 ( 0%) 0.54 ( 0%) 3429k ( 0%) tree operand scan : 0.60 ( 1%) 0.01 ( 0%) 0.65 ( 1%) 43M ( 4%) dominator optimization : 2.56 ( 2%) 0.04 ( 1%) 2.72 ( 2%) 12M ( 1%) backwards jump threading : 0.15 ( 0%) 0.00 ( 0%) 0.21 ( 0%) 347k ( 0%) tree SRA : 0.24 ( 0%) 0.00 ( 0%) 0.14 ( 0%) 1084k ( 0%) isolate eroneous paths : 0.03 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 1584 ( 0%) tree CCP : 1.54 ( 1%) 0.02 ( 1%) 1.29 ( 1%) 4451k ( 0%) tree split crit edges : 0.03 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 1578k ( 0%) tree reassociation : 0.08 ( 0%) 0.00 ( 0%) 0.06 ( 0%) 18k ( 0%) tree PRE : 1.87 ( 2%) 0.04 ( 1%) 2.22 ( 2%) 11M ( 1%) tree FRE : 2.53 ( 2%) 0.02 ( 1%) 2.66 ( 2%) 6890k ( 1%) tree code sinking : 0.13 ( 0%) 0.00 ( 0%) 0.13 ( 0%) 1307k ( 0%) tree linearize phis : 0.18 ( 0%) 0.00 ( 0%) 0.11 ( 0%) 993k ( 0%) tree backward propagate : 0.02 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 0 ( 0%) tree forward propagate : 0.76 ( 1%) 0.01 ( 0%) 0.90 ( 1%) 2245k ( 0%) tree phiprop : 0.04 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 19k ( 0%) tree conservative DCE : 0.29 ( 0%) 0.01 ( 0%) 0.38 ( 0%) 449k ( 0%) tree aggressive DCE : 0.39 ( 0%) 0.01 ( 0%) 0.36 ( 0%) 12M ( 1%) tree buildin call DCE : 0.01 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 3504 ( 0%) tree DSE : 1.04 ( 1%) 0.00 ( 0%) 1.16 ( 1%) 339k ( 0%) PHI merge : 0.06 ( 0%) 0.00 ( 0%) 0.11 ( 0%) 128k ( 0%) tree loop optimization : 0.07 ( 0%) 0.00 ( 0%) 0.00 ( 0%) 0 ( 0%) tree loop invariant motion : 0.32 ( 0%) 0.00 ( 0%) 0.33 ( 0%) 117k ( 0%) tree canonical iv : 0.19 ( 0%) 0.00 ( 0%) 0.18 ( 0%) 2167k ( 0%) scev constant prop : 0.10 ( 0%) 0.00 ( 0%) 0.04 ( 0%) 537k ( 0%) complete unrolling : 1.43 ( 1%) 0.02 ( 1%) 1.44 ( 1%) 14M ( 1%) tree loop distribution : 0.38 ( 0%) 0.00 ( 0%) 0.35 ( 0%) 3488k ( 0%) tree iv optimization : 1.36 ( 1%) 0.02 ( 1%) 1.36 ( 1%) 19M ( 2%) tree copy headers : 0.09 ( 0%) 0.00 ( 0%) 0.07 ( 0%) 1438k ( 0%) tree SSA uncprop : 0.06 ( 0%) 0.00 ( 0%) 0.06 ( 0%) 0 ( 0%) tree NRV optimization : 0.00 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 1824 ( 0%) tree SSA verifier : 11.82 ( 11%) 0.24 ( 8%) 12.05 ( 11%) 0 ( 0%) tree STMT verifier : 17.14 ( 16%) 0.47 ( 16%) 16.96 ( 15%) 0 ( 0%) tree switch conversion : 0.04 ( 0%) 0.00 ( 0%) 0.04 ( 0%) 0 ( 0%) tree switch lowering : 0.03 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 0 ( 0%) gimple CSE sin/cos : 0.01 ( 0%) 0.00 ( 0%) 0.03 ( 0%) 0 ( 0%) gimple widening/fma detection : 0.03 ( 0%) 0.00 ( 0%) 0.05 ( 0%) 13k ( 0%) tree strlen optimization : 0.60 ( 1%) 0.01 ( 0%) 0.61 ( 1%) 4021k ( 0%) tree modref : 0.35 ( 0%) 0.02 ( 1%) 0.27 ( 0%) 5652k ( 1%) callgraph verifier : 0.61 ( 1%) 0.03 ( 1%) 0.59 ( 1%) 0 ( 0%) dominance frontiers : 0.01 ( 0%) 0.00 ( 0%) 0.05 ( 0%) 0 ( 0%) dominance computation : 1.20 ( 1%) 0.09 ( 3%) 1.41 ( 1%) 0 ( 0%) control dependences : 0.03 ( 0%) 0.00 ( 0%) 0.04 ( 0%) 0 ( 0%) out of ssa : 0.12 ( 0%) 0.00 ( 0%) 0.12 ( 0%) 59k ( 0%) expand vars : 0.08 ( 0%) 0.00 ( 0%) 0.12 ( 0%) 2916k ( 0%) expand : 0.66 ( 1%) 0.01 ( 0%) 0.64 ( 1%) 30M ( 3%) post expand cleanups : 0.02 ( 0%) 0.00 ( 0%) 0.04 ( 0%) 2280k ( 0%) varconst : 0.02 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 16k ( 0%) lower subreg : 0.03 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 21k ( 0%) jump : 0.00 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 0 ( 0%) forward prop : 0.55 ( 1%) 0.00 ( 0%) 0.72 ( 1%) 284k ( 0%) CSE : 0.46 ( 0%) 0.00 ( 0%) 0.45 ( 0%) 1772k ( 0%) dead code elimination : 0.08 ( 0%) 0.00 ( 0%) 0.10 ( 0%) 0 ( 0%) dead store elim1 : 0.26 ( 0%) 0.00 ( 0%) 0.21 ( 0%) 2756k ( 0%) dead store elim2 : 0.39 ( 0%) 0.00 ( 0%) 0.35 ( 0%) 3977k ( 0%) loop analysis : 0.02 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 0 ( 0%) loop init : 1.83 ( 2%) 0.04 ( 1%) 1.90 ( 2%) 25M ( 2%) loop invariant motion : 0.07 ( 0%) 0.00 ( 0%) 0.10 ( 0%) 145k ( 0%) loop fini : 0.09 ( 0%) 0.00 ( 0%) 0.06 ( 0%) 16k ( 0%) CPROP : 0.67 ( 1%) 0.00 ( 0%) 0.50 ( 0%) 4218k ( 0%) PRE : 0.56 ( 1%) 0.00 ( 0%) 0.54 ( 0%) 1545k ( 0%) CSE 2 : 0.33 ( 0%) 0.00 ( 0%) 0.29 ( 0%) 736k ( 0%) branch prediction : 0.36 ( 0%) 0.02 ( 1%) 0.37 ( 0%) 3272k ( 0%) combiner : 0.68 ( 1%) 0.01 ( 0%) 0.85 ( 1%) 7613k ( 1%) if-conversion : 0.08 ( 0%) 0.00 ( 0%) 0.04 ( 0%) 312k ( 0%) integrated RA : 2.03 ( 2%) 0.01 ( 0%) 2.05 ( 2%) 44M ( 4%) LRA non-specific : 0.55 ( 1%) 0.00 ( 0%) 0.57 ( 1%) 4029k ( 0%) LRA virtuals elimination : 0.21 ( 0%) 0.00 ( 0%) 0.16 ( 0%) 2129k ( 0%) LRA reload inheritance : 0.09 ( 0%) 0.00 ( 0%) 0.09 ( 0%) 391k ( 0%) LRA create live ranges : 0.53 ( 0%) 0.00 ( 0%) 0.53 ( 0%) 417k ( 0%) LRA hard reg assignment : 0.06 ( 0%) 0.00 ( 0%) 0.16 ( 0%) 0 ( 0%) LRA rematerialization : 0.06 ( 0%) 0.00 ( 0%) 0.05 ( 0%) 2128 ( 0%) reload : 0.01 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 0 ( 0%) reload CSE regs : 0.69 ( 1%) 0.00 ( 0%) 0.59 ( 1%) 4376k ( 0%) ree : 0.02 ( 0%) 0.01 ( 0%) 0.05 ( 0%) 47k ( 0%) thread pro- & epilogue : 0.31 ( 0%) 0.00 ( 0%) 0.47 ( 0%) 2591k ( 0%) if-conversion 2 : 0.01 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 11k ( 0%) combine stack adjustments : 0.05 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 0 ( 0%) peephole 2 : 0.05 ( 0%) 0.00 ( 0%) 0.07 ( 0%) 479k ( 0%) hard reg cprop : 0.23 ( 0%) 0.00 ( 0%) 0.17 ( 0%) 36k ( 0%) scheduling 2 : 1.32 ( 1%) 0.02 ( 1%) 1.48 ( 1%) 1897k ( 0%) machine dep reorg : 0.08 ( 0%) 0.00 ( 0%) 0.12 ( 0%) 0 ( 0%) reorder blocks : 0.15 ( 0%) 0.00 ( 0%) 0.11 ( 0%) 1340k ( 0%) shorten branches : 0.13 ( 0%) 0.01 ( 0%) 0.06 ( 0%) 0 ( 0%) final : 0.19 ( 0%) 0.00 ( 0%) 0.22 ( 0%) 6736k ( 1%) variable output : 0.01 ( 0%) 0.00 ( 0%) 0.00 ( 0%) 196k ( 0%) symout : 0.02 ( 0%) 0.00 ( 0%) 0.00 ( 0%) 0 ( 0%) tree if-combine : 0.01 ( 0%) 0.00 ( 0%) 0.02 ( 0%) 17k ( 0%) if to switch conversion : 0.07 ( 0%) 0.00 ( 0%) 0.04 ( 0%) 0 ( 0%) straight-line strength reduction : 0.11 ( 0%) 0.00 ( 0%) 0.07 ( 0%) 56k ( 0%) store merging : 0.38 ( 0%) 0.01 ( 0%) 0.26 ( 0%) 1107k ( 0%) initialize rtl : 0.01 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 12k ( 0%) address lowering : 0.07 ( 0%) 0.00 ( 0%) 0.08 ( 0%) 1586k ( 0%) early local passes : 0.04 ( 0%) 0.01 ( 0%) 0.05 ( 0%) 0 ( 0%) unaccounted optimizations : 0.02 ( 0%) 0.00 ( 0%) 0.00 ( 0%) 0 ( 0%) rest of compilation : 0.99 ( 1%) 0.01 ( 0%) 1.00 ( 1%) 4036k ( 0%) unaccounted late compilation : 0.00 ( 0%) 0.00 ( 0%) 0.01 ( 0%) 0 ( 0%) remove unused locals : 0.21 ( 0%) 0.01 ( 0%) 0.31 ( 0%) 30k ( 0%) address taken : 0.20 ( 0%) 0.00 ( 0%) 0.25 ( 0%) 0 ( 0%) verify loop closed : 0.07 ( 0%) 0.00 ( 0%) 0.05 ( 0%) 0 ( 0%) verify RTL sharing : 1.63 ( 2%) 0.01 ( 0%) 1.62 ( 1%) 0 ( 0%) rebuild frequencies : 0.07 ( 0%) 0.00 ( 0%) 0.06 ( 0%) 31k ( 0%) repair loop structures : 0.14 ( 0%) 0.00 ( 0%) 0.15 ( 0%) 9456 ( 0%) TOTAL : 107.32 2.89 110.44 1097M Extra diagnostic checks enabled; compiler may run slowly. Configure with --enable-checking=release to disable checks. tmp$ [-- Attachment #4: gcc-98664.diff --] [-- Type: text/x-patch, Size: 9481 bytes --] PR middle-end/98664 - inconsistent -Wfree-nonheap-object for inlined calls to system headers gcc/ChangeLog: PR middle-end/98664 * tree-ssa-live.c (remove_unused_scope_block_p): Keep scopes for all functions, even if they're not declared artificial or inline. * tree.c (tree_inlined_location): Use macro expansion location only if scope traversal fails to expose one. gcc/testsuite/ChangeLog: PR middle-end/98664 * gcc.dg/Wvla-larger-than-4.c: Adjust expected output. * gcc.dg/plugin/diagnostic-test-inlining-3.c: Same. * g++.dg/warn/Wfree-nonheap-object-5.C: New test. * gcc.dg/Wfree-nonheap-object-4.c: New test. diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-5.C b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-5.C new file mode 100644 index 00000000000..742dba0cf58 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-5.C @@ -0,0 +1,129 @@ +/* PR middle-end/98664 - inconsistent --Wfree-nonheap-object for inlined + calls to system headers + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +# 7 "Wfree-nonheap-object-5.h" 1 3 + +struct A0 +{ + void *p; + + void f0 (void *q) { p = q; } + void g0 (void) { + __builtin_free (p); // { dg-warning "\\\[-Wfree-nonheap-object" } + } +}; + +struct A1 +{ + void *p; + + void f0 (void *q) { p = q; } + void f1 (void *q) { f0 (q); } + + void g0 (void) { + __builtin_free (p); // { dg-warning "\\\[-Wfree-nonheap-object" } + } + void g1 (void) { g0 (); } +}; + +struct A2 +{ + void *p; + + void f0 (void *q) { p = q; } + void f1 (void *q) { f0 (q); } + void f2 (void *q) { f1 (q); } + + void g0 (void) { + __builtin_free (p); // { dg-warning "\\\[-Wfree-nonheap-object" } + } + void g1 (void) { g0 (); } + void g2 (void) { g1 (); } +}; + +# 47 "Wfree-nonheap-object-5.C" + +#define NOIPA __attribute__ ((noipa)) + +extern int array[]; + +/* Verify the warning is issued even for calls in a system header inlined + into a function outside the header. */ + +NOIPA void warn_g0 (struct A0 *p) +{ + int *q = array + 1; + + p->f0 (q); + p->g0 (); +} + +// { dg-message "inlined from 'void warn_g0\\(A0\\*\\)'" "" { target *-*-* } 0 } + + +/* Also verify the warning can be suppressed. */ + +NOIPA void nowarn_g0 (struct A0 *p) +{ + int *q = array + 2; + + p->f0 (q); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" + p->g0 (); +#pragma GCC diagnostic pop +} + + +NOIPA void warn_g1 (struct A1 *p) +{ + int *q = array + 3; + + p->f1 (q); + p->g1 (); +} + +// { dg-message "inlined from 'void A1::g1\\(\\)'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'void warn_g1\\(A1\\*\\)'" "" { target *-*-* } 0 } + + +NOIPA void nowarn_g1 (struct A2 *p) +{ + int *q = array + 4; + + p->f1 (q); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" + p->g1 (); +#pragma GCC diagnostic pop +} + + +NOIPA void warn_g2 (struct A2 *p) +{ + int *q = array + 5; + + p->f2 (q); + p->g2 (); +} + +// { dg-message "inlined from 'void A2::g1\\(\\)'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'void A2::g2\\(\\)'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'void warn_g2\\(A2\\*\\)'" "" { target *-*-* } 0 } + + +NOIPA void nowarn_g2 (struct A2 *p) +{ + int *q = array + 6; + + p->f2 (q); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" + p->g2 (); +#pragma GCC diagnostic pop +} diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c new file mode 100644 index 00000000000..a7d921248c4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c @@ -0,0 +1,107 @@ +/* PR middle-end/98664 - inconsistent --Wfree-nonheap-object for inlined + calls to system headers + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +# 7 "Wfree-nonheap-object-4.h" 1 3 + +struct A +{ + void *p; +}; + +void f0 (struct A *p, void *q) { p->p = q; } +void f1 (struct A *p, void *q) { f0 (p, q); } +void f2 (struct A *p, void *q) { f1 (p, q); } + +void g0 (struct A *p) +{ + __builtin_free (p->p); // { dg-warning "\\\[-Wfree-nonheap-object" } +} + +void g1 (struct A *p) { g0 (p); } +void g2 (struct A *p) { g1 (p); } + +# 26 "Wfree-nonheap-object-4.c" + +#define NOIPA __attribute__ ((noipa)) + +extern int array[]; + +/* Verify the warning is issued even for calls in a system header inlined + into a function outside the header. */ + +NOIPA void warn_g0 (struct A *p) +{ + int *q = array + 1; + + f0 (p, q); + g0 (p); +} + +// { dg-message "inlined from 'warn_g0'" "" { target *-*-* } 0 } + + +/* Also verify the warning can be suppressed. */ + +NOIPA void nowarn_g0 (struct A *p) +{ + int *q = array + 2; + + f0 (p, q); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" + g0 (p); +#pragma GCC diagnostic pop +} + + +NOIPA void warn_g1 (struct A *p) +{ + int *q = array + 3; + + f1 (p, q); + g1 (p); +} + +// { dg-message "inlined from 'g1'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'warn_g1'" "" { target *-*-* } 0 } + + +NOIPA void nowarn_g1 (struct A *p) +{ + int *q = array + 4; + + f1 (p, q); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" + g1 (p); +#pragma GCC diagnostic pop +} + + +NOIPA void warn_g2 (struct A *p) +{ + int *q = array + 5; + + f2 (p, q); + g2 (p); +} + +// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 } +// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 } + + +NOIPA void nowarn_g2 (struct A *p) +{ + int *q = array + 6; + + f2 (p, q); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" + g2 (p); +#pragma GCC diagnostic pop +} diff --git a/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c b/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c index de99afbe56e..7d27829736f 100644 --- a/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c +++ b/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c @@ -17,14 +17,14 @@ static inline void inline_use_vla (unsigned n) static inline void use_inlined_vla (unsigned n) { inline_use_vla (n); // this call is okay - inline_use_vla (n + 1); // this one is not + inline_use_vla (n + 1); // this one is not (line 20) } void call_inline (void) { - use_inlined_vla (31); + use_inlined_vla (31); // line 25 } /* Verify that the inlining context is included and that it points to the correct line number in the inlined function: - { dg-message "function 'inline_use_vla'..*inlined from 'call_inline' .*:20:" "" { target *-*-* } 0 } */ + { dg-message "function 'inline_use_vla'.*inlined from 'use_inlined_vla'.*:20:.*inlined from 'call_inline' .*:25:" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c index e1a4fca2cb4..56c9546fb84 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c @@ -35,7 +35,8 @@ int main() This test case captures this behavior. */ /* { dg-regexp "In function 'foo'," "" } */ -/* { dg-regexp " inlined from 'main' at .+/diagnostic-test-inlining-3.c:15:3:" "" } */ +/* { dg-regexp " inlined from 'bar' at .+/diagnostic-test-inlining-3.c:15:3," "" } */ +/* { dg-regexp " inlined from 'main' at .+/diagnostic-test-inlining-3.c:20:3:" "" } */ /* { dg-warning "3: message" "" { target *-*-* } 9 } */ /* { dg-begin-multiline-output "" } __emit_warning ("message"); diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index 02a7a56f0f9..5f58bfb9168 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -555,19 +555,17 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block) ; /* When not generating debug info we can eliminate info on unused variables. */ - else if (!flag_auto_profile && debug_info_level == DINFO_LEVEL_NONE + 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. */ + /* Even for -g0 don't prune outer scopes from inlined functions, + otherwise late diagnostics from such functions will not be + emitted or suppressed 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))) + tree orig = BLOCK_ORIGIN (scope); + if (TREE_CODE (orig) == FUNCTION_DECL) unused = false; } } diff --git a/gcc/tree.c b/gcc/tree.c index a25c71f1152..061fe43aa31 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -12638,10 +12638,13 @@ tree_inlined_location (tree exp, bool system_header /* = true */) } if (loc == UNKNOWN_LOCATION) - loc = EXPR_LOCATION (exp); - - if (system_header) - return expansion_point_location_if_in_system_header (loc); + { + loc = EXPR_LOCATION (exp); + if (system_header) + /* Only consider macro expansion when the block traversal failed + to find a location. Otherwise it's not relevant. */ + return expansion_point_location_if_in_system_header (loc); + } return loc; } ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] keep scope blocks for all inlined functions (PR 98664) 2021-01-17 0:46 ` Martin Sebor @ 2021-01-18 13:25 ` Richard Biener 2021-01-21 21:52 ` [PATCH] document BLOCK_ABSTRACT_ORIGIN et al Martin Sebor 0 siblings, 1 reply; 12+ messages in thread From: Richard Biener @ 2021-01-18 13:25 UTC (permalink / raw) To: Martin Sebor; +Cc: Jeff Law, Jakub Jelinek, gcc-patches On Sun, Jan 17, 2021 at 1:46 AM Martin Sebor <msebor@gmail.com> wrote: > > On 1/15/21 12:44 AM, Richard Biener wrote: > > On Thu, Jan 14, 2021 at 8:13 PM Martin Sebor via Gcc-patches > > <gcc-patches@gcc.gnu.org> wrote: > >> > >> One aspect of PR 98465 - Bogus warning stringop-overread for std::string > >> is the inconsistency between -g and -g0 which turns out to be due to > >> GCC eliminating apparently unused scope blocks from inlined functions > >> that aren't explicitly declared inline and artificial. PR 98664 tracks > >> just this part of PR 98465. > >> > >> To resolve just the PR 98664 subset the attached change has > >> the tree-ssa-live.c pass preserve these blocks for all inlined > >> functions, not just artificial ones. Besides avoiding the interaction > >> between -g and warnings it also seems to improve the inlining context > >> by including more inlined call sites. This can be seen in the adjusted > >> tests. (Its effect on PR 98465 is that the false positive is issued > >> consistently, regardless of -g. Avoiding the false positive is my > >> next step.) > >> > >> Jakub, you raised a concern yesterday in PR 98465 c#13 about the memory > >> footprint of this change. Can you please comment on whether it's in > >> line with what you were suggesting? > > > > { > > tree ao = BLOCK_ABSTRACT_ORIGIN (block); > > - if (TREE_CODE (ao) == FUNCTION_DECL) > > - loc = BLOCK_SOURCE_LOCATION (block); > > - else if (TREE_CODE (ao) != BLOCK) > > - break; > > + if (TREE_CODE (ao) == FUNCTION_DECL) > > + loc = BLOCK_SOURCE_LOCATION (block); > > + else if (TREE_CODE (ao) != BLOCK) > > + break; > > > > you are replacing tabs with spaces? > > > > @@ -558,16 +558,13 @@ remove_unused_scope_block_p (tree scope, bool > > in_ctor_dtor_block) > > 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. */ > > + /* Even for -g0 don't prune outer scopes from inlined functions, > > + otherwise late diagnostics from such functions will not be > > + emitted or suppressed 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))) > > + if (ao && TREE_CODE (ao) == FUNCTION_DECL) > > unused = false; > > } > > } > > > > so which inlined_function_outer_scope_p are you _not_ marking now? > > BLOCK_ORIGIN is never NULL and all inlined scopes should have > > an abstract origin - I believe always a FUNCTIN_DECL. Which means > > you could have simplified it further? > > Quite possibly. I could find no documentation for these macros so > I tried to keep my changes conservative. I did put together some > notes to document what I saw the macros evaluate to in my testing > (below). If/when it's close to accurate I'd like to add them to > tree.h and to the internals manual. > > > And yes, the main reason for the code above is memory use for > > C++ with lots of inlining. I suggest to try the patch on tramp3d > > for example (there's about 10 inline instances per emitted > > assembly op). > > This one: > https://github.com/llvm-mirror/test-suite/tree/master/MultiSource/Benchmarks/tramp3d-v4 > ? yeah > With the patch, 69,022 more blocks with distinct numbers are kept > than without it. I see some small differences in -fmem-report > and -ftime-report output: > > Total: 286 -> 288M 210 -> 211M 3993 -> 4019k > > I'm not really sure what to look at so I attach the two reports > for you to judge for yourself. A build with --enable-gather-detailed-mem-stats would have given statistics on BLOCK trees I think, otherwise -fmem-report is not too useful but I guess the above overall stat tell us the overhead is manageable. > I also attach an updated patch with the slight simplification you > suggested. So I was even suggesting to do if (inlined_function_outer_scope_p (scope)) unused = false; and maybe gcc_assert (TREE_CODE (orig) == FUNCTION_DECL) but I think the patch is OK as updated. > Martin > > PS Here are my notes on the macros and the two related functions: > > BLOCK: Denotes a lexical scope. Contains BLOCK_VARS of variables > declared in it, BLOCK_SUBBLOCKS of scopes nested in it, and > BLOCK_CHAIN pointing to the next BLOCK. Its BLOCK_SUPERCONTEXT > point to the BLOCK of the enclosing scope. May have > a BLOCK_ABSTRACT_ORIGIN and a BLOCK_SOURCE_LOCATION. > > BLOCK_SUPERCONTEXT: The scope of the enclosing block, or FUNCTION_DECL > for the "outermost" function scope. Inlined functions are chained by > this so that given expression E and its TREE_BLOCK(E) B, > BLOCK_SUPERCONTEXT(B) is the scope (BLOCK) in which E has been made > or into which E has been inlined. In the latter case, > > BLOCK_ORIGIN(B) evaluates either to the enclosing BLOCK or to > the enclosing function DECL. It's never null. > > BLOCK_ABSTRACT_ORIGIN(B) is the FUNCTION_DECL of the function into > which it has been inlined, or null if B is not inlined. It's the BLOCK or FUNCTION it was inlined _from_, not were it was inlined to. It's the "ultimate" source, thus the abstract copy of the block or function decl (for the outermost scope, aka inlined_function_outer_scope_p). It corresponds to what you'd expect for the DWARF abstract origin. BLOCK_ABSTRACT_ORIGIN can be NULL (in case it isn't an inline instance). > BLOCK_ABSTRACT_ORIGIN: A BLOCK, or FUNCTION_DECL of the function > into which a block has been inlined. In a BLOCK immediately enclosing > an inlined leaf expression points to the outermost BLOCK into which it > has been inlined (thus bypassing all intermediate BLOCK_SUPERCONTEXTs). > > BLOCK_FRAGMENT_ORIGIN: ??? > BLOCK_FRAGMENT_CHAIN: ??? that's for scope blocks split by hot/cold partitioning and only temporarily populated. > bool inlined_function_outer_scope_p(BLOCK) [tree.h] > Returns true if a BLOCK has a source location. > True for all but the innermost (no SUBBLOCKs?) and outermost blocks > into which an expression has been inlined. (Is this always true?) > > tree block_ultimate_origin(BLOCK) [tree.c] > Returns BLOCK_ABSTRACT_ORIGIN(BLOCK), AO, after asserting that > (DECL_P(AO) && DECL_ORIGIN(AO) == AO) || BLOCK_ORIGIN(AO) == AO). ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] document BLOCK_ABSTRACT_ORIGIN et al. 2021-01-18 13:25 ` Richard Biener @ 2021-01-21 21:52 ` Martin Sebor 2021-01-28 0:54 ` Martin Sebor 0 siblings, 1 reply; 12+ messages in thread From: Martin Sebor @ 2021-01-21 21:52 UTC (permalink / raw) To: Richard Biener; +Cc: Jeff Law, Jakub Jelinek, gcc-patches [-- Attachment #1: Type: text/plain, Size: 2695 bytes --] On 1/18/21 6:25 AM, Richard Biener wrote: >> PS Here are my notes on the macros and the two related functions: >> >> BLOCK: Denotes a lexical scope. Contains BLOCK_VARS of variables >> declared in it, BLOCK_SUBBLOCKS of scopes nested in it, and >> BLOCK_CHAIN pointing to the next BLOCK. Its BLOCK_SUPERCONTEXT >> point to the BLOCK of the enclosing scope. May have >> a BLOCK_ABSTRACT_ORIGIN and a BLOCK_SOURCE_LOCATION. >> >> BLOCK_SUPERCONTEXT: The scope of the enclosing block, or FUNCTION_DECL >> for the "outermost" function scope. Inlined functions are chained by >> this so that given expression E and its TREE_BLOCK(E) B, >> BLOCK_SUPERCONTEXT(B) is the scope (BLOCK) in which E has been made >> or into which E has been inlined. In the latter case, >> >> BLOCK_ORIGIN(B) evaluates either to the enclosing BLOCK or to >> the enclosing function DECL. It's never null. >> >> BLOCK_ABSTRACT_ORIGIN(B) is the FUNCTION_DECL of the function into >> which it has been inlined, or null if B is not inlined. > > It's the BLOCK or FUNCTION it was inlined _from_, not were it was inlined to. > It's the "ultimate" source, thus the abstract copy of the block or function decl > (for the outermost scope, aka inlined_function_outer_scope_p). It corresponds > to what you'd expect for the DWARF abstract origin. Thanks for the correction! It's just the "innermost" block that points to the "ultimate" destination into which it's been inlined. > > BLOCK_ABSTRACT_ORIGIN can be NULL (in case it isn't an inline instance). > >> BLOCK_ABSTRACT_ORIGIN: A BLOCK, or FUNCTION_DECL of the function >> into which a block has been inlined. In a BLOCK immediately enclosing >> an inlined leaf expression points to the outermost BLOCK into which it >> has been inlined (thus bypassing all intermediate BLOCK_SUPERCONTEXTs). >> >> BLOCK_FRAGMENT_ORIGIN: ??? >> BLOCK_FRAGMENT_CHAIN: ??? > > that's for scope blocks split by hot/cold partitioning and only temporarily > populated. Thanks, I now see these documented in detail in tree.h. > >> bool inlined_function_outer_scope_p(BLOCK) [tree.h] >> Returns true if a BLOCK has a source location. >> True for all but the innermost (no SUBBLOCKs?) and outermost blocks >> into which an expression has been inlined. (Is this always true?) >> >> tree block_ultimate_origin(BLOCK) [tree.c] >> Returns BLOCK_ABSTRACT_ORIGIN(BLOCK), AO, after asserting that >> (DECL_P(AO) && DECL_ORIGIN(AO) == AO) || BLOCK_ORIGIN(AO) == AO). The attached diff adds the comments above to tree.h. I looked for a good place in the manual to add the same text but I'm not sure. Would the Blocks @subsection in generic.texi be appropriate? Martin [-- Attachment #2: gcc-block-abstract-origin.diff --] [-- Type: text/x-patch, Size: 2384 bytes --] diff --git a/gcc/tree.h b/gcc/tree.h index 02b03d1f68e..0dd2196008b 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1912,18 +1912,29 @@ class auto_suppress_location_wrappers #define OMP_CLAUSE_OPERAND(NODE, I) \ OMP_CLAUSE_ELT_CHECK (NODE, I) -/* In a BLOCK node. */ +/* In a BLOCK (scope) node: + Variables declared in the scope NODE. */ #define BLOCK_VARS(NODE) (BLOCK_CHECK (NODE)->block.vars) #define BLOCK_NONLOCALIZED_VARS(NODE) \ (BLOCK_CHECK (NODE)->block.nonlocalized_vars) #define BLOCK_NUM_NONLOCALIZED_VARS(NODE) \ vec_safe_length (BLOCK_NONLOCALIZED_VARS (NODE)) #define BLOCK_NONLOCALIZED_VAR(NODE,N) (*BLOCK_NONLOCALIZED_VARS (NODE))[N] +/* A chain of BLOCKs (scopes) nested within the scope NODE. */ #define BLOCK_SUBBLOCKS(NODE) (BLOCK_CHECK (NODE)->block.subblocks) +/* The scope enclosing the scope NODE, or FUNCTION_DECL for the "outermost" + function scope. Inlined functions are chained by this so that given + expression E and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope + in which E has been made or into which E has been inlined. */ #define BLOCK_SUPERCONTEXT(NODE) (BLOCK_CHECK (NODE)->block.supercontext) +/* Points to the next scope at the same level of nesting as scope NODE. */ #define BLOCK_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.chain) +/* A BLOCK, or FUNCTION_DECL of the function from which a block has been + inlined. In a scope immediately enclosing an inlined leaf expression, + points to the outermost scope into which it has been inlined (thus + bypassing all intermediate BLOCK_SUPERCONTEXTs). */ #define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.abstract_origin) -#define BLOCK_ORIGIN(NODE) \ +#define BLOCK_ORIGIN(NODE) \ (BLOCK_ABSTRACT_ORIGIN(NODE) ? BLOCK_ABSTRACT_ORIGIN(NODE) : (NODE)) #define BLOCK_DIE(NODE) (BLOCK_CHECK (NODE)->block.die) @@ -5078,7 +5089,10 @@ function_args_iter_next (function_args_iterator *i) i->next = TREE_CHAIN (i->next); } -/* We set BLOCK_SOURCE_LOCATION only to inlined function entry points. */ +/* Returns true if a BLOCK has a source location. + BLOCK_SOURCE_LOCATION is set only to inlined function entry points, + so the function returns true for all but the innermost and outermost + blocks into which an expression has been inlined. */ static inline bool inlined_function_outer_scope_p (const_tree block) ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] document BLOCK_ABSTRACT_ORIGIN et al. 2021-01-21 21:52 ` [PATCH] document BLOCK_ABSTRACT_ORIGIN et al Martin Sebor @ 2021-01-28 0:54 ` Martin Sebor 2021-02-01 16:20 ` Martin Sebor 0 siblings, 1 reply; 12+ messages in thread From: Martin Sebor @ 2021-01-28 0:54 UTC (permalink / raw) To: Richard Biener; +Cc: Jeff Law, Jakub Jelinek, gcc-patches [-- Attachment #1: Type: text/plain, Size: 2994 bytes --] Attached is an updated patch for both tree.h and the internals manual documenting the most important BLOCK_ macros and what they represent. On 1/21/21 2:52 PM, Martin Sebor wrote: > On 1/18/21 6:25 AM, Richard Biener wrote: >>> PS Here are my notes on the macros and the two related functions: >>> >>> BLOCK: Denotes a lexical scope. Contains BLOCK_VARS of variables >>> declared in it, BLOCK_SUBBLOCKS of scopes nested in it, and >>> BLOCK_CHAIN pointing to the next BLOCK. Its BLOCK_SUPERCONTEXT >>> point to the BLOCK of the enclosing scope. May have >>> a BLOCK_ABSTRACT_ORIGIN and a BLOCK_SOURCE_LOCATION. >>> >>> BLOCK_SUPERCONTEXT: The scope of the enclosing block, or FUNCTION_DECL >>> for the "outermost" function scope. Inlined functions are chained by >>> this so that given expression E and its TREE_BLOCK(E) B, >>> BLOCK_SUPERCONTEXT(B) is the scope (BLOCK) in which E has been made >>> or into which E has been inlined. In the latter case, >>> >>> BLOCK_ORIGIN(B) evaluates either to the enclosing BLOCK or to >>> the enclosing function DECL. It's never null. >>> >>> BLOCK_ABSTRACT_ORIGIN(B) is the FUNCTION_DECL of the function into >>> which it has been inlined, or null if B is not inlined. >> >> It's the BLOCK or FUNCTION it was inlined _from_, not were it was >> inlined to. >> It's the "ultimate" source, thus the abstract copy of the block or >> function decl >> (for the outermost scope, aka inlined_function_outer_scope_p). It >> corresponds >> to what you'd expect for the DWARF abstract origin. > > Thanks for the correction! It's just the "innermost" block that > points to the "ultimate" destination into which it's been inlined. > >> >> BLOCK_ABSTRACT_ORIGIN can be NULL (in case it isn't an inline instance). >> >>> BLOCK_ABSTRACT_ORIGIN: A BLOCK, or FUNCTION_DECL of the function >>> into which a block has been inlined. In a BLOCK immediately enclosing >>> an inlined leaf expression points to the outermost BLOCK into which it >>> has been inlined (thus bypassing all intermediate BLOCK_SUPERCONTEXTs). >>> >>> BLOCK_FRAGMENT_ORIGIN: ??? >>> BLOCK_FRAGMENT_CHAIN: ??? >> >> that's for scope blocks split by hot/cold partitioning and only >> temporarily >> populated. > > Thanks, I now see these documented in detail in tree.h. > >> >>> bool inlined_function_outer_scope_p(BLOCK) [tree.h] >>> Returns true if a BLOCK has a source location. >>> True for all but the innermost (no SUBBLOCKs?) and outermost blocks >>> into which an expression has been inlined. (Is this always true?) >>> >>> tree block_ultimate_origin(BLOCK) [tree.c] >>> Returns BLOCK_ABSTRACT_ORIGIN(BLOCK), AO, after asserting that >>> (DECL_P(AO) && DECL_ORIGIN(AO) == AO) || BLOCK_ORIGIN(AO) == AO). > > The attached diff adds the comments above to tree.h. > > I looked for a good place in the manual to add the same text but I'm > not sure. Would the Blocks @subsection in generic.texi be appropriate? > > Martin [-- Attachment #2: gcc-block-abstract-origin.diff --] [-- Type: text/x-patch, Size: 8855 bytes --] Document various BLOCK macros. gcc/ChangeLog: * doc/generic.texi (Function Basics): Mention BLOCK_SUBBLOCKS, BLOCK_VARS, BLOCK_SUPERCONTEXT, and BLOCK_ABSTRACT_ORIGIN. * doc/gimple.texi (GIMPLE): Update. Mention free_lang_data pass. * tree.h (BLOCK_VARS): Add comment. (BLOCK_SUBBLOCKS): Same. (BLOCK_SUPERCONTEXT): Same. (BLOCK_ABSTRACT_ORIGIN): Same. (inlined_function_outer_scope_p): Same. diff --git a/gcc/tree.h b/gcc/tree.h index 02b03d1f68e..0dd2196008b 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1912,18 +1912,29 @@ class auto_suppress_location_wrappers #define OMP_CLAUSE_OPERAND(NODE, I) \ OMP_CLAUSE_ELT_CHECK (NODE, I) -/* In a BLOCK node. */ +/* In a BLOCK (scope) node: + Variables declared in the scope NODE. */ #define BLOCK_VARS(NODE) (BLOCK_CHECK (NODE)->block.vars) #define BLOCK_NONLOCALIZED_VARS(NODE) \ (BLOCK_CHECK (NODE)->block.nonlocalized_vars) #define BLOCK_NUM_NONLOCALIZED_VARS(NODE) \ vec_safe_length (BLOCK_NONLOCALIZED_VARS (NODE)) #define BLOCK_NONLOCALIZED_VAR(NODE,N) (*BLOCK_NONLOCALIZED_VARS (NODE))[N] +/* A chain of BLOCKs (scopes) nested within the scope NODE. */ #define BLOCK_SUBBLOCKS(NODE) (BLOCK_CHECK (NODE)->block.subblocks) +/* The scope enclosing the scope NODE, or FUNCTION_DECL for the "outermost" + function scope. Inlined functions are chained by this so that given + expression E and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope + in which E has been made or into which E has been inlined. */ #define BLOCK_SUPERCONTEXT(NODE) (BLOCK_CHECK (NODE)->block.supercontext) +/* Points to the next scope at the same level of nesting as scope NODE. */ #define BLOCK_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.chain) +/* A BLOCK, or FUNCTION_DECL of the function from which a block has been + inlined. In a scope immediately enclosing an inlined leaf expression, + points to the outermost scope into which it has been inlined (thus + bypassing all intermediate BLOCK_SUPERCONTEXTs). */ #define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.abstract_origin) -#define BLOCK_ORIGIN(NODE) \ +#define BLOCK_ORIGIN(NODE) \ (BLOCK_ABSTRACT_ORIGIN(NODE) ? BLOCK_ABSTRACT_ORIGIN(NODE) : (NODE)) #define BLOCK_DIE(NODE) (BLOCK_CHECK (NODE)->block.die) @@ -5078,7 +5089,10 @@ function_args_iter_next (function_args_iterator *i) i->next = TREE_CHAIN (i->next); } -/* We set BLOCK_SOURCE_LOCATION only to inlined function entry points. */ +/* Returns true if a BLOCK has a source location. + BLOCK_SOURCE_LOCATION is set only to inlined function entry points, + so the function returns true for all but the innermost and outermost + blocks into which an expression has been inlined. */ static inline bool inlined_function_outer_scope_p (const_tree block) diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi index 642cbc83fe4..6be5e4c16ab 100644 --- a/gcc/doc/generic.texi +++ b/gcc/doc/generic.texi @@ -2570,12 +2570,17 @@ A function that has a definition in the current translation unit will have a non-@code{NULL} @code{DECL_INITIAL}. However, back ends should not make use of the particular value given by @code{DECL_INITIAL}. -It should contain a tree of @code{BLOCK} nodes that mirrors the scopes -that variables are bound in the function. Each block contains a list -of decls declared in a basic block, a pointer to a chain of blocks at -the next lower scope level, then a pointer to the next block at the -same level and a backpointer to the parent @code{BLOCK} or -@code{FUNCTION_DECL}. So given a function as follows: +@code{DECL_INITIAL} is a @code{BLOCK} tree node corresponding to +the outermost scope of the function definition. A @code{BLOCK} may contain +other blocks accessible by @code{BLOCK_SUBBLOCKS} and corresponding to +the scopes nested within it, a list of decls declared in a basic block +and accessible as @code{BLOCK_VARS}, a pointer to a chain of blocks at +the next lower scope level accessible as @code{BLOCK_SUBBLOCKS}, and +a pointer to the next block at the same level accessible as +@code{BLOCK_CHAIN}. Any of these trees may be null. In addition, +each @code{BLOCK} has a nonnull backpointer to the parent @code{BLOCK} +or @code{FUNCTION_DECL} (@code{BLOCK_SUPERCONTEXT}). For example, given +a function as follows: @smallexample void foo() @@ -2609,6 +2614,82 @@ BLOCK_SUPERCONTEXT(block_c) = foo; DECL_INITIAL(foo) = block_a; @end smallexample +Besides nesting lexical scopes, @code{BLOCK}s may be chained by +@code{BLOCK_ORIGIN} and @code{BLOCK_ABSTRACT_ORIGIN} during function +inlining to provide context in middle end diagnostic messages. + +@code{BLOCK_ABSTRACT_ORIGIN} is either a @code{BLOCK}, or +a @code{FUNCTION_DECL} of the function from which a block has been inlined. +In a scope immediately enclosing an inlined leaf expression, it points to +the outermost scope into which it has been inlined (thus bypassing all +intermediate @code{BLOCK_SUPERCONTEXT}s). For example, when all the calls +to the following functions are inlined + +@smallexample +void f0 (char *p, int n) @{ + memset (p, 1, n); // a.c:2:3 +@} + +void f1 (char *p, int n) @{ + f0 (p + 1, n + 1); // a.c:6:3 +@} + +void f2 (char *p, int n) @{ + f1 (p + 1, n + 1); // a.c:10:3 +@} + +char a[6]; + +void f3 (void) @{ + f2 (a, 3); // a.c:16:3 +@} +@end smallexample + +the result is the following output showing the inlining context + +@smallexample +In function 'f0', + inlined from 'f2' at a.c:6:3, + inlined from 'f3' at a.c:16:3: +a.c:2:3: warning: 'memset' writing 5 bytes into a region of size 4 overflows the destination [-Wstringop-overflow=] + 2 | memset (p, 1, n); + | ^~~~~~~~~~~~~~~~ +a.c: In function 'f3': +a.c:13:6: note: at offset 2 into destination object 'a' of size 6 + 13 | char a[6]; + | ^ +@end smallexample + +The context is made possible by the following arrangement of blocks. + +@smallexample + CALL_EXPR + memset (p, 1, n); | f0:2:3 + + BLOCK #13 | f0 + SUPERCONTEXT: BLOCK #12 + ABSTRACT_ORIGIN: BLOCK #0 + + BLOCK #12 [/build/tmp/a.c:6:3] | f1 + SUPERCONTEXT: BLOCK #10 + SUBBLOCKS: BLOCK #13 + ABSTRACT_ORIGIN: f0 + + BLOCK #10 [/build/tmp/a.c:10:3] | f2 + SUPERCONTEXT: BLOCK #8 + SUBBLOCKS: BLOCK #12 + ABSTRACT_ORIGIN: f1 + + BLOCK #8 [/build/tmp/a.c:16:3] | f3 + SUPERCONTEXT: BLOCK #0 + SUBBLOCKS: BLOCK #10 + ABSTRACT_ORIGIN: f2 + +BLOCK #0 | f3 + SUPERCONTEXT: f3 + SUBBLOCKS: BLOCK #8 +@end smallexample + @end ftable @c --------------------------------------------------------------------- diff --git a/gcc/doc/gimple.texi b/gcc/doc/gimple.texi index 4b3d7d7452e..02cd4e65727 100644 --- a/gcc/doc/gimple.texi +++ b/gcc/doc/gimple.texi @@ -17,8 +17,11 @@ choices. For one thing, SIMPLE doesn't support @code{goto}. Temporaries are introduced to hold intermediate values needed to compute complex expressions. Additionally, all the control structures used in GENERIC are lowered into conditional jumps, -lexical scopes are removed and exception regions are converted -into an on the side exception region tree. +lexical scopes other than at the function definition level are +removed, and exception regions are converted into an on the side +exception region tree. Nested scopes may be retained independently +of the GIMPLE representation. They are accessible as @code{BLOCK}s +via @code{DECL_INITIAL} of each function definition. The compiler pass which converts GENERIC into GIMPLE is referred to as the @samp{gimplifier}. The gimplifier works recursively, generating @@ -33,7 +36,7 @@ representation than abstract syntax trees (AST), therefore it does not require the full structural complexity provided by the main tree data structure. -The GENERIC representation of a function is stored in the +The GENERIC representation of a function definition is stored in the @code{DECL_SAVED_TREE} field of the associated @code{FUNCTION_DECL} tree node. It is converted to GIMPLE by a call to @code{gimplify_function_tree}. @@ -45,6 +48,8 @@ convert the front end trees to GIMPLE@. Usually such a hook will involve much of the same code for expanding front end trees to RTL@. This function can return fully lowered GIMPLE, or it can return GENERIC trees and let the main gimplifier lower them the rest of the way; this is often simpler. +Other language-specific tree codes should be removed by each front end +before gimplification no later than by the @code{free_lang_data} pass. GIMPLE that is not fully lowered is known as ``High GIMPLE'' and consists of the IL before the pass @code{pass_lower_cf}. High GIMPLE contains some container statements like lexical scopes ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] document BLOCK_ABSTRACT_ORIGIN et al. 2021-01-28 0:54 ` Martin Sebor @ 2021-02-01 16:20 ` Martin Sebor 2021-02-03 12:01 ` Richard Biener 0 siblings, 1 reply; 12+ messages in thread From: Martin Sebor @ 2021-02-01 16:20 UTC (permalink / raw) To: Richard Biener; +Cc: Jeff Law, Jakub Jelinek, gcc-patches I have pushed the tree.h comments in g:6a2053773b8. I will wait for an approval of the changes to the manual. On 1/27/21 5:54 PM, Martin Sebor wrote: > Attached is an updated patch for both tree.h and the internals manual > documenting the most important BLOCK_ macros and what they represent. > > On 1/21/21 2:52 PM, Martin Sebor wrote: >> On 1/18/21 6:25 AM, Richard Biener wrote: >>>> PS Here are my notes on the macros and the two related functions: >>>> >>>> BLOCK: Denotes a lexical scope. Contains BLOCK_VARS of variables >>>> declared in it, BLOCK_SUBBLOCKS of scopes nested in it, and >>>> BLOCK_CHAIN pointing to the next BLOCK. Its BLOCK_SUPERCONTEXT >>>> point to the BLOCK of the enclosing scope. May have >>>> a BLOCK_ABSTRACT_ORIGIN and a BLOCK_SOURCE_LOCATION. >>>> >>>> BLOCK_SUPERCONTEXT: The scope of the enclosing block, or FUNCTION_DECL >>>> for the "outermost" function scope. Inlined functions are chained by >>>> this so that given expression E and its TREE_BLOCK(E) B, >>>> BLOCK_SUPERCONTEXT(B) is the scope (BLOCK) in which E has been made >>>> or into which E has been inlined. In the latter case, >>>> >>>> BLOCK_ORIGIN(B) evaluates either to the enclosing BLOCK or to >>>> the enclosing function DECL. It's never null. >>>> >>>> BLOCK_ABSTRACT_ORIGIN(B) is the FUNCTION_DECL of the function into >>>> which it has been inlined, or null if B is not inlined. >>> >>> It's the BLOCK or FUNCTION it was inlined _from_, not were it was >>> inlined to. >>> It's the "ultimate" source, thus the abstract copy of the block or >>> function decl >>> (for the outermost scope, aka inlined_function_outer_scope_p). It >>> corresponds >>> to what you'd expect for the DWARF abstract origin. >> >> Thanks for the correction! It's just the "innermost" block that >> points to the "ultimate" destination into which it's been inlined. >> >>> >>> BLOCK_ABSTRACT_ORIGIN can be NULL (in case it isn't an inline instance). >>> >>>> BLOCK_ABSTRACT_ORIGIN: A BLOCK, or FUNCTION_DECL of the function >>>> into which a block has been inlined. In a BLOCK immediately enclosing >>>> an inlined leaf expression points to the outermost BLOCK into which it >>>> has been inlined (thus bypassing all intermediate BLOCK_SUPERCONTEXTs). >>>> >>>> BLOCK_FRAGMENT_ORIGIN: ??? >>>> BLOCK_FRAGMENT_CHAIN: ??? >>> >>> that's for scope blocks split by hot/cold partitioning and only >>> temporarily >>> populated. >> >> Thanks, I now see these documented in detail in tree.h. >> >>> >>>> bool inlined_function_outer_scope_p(BLOCK) [tree.h] >>>> Returns true if a BLOCK has a source location. >>>> True for all but the innermost (no SUBBLOCKs?) and outermost blocks >>>> into which an expression has been inlined. (Is this always true?) >>>> >>>> tree block_ultimate_origin(BLOCK) [tree.c] >>>> Returns BLOCK_ABSTRACT_ORIGIN(BLOCK), AO, after asserting that >>>> (DECL_P(AO) && DECL_ORIGIN(AO) == AO) || BLOCK_ORIGIN(AO) == AO). >> >> The attached diff adds the comments above to tree.h. >> >> I looked for a good place in the manual to add the same text but I'm >> not sure. Would the Blocks @subsection in generic.texi be appropriate? >> >> Martin > > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] document BLOCK_ABSTRACT_ORIGIN et al. 2021-02-01 16:20 ` Martin Sebor @ 2021-02-03 12:01 ` Richard Biener 2021-02-03 17:12 ` Martin Sebor 0 siblings, 1 reply; 12+ messages in thread From: Richard Biener @ 2021-02-03 12:01 UTC (permalink / raw) To: Martin Sebor; +Cc: Jeff Law, Jakub Jelinek, gcc-patches On Mon, Feb 1, 2021 at 5:20 PM Martin Sebor <msebor@gmail.com> wrote: > > I have pushed the tree.h comments in g:6a2053773b8. I will wait > for an approval of the changes to the manual. Sorry for not looking earlier. +/* The scope enclosing the scope NODE, or FUNCTION_DECL for the "outermost" + function scope. Inlined functions are chained by this so that given + expression E and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope + in which E has been made or into which E has been inlined. */ I can't really understand what you are trying to say with the second sentence. There's nothing really special about BLOCK_SUPERCONTEXT and inlines so I believe this sentence only adds confusion. #define BLOCK_SUPERCONTEXT(NODE) (BLOCK_CHECK (NODE)->block.supercontext) +/* Points to the next scope at the same level of nesting as scope NODE. */ #define BLOCK_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.chain) +/* A BLOCK, or FUNCTION_DECL of the function from which a block has been + inlined. ... from which a block has been ultimatively copied for example by inlining. [clones also will have abstract origins] In a scope immediately enclosing an inlined leaf expression, + points to the outermost scope into which it has been inlined (thus + bypassing all intermediate BLOCK_SUPERCONTEXTs). */ ? Maybe: An inlined function is represented by a scope with BLOCK_ABSTRACT_ORIGIN being the FUNCTION_DECL of the inlined function containing the inlined functions scope tree as children. All abstract origins are ultimate, that is BLOCK_ABSTRACT_ORIGIN(NODE) == BLOCK_ABSTRACT_ORIGIN(BLOCK_ABSTRACT_ORIGIN (NODE)). #define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.abstract_origin) > On 1/27/21 5:54 PM, Martin Sebor wrote: > > Attached is an updated patch for both tree.h and the internals manual > > documenting the most important BLOCK_ macros and what they represent. > > > > On 1/21/21 2:52 PM, Martin Sebor wrote: > >> On 1/18/21 6:25 AM, Richard Biener wrote: > >>>> PS Here are my notes on the macros and the two related functions: > >>>> > >>>> BLOCK: Denotes a lexical scope. Contains BLOCK_VARS of variables > >>>> declared in it, BLOCK_SUBBLOCKS of scopes nested in it, and > >>>> BLOCK_CHAIN pointing to the next BLOCK. Its BLOCK_SUPERCONTEXT > >>>> point to the BLOCK of the enclosing scope. May have > >>>> a BLOCK_ABSTRACT_ORIGIN and a BLOCK_SOURCE_LOCATION. > >>>> > >>>> BLOCK_SUPERCONTEXT: The scope of the enclosing block, or FUNCTION_DECL > >>>> for the "outermost" function scope. Inlined functions are chained by > >>>> this so that given expression E and its TREE_BLOCK(E) B, > >>>> BLOCK_SUPERCONTEXT(B) is the scope (BLOCK) in which E has been made > >>>> or into which E has been inlined. In the latter case, > >>>> > >>>> BLOCK_ORIGIN(B) evaluates either to the enclosing BLOCK or to > >>>> the enclosing function DECL. It's never null. > >>>> > >>>> BLOCK_ABSTRACT_ORIGIN(B) is the FUNCTION_DECL of the function into > >>>> which it has been inlined, or null if B is not inlined. > >>> > >>> It's the BLOCK or FUNCTION it was inlined _from_, not were it was > >>> inlined to. > >>> It's the "ultimate" source, thus the abstract copy of the block or > >>> function decl > >>> (for the outermost scope, aka inlined_function_outer_scope_p). It > >>> corresponds > >>> to what you'd expect for the DWARF abstract origin. > >> > >> Thanks for the correction! It's just the "innermost" block that > >> points to the "ultimate" destination into which it's been inlined. > >> > >>> > >>> BLOCK_ABSTRACT_ORIGIN can be NULL (in case it isn't an inline instance). > >>> > >>>> BLOCK_ABSTRACT_ORIGIN: A BLOCK, or FUNCTION_DECL of the function > >>>> into which a block has been inlined. In a BLOCK immediately enclosing > >>>> an inlined leaf expression points to the outermost BLOCK into which it > >>>> has been inlined (thus bypassing all intermediate BLOCK_SUPERCONTEXTs). > >>>> > >>>> BLOCK_FRAGMENT_ORIGIN: ??? > >>>> BLOCK_FRAGMENT_CHAIN: ??? > >>> > >>> that's for scope blocks split by hot/cold partitioning and only > >>> temporarily > >>> populated. > >> > >> Thanks, I now see these documented in detail in tree.h. > >> > >>> > >>>> bool inlined_function_outer_scope_p(BLOCK) [tree.h] > >>>> Returns true if a BLOCK has a source location. > >>>> True for all but the innermost (no SUBBLOCKs?) and outermost blocks > >>>> into which an expression has been inlined. (Is this always true?) > >>>> > >>>> tree block_ultimate_origin(BLOCK) [tree.c] > >>>> Returns BLOCK_ABSTRACT_ORIGIN(BLOCK), AO, after asserting that > >>>> (DECL_P(AO) && DECL_ORIGIN(AO) == AO) || BLOCK_ORIGIN(AO) == AO). > >> > >> The attached diff adds the comments above to tree.h. > >> > >> I looked for a good place in the manual to add the same text but I'm > >> not sure. Would the Blocks @subsection in generic.texi be appropriate? > >> > >> Martin > > > > > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] document BLOCK_ABSTRACT_ORIGIN et al. 2021-02-03 12:01 ` Richard Biener @ 2021-02-03 17:12 ` Martin Sebor 2021-02-04 8:48 ` Richard Biener 0 siblings, 1 reply; 12+ messages in thread From: Martin Sebor @ 2021-02-03 17:12 UTC (permalink / raw) To: Richard Biener; +Cc: Jeff Law, Jakub Jelinek, gcc-patches On 2/3/21 5:01 AM, Richard Biener wrote: > On Mon, Feb 1, 2021 at 5:20 PM Martin Sebor <msebor@gmail.com> wrote: >> >> I have pushed the tree.h comments in g:6a2053773b8. I will wait >> for an approval of the changes to the manual. > > Sorry for not looking earlier. Sorry, I thought you were fine with the text after your first review. I'll adjust the tree.h comments when we're done, though I'd like to think the example in the manual will do a lot more to help make it clear than the comments in tree.h can. > > +/* The scope enclosing the scope NODE, or FUNCTION_DECL for the "outermost" > + function scope. Inlined functions are chained by this so that given > + expression E and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope > + in which E has been made or into which E has been inlined. */ > > I can't really understand what you are trying to say with the second > sentence. There's > nothing really special about BLOCK_SUPERCONTEXT and inlines so I believe this > sentence only adds confusion. The sentence explains how SUPERCONTEXT chains inlined blocks. In the manual diff I show an example: void f0 (char *p, int n) { memset (p, 1, n); } void f1 (char *p, int n) { f0 (p + 1, n + 1); } void f2 (char *p, int n) { f1 (p + 1, n + 1); } int a[6]; void f3 (char *p, int n) { f2 (a, 3); } The blocks for all calls inlined into f3 are chained like so: CALL_EXPR: memset E BLOCK #13 <--+ TREE_BLOCK (E) +-- SUPERCONTEXT: BLOCK #12 | | ABSTRACT_ORIGIN: BLOCK #0 --+ | | | +-> BLOCK #12 (f1) <--|-+ | +-- SUPERCONTEXT: BLOCK #10 | | | | SUBBLOCKS: BLOCK #13 --|-| | | ABSTRACT_ORIGIN: f0 ---+ | | | | | +-> BLOCK #10 (f2) <-+ | | +--- SUPERCONTEXT: BLOCK #8 | | | | SUBBLOCKS: BLOCK #12 ---|-| | | ABSTRACT_ORIGIN: f1 ------+ | | | | +-> BLOCK #8 (f3) | | +---- SUPERCONTEXT: BLOCK #0 | | | SUBBLOCKS: BLOCK #10 --| | | ABSTRACT_ORIGIN: f2 ---+ | | | +-> BLOCK #0 (f3) <---------------+ SUPERCONTEXT: f3 SUBBLOCKS: BLOCK #8 Does the following sound better? (Dropping the "in which E has been made.") Inlined functions are chained by this so that given expression E and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope into which E has been inlined. > #define BLOCK_SUPERCONTEXT(NODE) (BLOCK_CHECK (NODE)->block.supercontext) > +/* Points to the next scope at the same level of nesting as scope NODE. */ > #define BLOCK_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.chain) > +/* A BLOCK, or FUNCTION_DECL of the function from which a block has been > + inlined. > > ... from which a block has been ultimatively copied for example by inlining. > > [clones also will have abstract origins] > > In a scope immediately enclosing an inlined leaf expression, > + points to the outermost scope into which it has been inlined (thus > + bypassing all intermediate BLOCK_SUPERCONTEXTs). */ > > ? This describes the long arrow on the right, pointing Block #13's ABSTRACT_ORIGIN down to Block #0. All the other AO's point down to the next/enclosing block (arrows on the left). I didn't expect this when I first worked with the blocks so it seemed like an important detail to mention. > > Maybe: An inlined function is represented by a scope with > BLOCK_ABSTRACT_ORIGIN being the FUNCTION_DECL of the inlined function > containing the inlined functions scope tree as children. All abstract origins > are ultimate, that is BLOCK_ABSTRACT_ORIGIN(NODE) > == BLOCK_ABSTRACT_ORIGIN(BLOCK_ABSTRACT_ORIGIN (NODE)). The first sentence sounds good to me as far as it goes but it doesn't capture the long arrow above. (By children I assume you mean SUBBLOCKS, correct?) I don't follow what you're trying to say in the second sentence. The equality isn't true for Block #0 whose AO is null. It also isn't true for Block #12 and the others whose AO is a DECL, not a block. What do you mean by "ultimate" in plain English? FWIW, if I were to try to explain it using the example I'd say only Block #13's AO is "ultimate:" it points down in the diagram to the block of the function into which the expression has ultimately been inlined. The AO's of all the other intervening inlined blocks are the DECLs of the inlined callees (up-pointing arrows); they don't look ultimate to me in this sense. But however this is phrased I suspect it won't be perfectly clear without an example or a picture. Martin > > #define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.abstract_origin) > > >> On 1/27/21 5:54 PM, Martin Sebor wrote: >>> Attached is an updated patch for both tree.h and the internals manual >>> documenting the most important BLOCK_ macros and what they represent. >>> >>> On 1/21/21 2:52 PM, Martin Sebor wrote: >>>> On 1/18/21 6:25 AM, Richard Biener wrote: >>>>>> PS Here are my notes on the macros and the two related functions: >>>>>> >>>>>> BLOCK: Denotes a lexical scope. Contains BLOCK_VARS of variables >>>>>> declared in it, BLOCK_SUBBLOCKS of scopes nested in it, and >>>>>> BLOCK_CHAIN pointing to the next BLOCK. Its BLOCK_SUPERCONTEXT >>>>>> point to the BLOCK of the enclosing scope. May have >>>>>> a BLOCK_ABSTRACT_ORIGIN and a BLOCK_SOURCE_LOCATION. >>>>>> >>>>>> BLOCK_SUPERCONTEXT: The scope of the enclosing block, or FUNCTION_DECL >>>>>> for the "outermost" function scope. Inlined functions are chained by >>>>>> this so that given expression E and its TREE_BLOCK(E) B, >>>>>> BLOCK_SUPERCONTEXT(B) is the scope (BLOCK) in which E has been made >>>>>> or into which E has been inlined. In the latter case, >>>>>> >>>>>> BLOCK_ORIGIN(B) evaluates either to the enclosing BLOCK or to >>>>>> the enclosing function DECL. It's never null. >>>>>> >>>>>> BLOCK_ABSTRACT_ORIGIN(B) is the FUNCTION_DECL of the function into >>>>>> which it has been inlined, or null if B is not inlined. >>>>> >>>>> It's the BLOCK or FUNCTION it was inlined _from_, not were it was >>>>> inlined to. >>>>> It's the "ultimate" source, thus the abstract copy of the block or >>>>> function decl >>>>> (for the outermost scope, aka inlined_function_outer_scope_p). It >>>>> corresponds >>>>> to what you'd expect for the DWARF abstract origin. >>>> >>>> Thanks for the correction! It's just the "innermost" block that >>>> points to the "ultimate" destination into which it's been inlined. >>>> >>>>> >>>>> BLOCK_ABSTRACT_ORIGIN can be NULL (in case it isn't an inline instance). >>>>> >>>>>> BLOCK_ABSTRACT_ORIGIN: A BLOCK, or FUNCTION_DECL of the function >>>>>> into which a block has been inlined. In a BLOCK immediately enclosing >>>>>> an inlined leaf expression points to the outermost BLOCK into which it >>>>>> has been inlined (thus bypassing all intermediate BLOCK_SUPERCONTEXTs). >>>>>> >>>>>> BLOCK_FRAGMENT_ORIGIN: ??? >>>>>> BLOCK_FRAGMENT_CHAIN: ??? >>>>> >>>>> that's for scope blocks split by hot/cold partitioning and only >>>>> temporarily >>>>> populated. >>>> >>>> Thanks, I now see these documented in detail in tree.h. >>>> >>>>> >>>>>> bool inlined_function_outer_scope_p(BLOCK) [tree.h] >>>>>> Returns true if a BLOCK has a source location. >>>>>> True for all but the innermost (no SUBBLOCKs?) and outermost blocks >>>>>> into which an expression has been inlined. (Is this always true?) >>>>>> >>>>>> tree block_ultimate_origin(BLOCK) [tree.c] >>>>>> Returns BLOCK_ABSTRACT_ORIGIN(BLOCK), AO, after asserting that >>>>>> (DECL_P(AO) && DECL_ORIGIN(AO) == AO) || BLOCK_ORIGIN(AO) == AO). >>>> >>>> The attached diff adds the comments above to tree.h. >>>> >>>> I looked for a good place in the manual to add the same text but I'm >>>> not sure. Would the Blocks @subsection in generic.texi be appropriate? >>>> >>>> Martin >>> >>> >> ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] document BLOCK_ABSTRACT_ORIGIN et al. 2021-02-03 17:12 ` Martin Sebor @ 2021-02-04 8:48 ` Richard Biener 2021-02-06 19:11 ` Martin Sebor 0 siblings, 1 reply; 12+ messages in thread From: Richard Biener @ 2021-02-04 8:48 UTC (permalink / raw) To: Martin Sebor; +Cc: Jeff Law, Jakub Jelinek, gcc-patches On Wed, Feb 3, 2021 at 6:12 PM Martin Sebor <msebor@gmail.com> wrote: > > On 2/3/21 5:01 AM, Richard Biener wrote: > > On Mon, Feb 1, 2021 at 5:20 PM Martin Sebor <msebor@gmail.com> wrote: > >> > >> I have pushed the tree.h comments in g:6a2053773b8. I will wait > >> for an approval of the changes to the manual. > > > > Sorry for not looking earlier. > > Sorry, I thought you were fine with the text after your first review. > I'll adjust the tree.h comments when we're done, though I'd like to > think the example in the manual will do a lot more to help make it > clear than the comments in tree.h can. > > > > > +/* The scope enclosing the scope NODE, or FUNCTION_DECL for the "outermost" > > + function scope. Inlined functions are chained by this so that given > > + expression E and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope > > + in which E has been made or into which E has been inlined. */ > > > > I can't really understand what you are trying to say with the second > > sentence. There's > > nothing really special about BLOCK_SUPERCONTEXT and inlines so I believe this > > sentence only adds confusion. > > The sentence explains how SUPERCONTEXT chains inlined blocks. In > the manual diff I show an example: > > void f0 (char *p, int n) { memset (p, 1, n); } > > void f1 (char *p, int n) { f0 (p + 1, n + 1); } > > void f2 (char *p, int n) { f1 (p + 1, n + 1); } > > int a[6]; > void f3 (char *p, int n) { f2 (a, 3); } > > The blocks for all calls inlined into f3 are chained like so: > > CALL_EXPR: memset E > > BLOCK #13 <--+ TREE_BLOCK (E) > +-- SUPERCONTEXT: BLOCK #12 | > | ABSTRACT_ORIGIN: BLOCK #0 --+ > | | | > +-> BLOCK #12 (f1) <--|-+ | > +-- SUPERCONTEXT: BLOCK #10 | | | > | SUBBLOCKS: BLOCK #13 --|-| | > | ABSTRACT_ORIGIN: f0 ---+ | | > | | | > +-> BLOCK #10 (f2) <-+ | | > +--- SUPERCONTEXT: BLOCK #8 | | | > | SUBBLOCKS: BLOCK #12 ---|-| | > | ABSTRACT_ORIGIN: f1 ------+ | > | | | > +-> BLOCK #8 (f3) | | > +---- SUPERCONTEXT: BLOCK #0 | | > | SUBBLOCKS: BLOCK #10 --| | > | ABSTRACT_ORIGIN: f2 ---+ | > | | > +-> BLOCK #0 (f3) <---------------+ > SUPERCONTEXT: f3 > SUBBLOCKS: BLOCK #8 > > Does the following sound better? (Dropping the "in which E has been > made.") > > Inlined functions are chained by this so that given expression E > and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope into > which E has been inlined. Oh, I see what you mean. But this is misleading for the case where f0 has any blocks: f0 (..) { { int tem; { memset (..); } } if () { }... } because BLOCK_SUPERCONTEXT is simply the parent scope ( { int tem; ... } ) and not yet the artifical scope we generate to wrap f0. To figure the scope a block was inlined to you'd have to do sth like b = TREE_BLOCK (E); gcc_assert (BLOCK_ABSTRACT_ORIGIN (b)); // it was inlined while (!inlined_function_outer_scope_p (b)) b = BLOCK_SUPERCONTEXT (b); now BLOCK_SUPERCONTEXT (b) is the block the function containing E was inlined to. So again, I think tree.h is not the place to document this. There BLOCK_SUPERCONTEXT should simply say it's pointing to the parent BLOCK. In the texi documentation I'd separate out the representation of inlines and clones, eventually put it on the BLOCK_ABSTRACT_ORIGIN documentation. [I did not review the texi part yet - I mainly want to avoid people being even more confused about the tree.h comments] > > #define BLOCK_SUPERCONTEXT(NODE) (BLOCK_CHECK (NODE)->block.supercontext) > > +/* Points to the next scope at the same level of nesting as scope NODE. */ > > #define BLOCK_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.chain) > > +/* A BLOCK, or FUNCTION_DECL of the function from which a block has been > > + inlined. > > > > ... from which a block has been ultimatively copied for example by inlining. > > > > [clones also will have abstract origins] > > > > In a scope immediately enclosing an inlined leaf expression, > > + points to the outermost scope into which it has been inlined (thus > > + bypassing all intermediate BLOCK_SUPERCONTEXTs). */ > > > > ? > > This describes the long arrow on the right, pointing Block #13's > ABSTRACT_ORIGIN down to Block #0. All the other AO's point down > to the next/enclosing block (arrows on the left). I didn't expect > this when I first worked with the blocks so it seemed like > an important detail to mention. > > > > > Maybe: An inlined function is represented by a scope with > > BLOCK_ABSTRACT_ORIGIN being the FUNCTION_DECL of the inlined function > > containing the inlined functions scope tree as children. All abstract origins > > are ultimate, that is BLOCK_ABSTRACT_ORIGIN(NODE) > > == BLOCK_ABSTRACT_ORIGIN(BLOCK_ABSTRACT_ORIGIN (NODE)). > > The first sentence sounds good to me as far as it goes but it > doesn't capture the long arrow above. (By children I assume you > mean SUBBLOCKS, correct?) > > I don't follow what you're trying to say in the second sentence. > The equality isn't true for Block #0 whose AO is null. It also > isn't true for Block #12 and the others whose AO is a DECL, not > a block. > > What do you mean by "ultimate" in plain English? Ultimate in the sense dwarf2out uses it. DWARF wants to refer to the abstract copy. Originally (I think till GCC 9) BLOCK_ABSTRACT_ORIGIN of a function inlined that had functions inlined into it pointed to the inlined block of the inner inline but now it points to the original outline copy BLOCK of the inner inline (uh, can you parse that?). That simplifies things and is all we need. > FWIW, if I were to try to explain it using the example I'd say > only Block #13's AO is "ultimate:" it points down in the diagram > to the block of the function into which the expression has > ultimately been inlined. The AO's of all the other intervening > inlined blocks are the DECLs of the inlined callees (up-pointing > arrows); they don't look ultimate to me in this sense. > > But however this is phrased I suspect it won't be perfectly clear > without an example or a picture. Which means giving partial info in tree.h isn't useful but confusing. Richard. > > Martin > > > > > #define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.abstract_origin) > > > > > >> On 1/27/21 5:54 PM, Martin Sebor wrote: > >>> Attached is an updated patch for both tree.h and the internals manual > >>> documenting the most important BLOCK_ macros and what they represent. > >>> > >>> On 1/21/21 2:52 PM, Martin Sebor wrote: > >>>> On 1/18/21 6:25 AM, Richard Biener wrote: > >>>>>> PS Here are my notes on the macros and the two related functions: > >>>>>> > >>>>>> BLOCK: Denotes a lexical scope. Contains BLOCK_VARS of variables > >>>>>> declared in it, BLOCK_SUBBLOCKS of scopes nested in it, and > >>>>>> BLOCK_CHAIN pointing to the next BLOCK. Its BLOCK_SUPERCONTEXT > >>>>>> point to the BLOCK of the enclosing scope. May have > >>>>>> a BLOCK_ABSTRACT_ORIGIN and a BLOCK_SOURCE_LOCATION. > >>>>>> > >>>>>> BLOCK_SUPERCONTEXT: The scope of the enclosing block, or FUNCTION_DECL > >>>>>> for the "outermost" function scope. Inlined functions are chained by > >>>>>> this so that given expression E and its TREE_BLOCK(E) B, > >>>>>> BLOCK_SUPERCONTEXT(B) is the scope (BLOCK) in which E has been made > >>>>>> or into which E has been inlined. In the latter case, > >>>>>> > >>>>>> BLOCK_ORIGIN(B) evaluates either to the enclosing BLOCK or to > >>>>>> the enclosing function DECL. It's never null. > >>>>>> > >>>>>> BLOCK_ABSTRACT_ORIGIN(B) is the FUNCTION_DECL of the function into > >>>>>> which it has been inlined, or null if B is not inlined. > >>>>> > >>>>> It's the BLOCK or FUNCTION it was inlined _from_, not were it was > >>>>> inlined to. > >>>>> It's the "ultimate" source, thus the abstract copy of the block or > >>>>> function decl > >>>>> (for the outermost scope, aka inlined_function_outer_scope_p). It > >>>>> corresponds > >>>>> to what you'd expect for the DWARF abstract origin. > >>>> > >>>> Thanks for the correction! It's just the "innermost" block that > >>>> points to the "ultimate" destination into which it's been inlined. > >>>> > >>>>> > >>>>> BLOCK_ABSTRACT_ORIGIN can be NULL (in case it isn't an inline instance). > >>>>> > >>>>>> BLOCK_ABSTRACT_ORIGIN: A BLOCK, or FUNCTION_DECL of the function > >>>>>> into which a block has been inlined. In a BLOCK immediately enclosing > >>>>>> an inlined leaf expression points to the outermost BLOCK into which it > >>>>>> has been inlined (thus bypassing all intermediate BLOCK_SUPERCONTEXTs). > >>>>>> > >>>>>> BLOCK_FRAGMENT_ORIGIN: ??? > >>>>>> BLOCK_FRAGMENT_CHAIN: ??? > >>>>> > >>>>> that's for scope blocks split by hot/cold partitioning and only > >>>>> temporarily > >>>>> populated. > >>>> > >>>> Thanks, I now see these documented in detail in tree.h. > >>>> > >>>>> > >>>>>> bool inlined_function_outer_scope_p(BLOCK) [tree.h] > >>>>>> Returns true if a BLOCK has a source location. > >>>>>> True for all but the innermost (no SUBBLOCKs?) and outermost blocks > >>>>>> into which an expression has been inlined. (Is this always true?) > >>>>>> > >>>>>> tree block_ultimate_origin(BLOCK) [tree.c] > >>>>>> Returns BLOCK_ABSTRACT_ORIGIN(BLOCK), AO, after asserting that > >>>>>> (DECL_P(AO) && DECL_ORIGIN(AO) == AO) || BLOCK_ORIGIN(AO) == AO). > >>>> > >>>> The attached diff adds the comments above to tree.h. > >>>> > >>>> I looked for a good place in the manual to add the same text but I'm > >>>> not sure. Would the Blocks @subsection in generic.texi be appropriate? > >>>> > >>>> Martin > >>> > >>> > >> > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] document BLOCK_ABSTRACT_ORIGIN et al. 2021-02-04 8:48 ` Richard Biener @ 2021-02-06 19:11 ` Martin Sebor 2021-02-08 10:37 ` Richard Biener 0 siblings, 1 reply; 12+ messages in thread From: Martin Sebor @ 2021-02-06 19:11 UTC (permalink / raw) To: Richard Biener; +Cc: Jeff Law, Jakub Jelinek, gcc-patches [-- Attachment #1: Type: text/plain, Size: 12896 bytes --] On 2/4/21 1:48 AM, Richard Biener wrote: > On Wed, Feb 3, 2021 at 6:12 PM Martin Sebor <msebor@gmail.com> wrote: >> >> On 2/3/21 5:01 AM, Richard Biener wrote: >>> On Mon, Feb 1, 2021 at 5:20 PM Martin Sebor <msebor@gmail.com> wrote: >>>> >>>> I have pushed the tree.h comments in g:6a2053773b8. I will wait >>>> for an approval of the changes to the manual. >>> >>> Sorry for not looking earlier. >> >> Sorry, I thought you were fine with the text after your first review. >> I'll adjust the tree.h comments when we're done, though I'd like to >> think the example in the manual will do a lot more to help make it >> clear than the comments in tree.h can. >> >>> >>> +/* The scope enclosing the scope NODE, or FUNCTION_DECL for the "outermost" >>> + function scope. Inlined functions are chained by this so that given >>> + expression E and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope >>> + in which E has been made or into which E has been inlined. */ >>> >>> I can't really understand what you are trying to say with the second >>> sentence. There's >>> nothing really special about BLOCK_SUPERCONTEXT and inlines so I believe this >>> sentence only adds confusion. >> >> The sentence explains how SUPERCONTEXT chains inlined blocks. In >> the manual diff I show an example: >> >> void f0 (char *p, int n) { memset (p, 1, n); } >> >> void f1 (char *p, int n) { f0 (p + 1, n + 1); } >> >> void f2 (char *p, int n) { f1 (p + 1, n + 1); } >> >> int a[6]; >> void f3 (char *p, int n) { f2 (a, 3); } >> >> The blocks for all calls inlined into f3 are chained like so: >> >> CALL_EXPR: memset E >> >> BLOCK #13 <--+ TREE_BLOCK (E) >> +-- SUPERCONTEXT: BLOCK #12 | >> | ABSTRACT_ORIGIN: BLOCK #0 --+ >> | | | >> +-> BLOCK #12 (f1) <--|-+ | >> +-- SUPERCONTEXT: BLOCK #10 | | | >> | SUBBLOCKS: BLOCK #13 --|-| | >> | ABSTRACT_ORIGIN: f0 ---+ | | >> | | | >> +-> BLOCK #10 (f2) <-+ | | >> +--- SUPERCONTEXT: BLOCK #8 | | | >> | SUBBLOCKS: BLOCK #12 ---|-| | >> | ABSTRACT_ORIGIN: f1 ------+ | >> | | | >> +-> BLOCK #8 (f3) | | >> +---- SUPERCONTEXT: BLOCK #0 | | >> | SUBBLOCKS: BLOCK #10 --| | >> | ABSTRACT_ORIGIN: f2 ---+ | >> | | >> +-> BLOCK #0 (f3) <---------------+ >> SUPERCONTEXT: f3 >> SUBBLOCKS: BLOCK #8 >> >> Does the following sound better? (Dropping the "in which E has been >> made.") >> >> Inlined functions are chained by this so that given expression E >> and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope into >> which E has been inlined. > > Oh, I see what you mean. But this is misleading for the case where f0 > has any blocks: > > f0 (..) { { int tem; { memset (..); } } if () { }... } > > because BLOCK_SUPERCONTEXT is simply the parent scope ( { int tem; ... } ) and > not yet the artifical scope we generate to wrap f0. I haven't seen those scopes in my (admittedly simplistic) tests and based on the internals manual have been assuming most lexical scopes are removed during gimplification: Additionally, all the control structures used in GENERIC are lowered into conditional jumps, lexical scopes are removed and exception regions are converted into an on the side exception region tree. Is the above wrong or inaccurate? Do all nested scope not get removed? > To figure the > scope a block was > inlined to you'd have to do sth like > > b = TREE_BLOCK (E); > gcc_assert (BLOCK_ABSTRACT_ORIGIN (b)); // it was inlined > while (!inlined_function_outer_scope_p (b)) > b = BLOCK_SUPERCONTEXT (b); > now BLOCK_SUPERCONTEXT (b) is the block the function containing E was > inlined to. > > So again, I think tree.h is not the place to document this. There > BLOCK_SUPERCONTEXT > should simply say it's pointing to the parent BLOCK. I can simplify the text but want to make it clear it doesn't necessarily point to a BLOCK but can also point to a FUNCTION_DECL. So how about: BLOCK_SUPERCONTEXT Either a BLOCK of the enclosing scope or FUNCTION_DECL for the "outermost" function scope. In the middle end used to chain scopes of functions inlined into their callers. */ > > In the texi documentation I'd separate out the representation of > inlines and clones, > eventually put it on the BLOCK_ABSTRACT_ORIGIN documentation. > > [I did not review the texi part yet - I mainly want to avoid people > being even more > confused about the tree.h comments] I take your point that sometimes less is more. But from my personal experience with these macros, I'd be surprised if the text that's there now could be worse than having no comments at all. > >>> #define BLOCK_SUPERCONTEXT(NODE) (BLOCK_CHECK (NODE)->block.supercontext) >>> +/* Points to the next scope at the same level of nesting as scope NODE. */ >>> #define BLOCK_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.chain) >>> +/* A BLOCK, or FUNCTION_DECL of the function from which a block has been >>> + inlined. >>> >>> ... from which a block has been ultimatively copied for example by inlining. >>> >>> [clones also will have abstract origins] Okay, how's this: /* A BLOCK, or FUNCTION_DECL of the function from which a block has been copied by inlining or cloning. */ #define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.abstract_origin) >>> >>> In a scope immediately enclosing an inlined leaf expression, >>> + points to the outermost scope into which it has been inlined (thus >>> + bypassing all intermediate BLOCK_SUPERCONTEXTs). */ >>> >>> ? >> >> This describes the long arrow on the right, pointing Block #13's >> ABSTRACT_ORIGIN down to Block #0. All the other AO's point down >> to the next/enclosing block (arrows on the left). I didn't expect >> this when I first worked with the blocks so it seemed like >> an important detail to mention. >> >>> >>> Maybe: An inlined function is represented by a scope with >>> BLOCK_ABSTRACT_ORIGIN being the FUNCTION_DECL of the inlined function >>> containing the inlined functions scope tree as children. All abstract origins >>> are ultimate, that is BLOCK_ABSTRACT_ORIGIN(NODE) >>> == BLOCK_ABSTRACT_ORIGIN(BLOCK_ABSTRACT_ORIGIN (NODE)). >> >> The first sentence sounds good to me as far as it goes but it >> doesn't capture the long arrow above. (By children I assume you >> mean SUBBLOCKS, correct?) >> >> I don't follow what you're trying to say in the second sentence. >> The equality isn't true for Block #0 whose AO is null. It also >> isn't true for Block #12 and the others whose AO is a DECL, not >> a block. >> >> What do you mean by "ultimate" in plain English? > > Ultimate in the sense dwarf2out uses it. DWARF wants to refer to > the abstract copy. Originally (I think till GCC 9) BLOCK_ABSTRACT_ORIGIN > of a function inlined that had functions inlined into it pointed to the > inlined block of the inner inline but now it points to the original > outline copy BLOCK of the inner inline (uh, can you parse that?). > That simplifies things and is all we need. I *think* I understand what you're saying about how it's set up now, but I had to refer to the diagram above to help. You're referring to the arrow below, f2's AO pointing to f1's block (and the corresponding arrow from f3's AO to f2's block: BLOCK #12 (f1) <----+ SUPERCONTEXT: BLOCK #10 | SUBBLOCKS: BLOCK #13 | ABSTRACT_ORIGIN: f0 | | BLOCK #10 (f2) | SUPERCONTEXT: BLOCK #8 | SUBBLOCKS: BLOCK #12 | ABSTRACT_ORIGIN: f1 -----+ FWIW, a relationship between two interior parts of a larger whole is not something I would understand by the word ultimate. A couple of synonyms for "ultimate" are "last" and "final" and f1 is neither. I would call f3 the ultimate origin the three inlined calls, and that matches AO only in Block #13, but not in any others. >> FWIW, if I were to try to explain it using the example I'd say >> only Block #13's AO is "ultimate:" it points down in the diagram >> to the block of the function into which the expression has >> ultimately been inlined. The AO's of all the other intervening >> inlined blocks are the DECLs of the inlined callees (up-pointing >> arrows); they don't look ultimate to me in this sense. >> >> But however this is phrased I suspect it won't be perfectly clear >> without an example or a picture. > > Which means giving partial info in tree.h isn't useful but confusing. I don't think that's true. Most comments in tree.h are only partial and don't fully describe every fine detail of whatever they document. They may not be enough for using the thing they describe properly and safely in every instance but they're often good enough to read the code and what what it does. BLOCK_ABSTRACT_ORIGIN or BLOC_SUPERCONTEXT without any comment at all isn't good enough for even that. Anyway, thanks for continuing to help with this. Attached are the tweaks to tree.h. I'll post an update to the manual separately. Martin > > Richard. > >> >> Martin >> >>> >>> #define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.abstract_origin) >>> >>> >>>> On 1/27/21 5:54 PM, Martin Sebor wrote: >>>>> Attached is an updated patch for both tree.h and the internals manual >>>>> documenting the most important BLOCK_ macros and what they represent. >>>>> >>>>> On 1/21/21 2:52 PM, Martin Sebor wrote: >>>>>> On 1/18/21 6:25 AM, Richard Biener wrote: >>>>>>>> PS Here are my notes on the macros and the two related functions: >>>>>>>> >>>>>>>> BLOCK: Denotes a lexical scope. Contains BLOCK_VARS of variables >>>>>>>> declared in it, BLOCK_SUBBLOCKS of scopes nested in it, and >>>>>>>> BLOCK_CHAIN pointing to the next BLOCK. Its BLOCK_SUPERCONTEXT >>>>>>>> point to the BLOCK of the enclosing scope. May have >>>>>>>> a BLOCK_ABSTRACT_ORIGIN and a BLOCK_SOURCE_LOCATION. >>>>>>>> >>>>>>>> BLOCK_SUPERCONTEXT: The scope of the enclosing block, or FUNCTION_DECL >>>>>>>> for the "outermost" function scope. Inlined functions are chained by >>>>>>>> this so that given expression E and its TREE_BLOCK(E) B, >>>>>>>> BLOCK_SUPERCONTEXT(B) is the scope (BLOCK) in which E has been made >>>>>>>> or into which E has been inlined. In the latter case, >>>>>>>> >>>>>>>> BLOCK_ORIGIN(B) evaluates either to the enclosing BLOCK or to >>>>>>>> the enclosing function DECL. It's never null. >>>>>>>> >>>>>>>> BLOCK_ABSTRACT_ORIGIN(B) is the FUNCTION_DECL of the function into >>>>>>>> which it has been inlined, or null if B is not inlined. >>>>>>> >>>>>>> It's the BLOCK or FUNCTION it was inlined _from_, not were it was >>>>>>> inlined to. >>>>>>> It's the "ultimate" source, thus the abstract copy of the block or >>>>>>> function decl >>>>>>> (for the outermost scope, aka inlined_function_outer_scope_p). It >>>>>>> corresponds >>>>>>> to what you'd expect for the DWARF abstract origin. >>>>>> >>>>>> Thanks for the correction! It's just the "innermost" block that >>>>>> points to the "ultimate" destination into which it's been inlined. >>>>>> >>>>>>> >>>>>>> BLOCK_ABSTRACT_ORIGIN can be NULL (in case it isn't an inline instance). >>>>>>> >>>>>>>> BLOCK_ABSTRACT_ORIGIN: A BLOCK, or FUNCTION_DECL of the function >>>>>>>> into which a block has been inlined. In a BLOCK immediately enclosing >>>>>>>> an inlined leaf expression points to the outermost BLOCK into which it >>>>>>>> has been inlined (thus bypassing all intermediate BLOCK_SUPERCONTEXTs). >>>>>>>> >>>>>>>> BLOCK_FRAGMENT_ORIGIN: ??? >>>>>>>> BLOCK_FRAGMENT_CHAIN: ??? >>>>>>> >>>>>>> that's for scope blocks split by hot/cold partitioning and only >>>>>>> temporarily >>>>>>> populated. >>>>>> >>>>>> Thanks, I now see these documented in detail in tree.h. >>>>>> >>>>>>> >>>>>>>> bool inlined_function_outer_scope_p(BLOCK) [tree.h] >>>>>>>> Returns true if a BLOCK has a source location. >>>>>>>> True for all but the innermost (no SUBBLOCKs?) and outermost blocks >>>>>>>> into which an expression has been inlined. (Is this always true?) >>>>>>>> >>>>>>>> tree block_ultimate_origin(BLOCK) [tree.c] >>>>>>>> Returns BLOCK_ABSTRACT_ORIGIN(BLOCK), AO, after asserting that >>>>>>>> (DECL_P(AO) && DECL_ORIGIN(AO) == AO) || BLOCK_ORIGIN(AO) == AO). >>>>>> >>>>>> The attached diff adds the comments above to tree.h. >>>>>> >>>>>> I looked for a good place in the manual to add the same text but I'm >>>>>> not sure. Would the Blocks @subsection in generic.texi be appropriate? >>>>>> >>>>>> Martin >>>>> >>>>> >>>> >> [-- Attachment #2: gcc-ao-tree.h.diff --] [-- Type: text/x-patch, Size: 1578 bytes --] diff --git a/gcc/tree.h b/gcc/tree.h index 4f33868e8e1..86f142be6f3 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1922,17 +1922,14 @@ class auto_suppress_location_wrappers #define BLOCK_NONLOCALIZED_VAR(NODE,N) (*BLOCK_NONLOCALIZED_VARS (NODE))[N] /* A chain of BLOCKs (scopes) nested within the scope NODE. */ #define BLOCK_SUBBLOCKS(NODE) (BLOCK_CHECK (NODE)->block.subblocks) -/* The scope enclosing the scope NODE, or FUNCTION_DECL for the "outermost" - function scope. Inlined functions are chained by this so that given - expression E and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope - in which E has been made or into which E has been inlined. */ +/* Either a BLOCK of the enclosing scope or FUNCTION_DECL for + the "outermost" function scope. In the middle end used to chain + scopes of functions inlined into their callers. */ #define BLOCK_SUPERCONTEXT(NODE) (BLOCK_CHECK (NODE)->block.supercontext) /* Points to the next scope at the same level of nesting as scope NODE. */ #define BLOCK_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.chain) /* A BLOCK, or FUNCTION_DECL of the function from which a block has been - inlined. In a scope immediately enclosing an inlined leaf expression, - points to the outermost scope into which it has been inlined (thus - bypassing all intermediate BLOCK_SUPERCONTEXTs). */ + copied by inlining or cloning. */ #define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.abstract_origin) #define BLOCK_ORIGIN(NODE) \ (BLOCK_ABSTRACT_ORIGIN(NODE) ? BLOCK_ABSTRACT_ORIGIN(NODE) : (NODE)) ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] document BLOCK_ABSTRACT_ORIGIN et al. 2021-02-06 19:11 ` Martin Sebor @ 2021-02-08 10:37 ` Richard Biener 0 siblings, 0 replies; 12+ messages in thread From: Richard Biener @ 2021-02-08 10:37 UTC (permalink / raw) To: Martin Sebor; +Cc: Jeff Law, Jakub Jelinek, gcc-patches On Sat, Feb 6, 2021 at 8:11 PM Martin Sebor <msebor@gmail.com> wrote: > > On 2/4/21 1:48 AM, Richard Biener wrote: > > On Wed, Feb 3, 2021 at 6:12 PM Martin Sebor <msebor@gmail.com> wrote: > >> > >> On 2/3/21 5:01 AM, Richard Biener wrote: > >>> On Mon, Feb 1, 2021 at 5:20 PM Martin Sebor <msebor@gmail.com> wrote: > >>>> > >>>> I have pushed the tree.h comments in g:6a2053773b8. I will wait > >>>> for an approval of the changes to the manual. > >>> > >>> Sorry for not looking earlier. > >> > >> Sorry, I thought you were fine with the text after your first review. > >> I'll adjust the tree.h comments when we're done, though I'd like to > >> think the example in the manual will do a lot more to help make it > >> clear than the comments in tree.h can. > >> > >>> > >>> +/* The scope enclosing the scope NODE, or FUNCTION_DECL for the "outermost" > >>> + function scope. Inlined functions are chained by this so that given > >>> + expression E and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope > >>> + in which E has been made or into which E has been inlined. */ > >>> > >>> I can't really understand what you are trying to say with the second > >>> sentence. There's > >>> nothing really special about BLOCK_SUPERCONTEXT and inlines so I believe this > >>> sentence only adds confusion. > >> > >> The sentence explains how SUPERCONTEXT chains inlined blocks. In > >> the manual diff I show an example: > >> > >> void f0 (char *p, int n) { memset (p, 1, n); } > >> > >> void f1 (char *p, int n) { f0 (p + 1, n + 1); } > >> > >> void f2 (char *p, int n) { f1 (p + 1, n + 1); } > >> > >> int a[6]; > >> void f3 (char *p, int n) { f2 (a, 3); } > >> > >> The blocks for all calls inlined into f3 are chained like so: > >> > >> CALL_EXPR: memset E > >> > >> BLOCK #13 <--+ TREE_BLOCK (E) > >> +-- SUPERCONTEXT: BLOCK #12 | > >> | ABSTRACT_ORIGIN: BLOCK #0 --+ > >> | | | > >> +-> BLOCK #12 (f1) <--|-+ | > >> +-- SUPERCONTEXT: BLOCK #10 | | | > >> | SUBBLOCKS: BLOCK #13 --|-| | > >> | ABSTRACT_ORIGIN: f0 ---+ | | > >> | | | > >> +-> BLOCK #10 (f2) <-+ | | > >> +--- SUPERCONTEXT: BLOCK #8 | | | > >> | SUBBLOCKS: BLOCK #12 ---|-| | > >> | ABSTRACT_ORIGIN: f1 ------+ | > >> | | | > >> +-> BLOCK #8 (f3) | | > >> +---- SUPERCONTEXT: BLOCK #0 | | > >> | SUBBLOCKS: BLOCK #10 --| | > >> | ABSTRACT_ORIGIN: f2 ---+ | > >> | | > >> +-> BLOCK #0 (f3) <---------------+ > >> SUPERCONTEXT: f3 > >> SUBBLOCKS: BLOCK #8 > >> > >> Does the following sound better? (Dropping the "in which E has been > >> made.") > >> > >> Inlined functions are chained by this so that given expression E > >> and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope into > >> which E has been inlined. > > > > Oh, I see what you mean. But this is misleading for the case where f0 > > has any blocks: > > > > f0 (..) { { int tem; { memset (..); } } if () { }... } > > > > because BLOCK_SUPERCONTEXT is simply the parent scope ( { int tem; ... } ) and > > not yet the artifical scope we generate to wrap f0. > > I haven't seen those scopes in my (admittedly simplistic) tests and > based on the internals manual have been assuming most lexical scopes > are removed during gimplification: > > Additionally, all the control structures used in GENERIC are lowered > into conditional jumps, lexical scopes are removed and exception > regions are converted into an on the side exception region tree. > > Is the above wrong or inaccurate? Do all nested scope not get removed? The scopes are not present in the GIMPLE IL but the lexical scope tree is still there in a function decls DECL_INITIAL. What happens is that scopes are gone semantically since all automatic vars get promoted to function scope by GIMPLE but we preserve (some) out-of-scope going by inserting CLOBBER instructions into the IL (there's nothing similar at the point the vars originally went live - liveness analysis has to be done for this and the compiler can freely move defs outside of the original scope). > > To figure the > > scope a block was > > inlined to you'd have to do sth like > > > > b = TREE_BLOCK (E); > > gcc_assert (BLOCK_ABSTRACT_ORIGIN (b)); // it was inlined > > while (!inlined_function_outer_scope_p (b)) > > b = BLOCK_SUPERCONTEXT (b); > > now BLOCK_SUPERCONTEXT (b) is the block the function containing E was > > inlined to. > > > > So again, I think tree.h is not the place to document this. There > > BLOCK_SUPERCONTEXT > > should simply say it's pointing to the parent BLOCK. > > I can simplify the text but want to make it clear it doesn't > necessarily point to a BLOCK but can also point to a FUNCTION_DECL. > So how about: > > BLOCK_SUPERCONTEXT > Either a BLOCK of the enclosing scope or FUNCTION_DECL for > the "outermost" function scope. In the middle end used to chain > scopes of functions inlined into their callers. */ Please remove the last sentence. There's nothing different in FE vs. middle-end about BLOCK_SUPERCONTEXT. It's BLOCK_ABSTRACT_ORIGIN where inlining comes into play. > > > > In the texi documentation I'd separate out the representation of > > inlines and clones, > > eventually put it on the BLOCK_ABSTRACT_ORIGIN documentation. > > > > [I did not review the texi part yet - I mainly want to avoid people > > being even more > > confused about the tree.h comments] > > I take your point that sometimes less is more. But from my personal > experience with these macros, I'd be surprised if the text that's > there now could be worse than having no comments at all. But wrong or misleading comments are worse than no comments. > > > >>> #define BLOCK_SUPERCONTEXT(NODE) (BLOCK_CHECK (NODE)->block.supercontext) > >>> +/* Points to the next scope at the same level of nesting as scope NODE. */ > >>> #define BLOCK_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.chain) > >>> +/* A BLOCK, or FUNCTION_DECL of the function from which a block has been > >>> + inlined. > >>> > >>> ... from which a block has been ultimatively copied for example by inlining. > >>> > >>> [clones also will have abstract origins] > > Okay, how's this: > > /* A BLOCK, or FUNCTION_DECL of the function from which a block has been > copied by inlining or cloning. */ > #define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK > (NODE)->block.abstract_origin) Sounds good. > >>> > >>> In a scope immediately enclosing an inlined leaf expression, > >>> + points to the outermost scope into which it has been inlined (thus > >>> + bypassing all intermediate BLOCK_SUPERCONTEXTs). */ > >>> > >>> ? > >> > >> This describes the long arrow on the right, pointing Block #13's > >> ABSTRACT_ORIGIN down to Block #0. All the other AO's point down > >> to the next/enclosing block (arrows on the left). I didn't expect > >> this when I first worked with the blocks so it seemed like > >> an important detail to mention. > >> > >>> > >>> Maybe: An inlined function is represented by a scope with > >>> BLOCK_ABSTRACT_ORIGIN being the FUNCTION_DECL of the inlined function > >>> containing the inlined functions scope tree as children. All abstract origins > >>> are ultimate, that is BLOCK_ABSTRACT_ORIGIN(NODE) > >>> == BLOCK_ABSTRACT_ORIGIN(BLOCK_ABSTRACT_ORIGIN (NODE)). > >> > >> The first sentence sounds good to me as far as it goes but it > >> doesn't capture the long arrow above. (By children I assume you > >> mean SUBBLOCKS, correct?) > >> > >> I don't follow what you're trying to say in the second sentence. > >> The equality isn't true for Block #0 whose AO is null. It also > >> isn't true for Block #12 and the others whose AO is a DECL, not > >> a block. > >> > >> What do you mean by "ultimate" in plain English? > > > > Ultimate in the sense dwarf2out uses it. DWARF wants to refer to > > the abstract copy. Originally (I think till GCC 9) BLOCK_ABSTRACT_ORIGIN > > of a function inlined that had functions inlined into it pointed to the > > inlined block of the inner inline but now it points to the original > > outline copy BLOCK of the inner inline (uh, can you parse that?). > > That simplifies things and is all we need. > > I *think* I understand what you're saying about how it's set up now, > but I had to refer to the diagram above to help. You're referring > to the arrow below, f2's AO pointing to f1's block (and > the corresponding arrow from f3's AO to f2's block: > > BLOCK #12 (f1) <----+ > SUPERCONTEXT: BLOCK #10 | > SUBBLOCKS: BLOCK #13 | > ABSTRACT_ORIGIN: f0 | > | > BLOCK #10 (f2) | > SUPERCONTEXT: BLOCK #8 | > SUBBLOCKS: BLOCK #12 | > ABSTRACT_ORIGIN: f1 -----+ > > FWIW, a relationship between two interior parts of a larger whole > is not something I would understand by the word ultimate. A couple > of synonyms for "ultimate" are "last" and "final" and f1 is neither. > I would call f3 the ultimate origin the three inlined calls, and > that matches AO only in Block #13, but not in any others. But the diagram is only correct until GCC 9 (if I remembered correctly the point I changed it). Currently f2 abstract origin refers to the abstract origin of f1 (so f0). Otherwise the invariant I gave doesn't hold. Abstract origins are best understood in the context of generated DWARF for DW_TAG_lexical_block DW_AT_abstract_origins and the way you'd expect those for DW_TAG_inlined_subroutine DIEs (those we generate for the inlined_function_outer_scope_p blocks - the BLOCKs with FUNCTION_DECL abstract origin). > >> FWIW, if I were to try to explain it using the example I'd say > >> only Block #13's AO is "ultimate:" it points down in the diagram > >> to the block of the function into which the expression has > >> ultimately been inlined. The AO's of all the other intervening > >> inlined blocks are the DECLs of the inlined callees (up-pointing > >> arrows); they don't look ultimate to me in this sense. > >> > >> But however this is phrased I suspect it won't be perfectly clear > >> without an example or a picture. > > > > Which means giving partial info in tree.h isn't useful but confusing. > > I don't think that's true. Most comments in tree.h are only partial > and don't fully describe every fine detail of whatever they document. > They may not be enough for using the thing they describe properly > and safely in every instance but they're often good enough to read > the code and what what it does. BLOCK_ABSTRACT_ORIGIN or > BLOC_SUPERCONTEXT without any comment at all isn't good enough > for even that. But wrong info gives people the idea they can use it wrongly without investigating or asking. Richard. > Anyway, thanks for continuing to help with this. Attached are > the tweaks to tree.h. I'll post an update to the manual separately. > > Martin > > > > > Richard. > > > >> > >> Martin > >> > >>> > >>> #define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.abstract_origin) > >>> > >>> > >>>> On 1/27/21 5:54 PM, Martin Sebor wrote: > >>>>> Attached is an updated patch for both tree.h and the internals manual > >>>>> documenting the most important BLOCK_ macros and what they represent. > >>>>> > >>>>> On 1/21/21 2:52 PM, Martin Sebor wrote: > >>>>>> On 1/18/21 6:25 AM, Richard Biener wrote: > >>>>>>>> PS Here are my notes on the macros and the two related functions: > >>>>>>>> > >>>>>>>> BLOCK: Denotes a lexical scope. Contains BLOCK_VARS of variables > >>>>>>>> declared in it, BLOCK_SUBBLOCKS of scopes nested in it, and > >>>>>>>> BLOCK_CHAIN pointing to the next BLOCK. Its BLOCK_SUPERCONTEXT > >>>>>>>> point to the BLOCK of the enclosing scope. May have > >>>>>>>> a BLOCK_ABSTRACT_ORIGIN and a BLOCK_SOURCE_LOCATION. > >>>>>>>> > >>>>>>>> BLOCK_SUPERCONTEXT: The scope of the enclosing block, or FUNCTION_DECL > >>>>>>>> for the "outermost" function scope. Inlined functions are chained by > >>>>>>>> this so that given expression E and its TREE_BLOCK(E) B, > >>>>>>>> BLOCK_SUPERCONTEXT(B) is the scope (BLOCK) in which E has been made > >>>>>>>> or into which E has been inlined. In the latter case, > >>>>>>>> > >>>>>>>> BLOCK_ORIGIN(B) evaluates either to the enclosing BLOCK or to > >>>>>>>> the enclosing function DECL. It's never null. > >>>>>>>> > >>>>>>>> BLOCK_ABSTRACT_ORIGIN(B) is the FUNCTION_DECL of the function into > >>>>>>>> which it has been inlined, or null if B is not inlined. > >>>>>>> > >>>>>>> It's the BLOCK or FUNCTION it was inlined _from_, not were it was > >>>>>>> inlined to. > >>>>>>> It's the "ultimate" source, thus the abstract copy of the block or > >>>>>>> function decl > >>>>>>> (for the outermost scope, aka inlined_function_outer_scope_p). It > >>>>>>> corresponds > >>>>>>> to what you'd expect for the DWARF abstract origin. > >>>>>> > >>>>>> Thanks for the correction! It's just the "innermost" block that > >>>>>> points to the "ultimate" destination into which it's been inlined. > >>>>>> > >>>>>>> > >>>>>>> BLOCK_ABSTRACT_ORIGIN can be NULL (in case it isn't an inline instance). > >>>>>>> > >>>>>>>> BLOCK_ABSTRACT_ORIGIN: A BLOCK, or FUNCTION_DECL of the function > >>>>>>>> into which a block has been inlined. In a BLOCK immediately enclosing > >>>>>>>> an inlined leaf expression points to the outermost BLOCK into which it > >>>>>>>> has been inlined (thus bypassing all intermediate BLOCK_SUPERCONTEXTs). > >>>>>>>> > >>>>>>>> BLOCK_FRAGMENT_ORIGIN: ??? > >>>>>>>> BLOCK_FRAGMENT_CHAIN: ??? > >>>>>>> > >>>>>>> that's for scope blocks split by hot/cold partitioning and only > >>>>>>> temporarily > >>>>>>> populated. > >>>>>> > >>>>>> Thanks, I now see these documented in detail in tree.h. > >>>>>> > >>>>>>> > >>>>>>>> bool inlined_function_outer_scope_p(BLOCK) [tree.h] > >>>>>>>> Returns true if a BLOCK has a source location. > >>>>>>>> True for all but the innermost (no SUBBLOCKs?) and outermost blocks > >>>>>>>> into which an expression has been inlined. (Is this always true?) > >>>>>>>> > >>>>>>>> tree block_ultimate_origin(BLOCK) [tree.c] > >>>>>>>> Returns BLOCK_ABSTRACT_ORIGIN(BLOCK), AO, after asserting that > >>>>>>>> (DECL_P(AO) && DECL_ORIGIN(AO) == AO) || BLOCK_ORIGIN(AO) == AO). > >>>>>> > >>>>>> The attached diff adds the comments above to tree.h. > >>>>>> > >>>>>> I looked for a good place in the manual to add the same text but I'm > >>>>>> not sure. Would the Blocks @subsection in generic.texi be appropriate? > >>>>>> > >>>>>> Martin > >>>>> > >>>>> > >>>> > >> > ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2021-02-08 10:37 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-01-14 19:13 [PATCH] keep scope blocks for all inlined functions (PR 98664) Martin Sebor 2021-01-15 7:44 ` Richard Biener 2021-01-17 0:46 ` Martin Sebor 2021-01-18 13:25 ` Richard Biener 2021-01-21 21:52 ` [PATCH] document BLOCK_ABSTRACT_ORIGIN et al Martin Sebor 2021-01-28 0:54 ` Martin Sebor 2021-02-01 16:20 ` Martin Sebor 2021-02-03 12:01 ` Richard Biener 2021-02-03 17:12 ` Martin Sebor 2021-02-04 8:48 ` Richard Biener 2021-02-06 19:11 ` Martin Sebor 2021-02-08 10:37 ` Richard Biener
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).