[PATCH] D43077: [ThinLTO] Import external globals
Teresa Johnson via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 12 07:06:01 PST 2018
tejohnson added inline comments.
================
Comment at: lib/Linker/IRMover.cpp:1442
+ IRMover::StructTypeKeyInfo::KeyTy((*NI).second) == Key)
+ return (*NI).second;
+ return *I;
----------------
evgeny777 wrote:
> tejohnson wrote:
> > I'm not as familiar with the struct mapping - what happens without this change? Why did importing variables necessitate it?
> Consider this C++ program, which consists of three TUs:
>
> main.cpp:
> ```
> struct Bar { i64 a,b; } B; // Do not optimize this out
> struct Foo { i64 a, b; }; // Foo is isomorphic to Bar
>
> Foo *getFoo(); // We'll import this function from foo.cpp
> struct S { Foo *_f } instance = { getFoo(); };
>
> void main() { return instance._f->a; }
> ```
>
> foo.cpp
> ```
> struct Foo { i64 a, b; }; // Same as in main.cpp
> struct Baz { i64 a, b; Foo f; };
>
> Foo *gFoo;
> extern Baz *gBaz;
>
> Foo *getFoo() {
> return gFoo ? gFoo : &gBaz->f;
> }
> ```
>
> baz.cpp
> ```
> struct Foo { i64 a, b; };
> struct Baz { i64 a, b; Foo f; }; // Same as in foo.cpp
>
> Baz *gBaz;
> ```
>
> Now you perform thinlto import and get following definition of Baz in main.o0.3.import.bc when no name mapping used:
> ```
> %struct.Bar = type { i64, i64 }
> %struct.Foo = type { i64, i64 }
>
> ; This is incorrect. We should have %struct.Foo in the 3rd field
> ; This happens because Foo and Bar are recursively isomorphic
> ; and Bar is seen first by IRLinker.
> %struct.Baz = type { i64, i64, %struct.Bar }
> ```
>
> The faulted import causes bitcast created in static constructor:
> ```
> ; This static constructor can't be evaluated due to a bitcast (Bar -> Foo)
> define internal void @_GLOBAL__sub_I_main.cpp() #1 section ".text.startup" {
> entry:
> %call.i.i = tail call %struct.Foo* bitcast (%struct.Bar* ()* @_Z6getFoov to %struct.Foo* ()*)()
> store %struct.Foo* %call.i.i, %struct.Foo** getelementptr inbounds (%struct.S, %struct.S* @instance, i64 0, i32 0), align 8, !tbaa !2
> ret void
> }
> ```
>
> Adding name mapping fixes the problem:
> ```
> %struct.Baz = type { i64, i64, %struct.Foo } ; Good
>
> ; No bitcast - evaluator is happy.
> define internal void @_GLOBAL__sub_I_main.cpp() section ".text.startup" {
> entry:
> %call.i.i = tail call %struct.Foo* @getFoo()
> store %struct.Foo* %call.i.i, %struct.Foo** getelementptr inbounds (%struct.S, %struct.S* @instance, i64 0, i32 0), align 8
> ret void
> }
> ```
>
> The problem isn't specific at all to importing globals. You can easily rewrite this example to using functions (i.e gBaz -> getBaz) and get the same result. (it probably makes sense to divide this patch into two separate ones).
>
> BTW the negative impact of those bitcasts isn't limited to evaluator. It also affects inliner behavior - see D38896
>
Thanks for the detailed explanation. Since this isn't specific to the importing of variables, and can happen already with functions, please do separate out into a different patch.
https://reviews.llvm.org/D43077
More information about the llvm-commits
mailing list