diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -19123,7 +19123,7 @@ return GetTLSADDR(DAG, Chain, GA, &InFlag, PtrVT, X86::EAX, X86II::MO_TLSGD); } -// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 64 bit +// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 64 bit LP64 static SDValue LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA, SelectionDAG &DAG, const EVT PtrVT) { @@ -19131,6 +19131,14 @@ X86::RAX, X86II::MO_TLSGD); } +// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 64 bit ILP32 +static SDValue +LowerToTLSGeneralDynamicModelX32(GlobalAddressSDNode *GA, SelectionDAG &DAG, + const EVT PtrVT) { + return GetTLSADDR(DAG, DAG.getEntryNode(), GA, nullptr, PtrVT, + X86::EAX, X86II::MO_TLSGD); +} + static SDValue LowerToTLSLocalDynamicModel(GlobalAddressSDNode *GA, SelectionDAG &DAG, const EVT PtrVT, @@ -19241,8 +19249,11 @@ TLSModel::Model model = DAG.getTarget().getTLSModel(GV); switch (model) { case TLSModel::GeneralDynamic: - if (Subtarget.is64Bit()) - return LowerToTLSGeneralDynamicModel64(GA, DAG, PtrVT); + if (Subtarget.is64Bit()) { + if (Subtarget.isTarget64BitLP64()) + return LowerToTLSGeneralDynamicModel64(GA, DAG, PtrVT); + return LowerToTLSGeneralDynamicModelX32(GA, DAG, PtrVT); + } return LowerToTLSGeneralDynamicModel32(GA, DAG, PtrVT); case TLSModel::LocalDynamic: return LowerToTLSLocalDynamicModel(GA, DAG, PtrVT, @@ -33511,8 +33522,10 @@ default: llvm_unreachable("Unexpected instr type to insert"); case X86::TLS_addr32: case X86::TLS_addr64: + case X86::TLS_addrX32: case X86::TLS_base_addr32: case X86::TLS_base_addr64: + case X86::TLS_base_addrX32: return EmitLoweredTLSAddr(MI, BB); case X86::INDIRECT_THUNK_CALL32: case X86::INDIRECT_THUNK_CALL64: diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td --- a/llvm/lib/Target/X86/X86InstrCompiler.td +++ b/llvm/lib/Target/X86/X86InstrCompiler.td @@ -467,11 +467,19 @@ def TLS_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym), "# TLS_addr64", [(X86tlsaddr tls64addr:$sym)]>, - Requires<[In64BitMode]>; + Requires<[In64BitMode, IsLP64]>; def TLS_base_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym), "# TLS_base_addr64", [(X86tlsbaseaddr tls64baseaddr:$sym)]>, - Requires<[In64BitMode]>; + Requires<[In64BitMode, IsLP64]>; +def TLS_addrX32 : I<0, Pseudo, (outs), (ins i32mem:$sym), + "# TLS_addrX32", + [(X86tlsaddr tls32addr:$sym)]>, + Requires<[In64BitMode, NotLP64]>; +def TLS_base_addrX32 : I<0, Pseudo, (outs), (ins i32mem:$sym), + "# TLS_base_addrX32", + [(X86tlsbaseaddr tls32baseaddr:$sym)]>, + Requires<[In64BitMode, NotLP64]>; } // Darwin TLS Support diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -977,20 +977,22 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering, const MachineInstr &MI) { NoAutoPaddingScope NoPadScope(*OutStreamer); - bool Is64Bits = MI.getOpcode() == X86::TLS_addr64 || - MI.getOpcode() == X86::TLS_base_addr64; + bool Is64Bits = MI.getOpcode() != X86::TLS_addr32 && + MI.getOpcode() != X86::TLS_base_addr32; MCContext &Ctx = OutStreamer->getContext(); MCSymbolRefExpr::VariantKind SRVK; switch (MI.getOpcode()) { case X86::TLS_addr32: case X86::TLS_addr64: + case X86::TLS_addrX32: SRVK = MCSymbolRefExpr::VK_TLSGD; break; case X86::TLS_base_addr32: SRVK = MCSymbolRefExpr::VK_TLSLDM; break; case X86::TLS_base_addr64: + case X86::TLS_base_addrX32: SRVK = MCSymbolRefExpr::VK_TLSLD; break; default: @@ -2445,8 +2447,10 @@ case X86::TLS_addr32: case X86::TLS_addr64: + case X86::TLS_addrX32: case X86::TLS_base_addr32: case X86::TLS_base_addr64: + case X86::TLS_base_addrX32: return LowerTlsAddr(MCInstLowering, *MI); case X86::MOVPC32r: { diff --git a/llvm/test/CodeGen/X86/pic.ll b/llvm/test/CodeGen/X86/pic.ll --- a/llvm/test/CodeGen/X86/pic.ll +++ b/llvm/test/CodeGen/X86/pic.ll @@ -252,3 +252,36 @@ declare void @foo3(...) declare void @foo4(...) declare void @foo5(...) + +;; Check TLS references +@tlsptr = external thread_local global i32* +@tlsdst = external thread_local global i32 +@tlssrc = external thread_local global i32 + +define void @test8() nounwind { +entry: + store i32* @tlsdst, i32** @tlsptr + %tmp.s = load i32, i32* @tlssrc + store i32 %tmp.s, i32* @tlsdst + ret void + +; CHECK-LABEL: test8: +; CHECK-I686: calll .L8$pb +; CHECK-I686-NEXT: .L8$pb: +; CHECK-I686-NEXT: popl +; CHECK-I686: addl $_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L8$pb), %ebx +; CHECK-I686-DAG: leal tlsdst@TLSGD(,%ebx), %eax +; CHECK-I686-DAG: calll ___tls_get_addr@PLT +; CHECK-I686-DAG: leal tlsptr@TLSGD(,%ebx), %eax +; CHECK-I686-DAG: calll ___tls_get_addr@PLT +; CHECK-I686-DAG: leal tlssrc@TLSGD(,%ebx), %eax +; CHECK-I686-DAG: calll ___tls_get_addr@PLT +; CHECK-X32-DAG: leaq tlsdst@TLSGD(%rip), %rdi +; CHECK-X32-DAG: callq __tls_get_addr@PLT +; CHECK-X32-DAG: leaq tlsptr@TLSGD(%rip), %rdi +; CHECK-X32-DAG: callq __tls_get_addr@PLT +; CHECK-X32-DAG: leaq tlssrc@TLSGD(%rip), %rdi +; CHECK-X32-DAG: callq __tls_get_addr@PLT +; CHECK-I686: ret +; CHECK-X32: retq +}