* [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).