[X86] Implement the local-exec TLS model for Windows targets

We know that _tls_index is zero for local-exec TLS variables because
they are always defined in the executable.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237772 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer 2015-05-20 04:45:26 +00:00
parent 37e9aba0db
commit 349f0b12a4
2 changed files with 48 additions and 14 deletions

View File

@ -11289,7 +11289,6 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
if (Subtarget->isTargetELF()) {
TLSModel::Model model = DAG.getTarget().getTLSModel(GV);
switch (model) {
case TLSModel::GeneralDynamic:
if (Subtarget->is64Bit())
@ -11388,21 +11387,27 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
DAG.getLoad(getPointerTy(), dl, Chain, TlsArray,
MachinePointerInfo(Ptr), false, false, false, 0);
// Load the _tls_index variable
SDValue IDX = DAG.getExternalSymbol("_tls_index", getPointerTy());
if (Subtarget->is64Bit())
IDX = DAG.getExtLoad(ISD::ZEXTLOAD, dl, getPointerTy(), Chain,
IDX, MachinePointerInfo(), MVT::i32,
false, false, false, 0);
else
IDX = DAG.getLoad(getPointerTy(), dl, Chain, IDX, MachinePointerInfo(),
false, false, false, 0);
SDValue res;
if (GV->getThreadLocalMode() == GlobalVariable::LocalExecTLSModel) {
res = ThreadPointer;
} else {
// Load the _tls_index variable
SDValue IDX = DAG.getExternalSymbol("_tls_index", getPointerTy());
if (Subtarget->is64Bit())
IDX = DAG.getExtLoad(ISD::ZEXTLOAD, dl, getPointerTy(), Chain, IDX,
MachinePointerInfo(), MVT::i32, false, false,
false, 0);
else
IDX = DAG.getLoad(getPointerTy(), dl, Chain, IDX, MachinePointerInfo(),
false, false, false, 0);
SDValue Scale = DAG.getConstant(Log2_64_Ceil(TD->getPointerSize()), dl,
getPointerTy());
IDX = DAG.getNode(ISD::SHL, dl, getPointerTy(), IDX, Scale);
SDValue Scale = DAG.getConstant(Log2_64_Ceil(TD->getPointerSize()), dl,
getPointerTy());
IDX = DAG.getNode(ISD::SHL, dl, getPointerTy(), IDX, Scale);
res = DAG.getNode(ISD::ADD, dl, getPointerTy(), ThreadPointer, IDX);
}
SDValue res = DAG.getNode(ISD::ADD, dl, getPointerTy(), ThreadPointer, IDX);
res = DAG.getLoad(getPointerTy(), dl, Chain, res, MachinePointerInfo(),
false, false, false, 0);

View File

@ -12,6 +12,7 @@
@i5 = external hidden thread_local global i32
@s1 = thread_local global i16 15
@b1 = thread_local global i8 0
@b2 = thread_local(localexec) global i8 0
define i32 @f1() {
; X32_LINUX-LABEL: f1:
@ -409,3 +410,31 @@ entry:
ret i32 %tmp2
}
define i8* @f15() {
; X32_LINUX-LABEL: f15:
; X32_LINUX: movl %gs:0, %eax
; X32_LINUX-NEXT: leal b2@NTPOFF(%eax), %eax
; X32_LINUX-NEXT: ret
; X64_LINUX-LABEL: f15:
; X64_LINUX: movq %fs:0, %rax
; X64_LINUX-NEXT: leaq b2@TPOFF(%rax), %rax
; X64_LINUX-NEXT: ret
; X32_WIN-LABEL: f15:
; X32_WIN: movl %fs:__tls_array, %eax
; X32_WIN-NEXT: movl (%eax), %eax
; X32_WIN-NEXT: leal _b2@SECREL32(%eax), %eax
; X32_WIN-NEXT: ret
; X64_WIN-LABEL: f15:
; X64_WIN: movq %gs:88, %rax
; X64_WIN-NEXT: movq (%rax), %rax
; X64_WIN-NEXT: leaq b2@SECREL32(%rax), %rax
; X64_WIN-NEXT: ret
; MINGW32-LABEL: f15:
; MINGW32: movl %fs:44, %eax
; MINGW32-NEXT: movl (%eax), %eax
; MINGW32-NEXT: leal _b2@SECREL32(%eax), %eax
; MINGW32-NEXT: ret
entry:
ret i8* @b2
}