From 2ee3db3003deb18461a72b82166d8d417925d06f Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 17 Apr 2009 14:35:58 +0000 Subject: [PATCH] For general dynamic TLS access we must use leaq foo@TLSGD(%rip), %rdi as part of the instruction sequence. Using a register other than %rdi and then copying it to %rdi is not valid. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69350 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 49 ++++++++++++++------------------- lib/Target/X86/X86Instr64bit.td | 8 ++++-- lib/Target/X86/X86InstrInfo.td | 11 ++++---- test/CodeGen/X86/2009-04-17-tls-fast.ll | 17 ++++++++++++ 4 files changed, 49 insertions(+), 36 deletions(-) create mode 100644 test/CodeGen/X86/2009-04-17-tls-fast.ll diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 825e31d503c..cf3a6ce3b50 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -4754,6 +4754,23 @@ X86TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) { return LowerGlobalAddress(GV, Op.getDebugLoc(), Offset, DAG); } +static SDValue +GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA, + SDValue *InFlag) { + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + DebugLoc dl = GA->getDebugLoc(); + SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), + GA->getValueType(0), + GA->getOffset()); + if (InFlag) { + SDValue Ops[] = { Chain, TGA, *InFlag }; + return DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 3); + } else { + SDValue Ops[] = { Chain, TGA }; + return DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 2); + } +} + // Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit static SDValue LowerToTLSGeneralDynamicModel32(GlobalAddressSDNode *GA, SelectionDAG &DAG, @@ -4766,22 +4783,10 @@ LowerToTLSGeneralDynamicModel32(GlobalAddressSDNode *GA, SelectionDAG &DAG, PtrVT), InFlag); InFlag = Chain.getValue(1); - // emit leal symbol@TLSGD(,%ebx,1), %eax - SDVTList NodeTys = DAG.getVTList(PtrVT, MVT::Other, MVT::Flag); - SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), - GA->getValueType(0), - GA->getOffset()); - SDValue Ops[] = { Chain, TGA, InFlag }; - SDValue Result = DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 3); - InFlag = Result.getValue(2); - Chain = Result.getValue(1); - - // call ___tls_get_addr. This function receives its argument in - // the register EAX. - Chain = DAG.getCopyToReg(Chain, dl, X86::EAX, Result, InFlag); + Chain = GetTLSADDR(DAG, Chain, GA, &InFlag); InFlag = Chain.getValue(1); - NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); SDValue Ops1[] = { Chain, DAG.getTargetExternalSymbol("___tls_get_addr", PtrVT), @@ -4801,22 +4806,10 @@ LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA, SelectionDAG &DAG, SDValue InFlag, Chain; DebugLoc dl = GA->getDebugLoc(); // ? function entry point might be better - // emit leaq symbol@TLSGD(%rip), %rdi - SDVTList NodeTys = DAG.getVTList(PtrVT, MVT::Other, MVT::Flag); - SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), - GA->getValueType(0), - GA->getOffset()); - SDValue Ops[] = { DAG.getEntryNode(), TGA}; - SDValue Result = DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 2); - Chain = Result.getValue(1); - InFlag = Result.getValue(2); - - // call __tls_get_addr. This function receives its argument in - // the register RDI. - Chain = DAG.getCopyToReg(Chain, dl, X86::RDI, Result, InFlag); + Chain = GetTLSADDR(DAG, DAG.getEntryNode(), GA, NULL); InFlag = Chain.getValue(1); - NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); SDValue Ops1[] = { Chain, DAG.getTargetExternalSymbol("__tls_get_addr", PtrVT), diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index 1785bd13316..69c74b2c985 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -1303,9 +1303,11 @@ def MOV64ri64i32 : Ii32<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64i32imm:$src), // Thread Local Storage Instructions //===----------------------------------------------------------------------===// -def TLS_addr64 : I<0, Pseudo, (outs GR64:$dst), (ins i64imm:$sym), - ".byte\t0x66; leaq\t${sym:mem}(%rip), $dst; .word\t0x6666; rex64", - [(set GR64:$dst, (X86tlsaddr tglobaltlsaddr:$sym))]>; +let hasSideEffects = 1, Uses = [RDI] in +def TLS_addr64 : I<0, Pseudo, (outs), (ins i64imm:$sym), + ".byte\t0x66; leaq\t${sym:mem}(%rip), %rdi; .word\t0x6666; rex64", + [(X86tlsaddr tglobaltlsaddr:$sym)]>, + Requires<[In64BitMode]>; let AddedComplexity = 5 in def MOV64GSrm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 343691188b1..7cf1ad31fcb 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -63,7 +63,7 @@ def SDTX86RdTsc : SDTypeProfile<0, 0, []>; def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; -def SDT_X86TLSADDR : SDTypeProfile<1, 1, [SDTCisPtrTy<0>, SDTCisInt<1>]>; +def SDT_X86TLSADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; def SDT_X86SegmentBaseAddress : SDTypeProfile<1, 1, [SDTCisPtrTy<0>]>; @@ -2977,10 +2977,11 @@ def MOV32r0 : I<0x31, MRMInitReg, (outs GR32:$dst), (ins), // Thread Local Storage Instructions // -let Uses = [EBX] in -def TLS_addr32 : I<0, Pseudo, (outs GR32:$dst), (ins i32imm:$sym), - "leal\t${sym:mem}(,%ebx,1), $dst", - [(set GR32:$dst, (X86tlsaddr tglobaltlsaddr:$sym))]>; +let hasSideEffects = 1, Uses = [EAX, EBX] in +def TLS_addr32 : I<0, Pseudo, (outs), (ins i32imm:$sym), + "leal\t${sym:mem}(,%ebx,1), %eax", + [(X86tlsaddr tglobaltlsaddr:$sym)]>, + Requires<[In32BitMode]>; let AddedComplexity = 5 in def GS_MOV32rm : I<0x8B, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), diff --git a/test/CodeGen/X86/2009-04-17-tls-fast.ll b/test/CodeGen/X86/2009-04-17-tls-fast.ll new file mode 100644 index 00000000000..6a8054eae25 --- /dev/null +++ b/test/CodeGen/X86/2009-04-17-tls-fast.ll @@ -0,0 +1,17 @@ +; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu -relocation-model=pic -regalloc=local > %t +; RUN: grep {leaq foo@TLSGD(%rip), %rdi} %t + +@foo = internal thread_local global i32 100 + +define void @f(i32 %n) nounwind { +entry: + %n_addr = alloca i32 + %p = alloca i32* + %"alloca point" = bitcast i32 0 to i32 + store i32 %n, i32* %n_addr + store i32* @foo, i32** %p, align 8 + br label %return + +return: + ret void +} -- 2.11.0