Skip to content

[LTO] Dynamic initializer incorrectly optimized outΒ #110232

@mstorsjo

Description

@mstorsjo

Since 601645c, CC @rnk, the following testcase fails:

main.cpp:

int DoIt() { return 0; }
inline int Unused0 = DoIt();
int GetUnused();
int main(int, char **) { return GetUnused(); }

lib.cpp:

int DoIt();
inline int Unused0 = DoIt();
int GetUnused() { return Unused0; }

stub.c:

void __cxa_guard_acquire(void) {}
void __cxa_guard_release(void) {}
void __gxx_personality_seh0(void) {}
void __cxa_guard_abort(void) {}
void _Unwind_Resume(void) {}
void __main(void) {}

To reproduce:

$ clang -target x86_64-w64-mingw32 -c stub.c
$ clang -target x86_64-w64-mingw32 -c main.cpp -mguard=cf -flto=thin
$ clang -target x86_64-w64-mingw32 -c lib.cpp -mguard=cf -flto=thin
$ lld-link lib.o main.o stub.o -out:out.exe -entry:main
lld-link: error: undefined symbol: __cxx_global_var_init
>>> referenced by out.exe.lto.lib.obj

The reason for this is visible, if we inspect the output of the LTO compile:

$ lld-link lib.o main.o stub.o -out:out.exe -entry:main -lldemit:asm
$ cat out.exe.lto.main.s | grep -A1 -B1 __cxx_global_var_init
	.section	.gfids$y,"dr"
	.symidx	__cxx_global_var_init
	.section	.giats$y,"dr"
--
	.addrsig
	.addrsig_sym __cxx_global_var_init
	.addrsig_sym Unused0

So due to the -mguard=cf, we end up keeping a reference to __cxx_global_var_init in the .gfids$y section - but the LTO optimization itself has decided to optimize out the __cxx_global_var_init function entirely.

It seems like the exact ordering of object files is crucial here; if I swap the order of lib.o and main.o in this example, then out.exe.lto.main.s does retain the __cxx_global_var_init function, but out.exe.lto.lto.s has lost the function instead.

This was originally reported downstream at mstorsjo/llvm-mingw#457.

Debugging what really happens during the LTO compilation is somewhat finicky; if I grab the LTO IR with -lldemit:llvm -out:lto.bc and try to compile that with llc, I get different results as well. (In that case, I end up with an undefined GetUnused() function.)

As the referenced commit 601645c was NFCI, no functional changes intended, but we do have functional changes here, I think it would be reasonable to revert the commit.

Metadata

Metadata

Assignees

Labels

LTOLink time optimization (regular/full LTO or ThinLTO)llvm:codegen

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions