[Bug c/106725] New: LTO semantics for __attribute__((leaf))
dthorn at google dot com
gcc-bugzilla@gcc.gnu.org
Tue Aug 23 18:09:49 GMT 2022
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106725
Bug ID: 106725
Summary: LTO semantics for __attribute__((leaf))
Product: gcc
Version: 12.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: dthorn at google dot com
Target Milestone: ---
After implementing GCC's `__attribute__((leaf))` in Clang/LLVM, discussion
arose (https://reviews.llvm.org/D131628#3740602) about the semantics of LTO.
It seems like merging together object files in LTO might or might notproduce
erroneous results, depending on how the term "compilation unit" in the docs are
interpreted.
A minimal example consists of three source files:
main.c:
__attribute__((leaf)) void foo(void);
int main(void) {
foo();
return 0;
}
foo.c:
void bar(void);
void foo(void) {
bar();
}
bar.c:
void bar(void) {}
If "compilation unit" in the `__attribute__((leaf))` manual means "translation
unit", `__attribute__((leaf))` should be valid in main.c, since foo() only
calls bar(), which is not in the main.c translation unit.
Compile main.c and bar.c to LTO GIMPLE, but compile foo.c without LTO:
$ gcc -flto -c main.c bar.c
$ gcc -c foo.c
The resulting GIMPLE and object files can then be linked together and the LTO
trees dumped (Here I'm using -nostdlib just because I built gcc in isolation).
I installed a simple printf hack to gimple-pretty-print to print "leaf" if
ECF_LEAF is set on a printed call. This gives the following results:
$ gcc -fdump-tree-all main.o bar.o foo.o
$ cat a.ltrans0.ltrans.252t.optimized
<...>
int main ()
{
<...>
foo (); check 1 1024 leaf
<...>
}
;; Function bar (bar, funcdef_no=1, decl_uid=4720, cgraph_uid=1,
symbol_order=2)
<...>
>From the above, it appears that the main and bar translation units are merged
together by LTO to form a new module without altering the
`__attribute__((leaf))` semantics given on the call to foo() in main().
If "compilation unit" is interpreted as "translation unit", this may be
incorrect behavior, since any post-LTO passes that are expecting that foo()
cannot call bar() (since it's in the same TU) would have their expectations
violated.
If instead "compilation unit" is interpreted as "LTO unit", `then the above
program has undefined behavior, since `__attribute__((leaf)) should never have
been used on foo(), since it calls something (bar()) in the same LTO unit as
main.c.
Accordingly, if "compilation unit" means "translation unit" and this case is
incorrect behavior, this bug is to report this.
If "compilation unit" instead means "LTO unit", this bug is to request
clarification in the GCC manual about the precise behavior in case of LTO.
Finally, if "compilation unit" means "translation unit", but GCC has some other
internal mechanisms for dealing with this, feel free to close this. Please do
report back with those mechanisms though, as we'll have to do something similar
in LLVM in that case. It still may be worth altering the docs, given the
ambiguity in the term "compilation unit" in the presence of LTO.
System: Debian rodete
GCC build commands used:
../configure --disable-bootstrap --enable-languages=c,c++,lto \
--prefix=$(realpath ..)/gcc-install
make -j96 -l96 all-gcc
make install-gcc
More information about the Gcc-bugs
mailing list