From: David Majnemer Date: Wed, 20 May 2015 04:45:26 +0000 (+0000) Subject: [X86] Implement the local-exec TLS model for Windows targets X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=349f0b12a4d320bfe77efee513bc758e28cfd671;p=oota-llvm.git [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 --- diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index bfd99a55179..e83e62a4709 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -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); diff --git a/test/CodeGen/X86/tls.ll b/test/CodeGen/X86/tls.ll index 93ea8333d5c..0f3d3adec4c 100644 --- a/test/CodeGen/X86/tls.ll +++ b/test/CodeGen/X86/tls.ll @@ -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 +} +