This is an archive of the discontinued LLVM Phabricator instance.

New lower emutls pass, fix linkage bugs.
ClosedPublic

Authored by chh on Dec 7 2015, 12:30 PM.

Details

Summary

Previous implementation in http://reviews.llvm.org/D10522
created external references to __emutls_v.* variables.
Such references are inaccurate and cannot be handled by
all linkers, e.g. Android dynamic and gold linkers for aarch64.

Now a new LowerEmuTLS pass to go through all global variables,
and add emutls_v.* and emutls_t.* variables.
These __emutls* variables have the same linkage and
visibility as the associated user defined TLS variable.

Also removed old code that dump __emutls* variables in AsmPrinter.cpp,
and updated TLS unit tests.

Diff Detail

Repository
rL LLVM

Event Timeline

chh updated this revision to Diff 42093.Dec 7 2015, 12:30 PM
chh retitled this revision from to Fix wrong external references to __emutls_v.*.
chh updated this object.
chh added reviewers: rnk, beanz, resistor.
chh added subscribers: srhines, davidxl, danalbert and 3 others.
rnk added inline comments.Dec 9 2015, 12:54 PM
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
394–395 ↗(On Diff #42093)

Remind me why we bother making an IR-level GlobalVariable if we never want to emit it?

lib/CodeGen/SelectionDAG/TargetLowering.cpp
3072 ↗(On Diff #42093)

I guess I didn't pay enough attention on the first review. :(

We really shouldn't be modifying the IR in TargetLowering. We have some instances of that, but we shouldn't be adding more.

Long term, if we want to stick with the IR lowering strategy, maybe we should do it as an IR pass. I seem to recall Chandler objected strongly to that, though.

Anyway, setting the initializer and linkage here for now seems fine.

3088 ↗(On Diff #42093)

If we only need the global variable to make this GlobalAddress node, there are other ways to do that, like DAG.getExternalSymbol and DAG.getMCSymbol.

chh added inline comments.Dec 9 2015, 2:02 PM
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
394–395 ↗(On Diff #42093)

We do emit it, when the controlled variable xyz is visited by this function.
At that time, it is easier to emit both "emutls_v.xyz" and "emutls_t.xyz".
Originally, I didn't want to put either of them into symbol table,
but it turned out that it's easier to reuse codegen to access address of "__emutls_v.xyz"
if it is a global variable.

lib/CodeGen/SelectionDAG/TargetLowering.cpp
3072 ↗(On Diff #42093)

Agree, I thought about a special pass for TLS too, until I found the target dependent LowerGlobalTLSAddres.
So, here LowerToTLSEmulateMode is only a target independent special case of LowerGlobalTLSAddres.

3088 ↗(On Diff #42093)

I tried to do that, but maybe I did not make it all correct for an external symbol.
What I found out after my initial implementation is that get address of an external symbol would fail to link if the symbol is defined with internal linkage, for some linkers. That's what this patch to fix. So I would now make the symbol as real as necessary here to generate code to get the address.

rnk edited edge metadata.Dec 14 2015, 2:37 PM

I think the fact that you're excluding __emutls_v variables in AsmPrinter shows that this approach isn't a good one, and we need to go back and do it differently.

I think an IR preparation transform is going to be the cleanest, most portable way to do this.

lib/CodeGen/SelectionDAG/TargetLowering.cpp
3088 ↗(On Diff #42093)

True, you have to do lots of target specific things to get PIC access right.

chh added a comment.Dec 14 2015, 2:52 PM

I think what you meant is to let AsmPrinter emit
emutls_v and emutls_t variables and those variables
should have complete definition in symbol table.
That should be doable.

How about the original TLS variable xyz?
It should be skipped when in emutls mode,
as it is done now in AsmPrinter, right?

chh updated this revision to Diff 43026.Dec 16 2015, 10:25 AM
chh retitled this revision from Fix wrong external references to __emutls_v.* to New lower emutls pass, fix linkage bugs. .
chh updated this object.
chh edited edge metadata.

Now a new emutls lowering pass, plus fixing bugs.

rnk added a comment.Dec 16 2015, 11:16 AM

The general approach seems reasonable to me, but IIRC a ModulePass creates a scheduling barrier in the PassManager pipeline. You probably want to schedule it first at the top of addPassesToGenerateCode in LLVMTargetMachine.cpp.

chh updated this revision to Diff 43046.Dec 16 2015, 12:07 PM

Schedule LowerEmuTLS pass first at the top of addPassesToGenerateCode.

petarj added a subscriber: petarj.Dec 21 2015, 10:25 AM
rnk accepted this revision.Jan 12 2016, 3:57 PM
rnk edited edge metadata.

lgtm

lib/CodeGen/LowerEmuTLS.cpp
42 ↗(On Diff #43046)

What about COMDAT TLS variables? Consider this code:

template <typename T> struct A { static thread_local int x; };
int getX() { return A<int>::x++; }

Multiple TUs may instantiate A<int>::x, and we need __emutls_v._ZN1AIiE1xE to go in a comdat section.

Perhaps we can handle this in a subsequent patch, but it's good to think about.

105–106 ↗(On Diff #43046)

Don't create an EVT object in IR transforms, they aren't needed.

A better way to write this would be:

IntegerType *WordType = DL.getIntPtrType(C, 0);
112–114 ↗(On Diff #43046)

If you use cast<> instead of dyn_cast_or_null<>, this assertion will be performed for you implicitly.

This revision is now accepted and ready to land.Jan 12 2016, 3:57 PM
chh updated this revision to Diff 44799.Jan 13 2016, 3:08 PM
chh edited edge metadata.
chh marked 2 inline comments as done.

Handle comdat; simplify some code; add/update unit tests.

lib/CodeGen/LowerEmuTLS.cpp
42 ↗(On Diff #43046)

Good catch. Please take a look of the new diff.
I added also some unit test to AArch64/emutls.ll.
Thanks.

105–106 ↗(On Diff #43046)

Good suggestion. Thanks.

This revision was automatically updated to reflect the committed changes.