From 15f1b66d64b3c79966e2d36a39817eb97ea579aa Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 24 Apr 2009 12:59:40 +0000 Subject: [PATCH] Fix PR 4004 by including the call to __tls_get_addr in X86tlsaddr. This is not very elegant, but neither is the tls specification :-( git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69968 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 40 ++++++------------------------ lib/Target/X86/X86Instr64bit.td | 12 +++++++-- lib/Target/X86/X86InstrInfo.td | 11 ++++++-- test/CodeGen/X86/2009-04-24.ll | 13 ++++++++++ 4 files changed, 39 insertions(+), 37 deletions(-) create mode 100644 test/CodeGen/X86/2009-04-24.ll diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index d51435cf873..5c9b7bfa8ae 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -4745,7 +4745,7 @@ X86TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) { static SDValue GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA, - SDValue *InFlag) { + SDValue *InFlag, const MVT PtrVT, unsigned ReturnReg) { SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); DebugLoc dl = GA->getDebugLoc(); SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), @@ -4753,11 +4753,13 @@ GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA, GA->getOffset()); if (InFlag) { SDValue Ops[] = { Chain, TGA, *InFlag }; - return DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 3); + Chain = DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 3); } else { SDValue Ops[] = { Chain, TGA }; - return DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 2); + Chain = DAG.getNode(X86ISD::TLSADDR, dl, NodeTys, Ops, 2); } + SDValue Flag = Chain.getValue(1); + return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Flag); } // Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit @@ -4772,42 +4774,14 @@ LowerToTLSGeneralDynamicModel32(GlobalAddressSDNode *GA, SelectionDAG &DAG, PtrVT), InFlag); InFlag = Chain.getValue(1); - Chain = GetTLSADDR(DAG, Chain, GA, &InFlag); - InFlag = Chain.getValue(1); - - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); - SDValue Ops1[] = { Chain, - DAG.getTargetExternalSymbol("___tls_get_addr", - PtrVT), - DAG.getRegister(X86::EAX, PtrVT), - DAG.getRegister(X86::EBX, PtrVT), - InFlag }; - Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, Ops1, 5); - InFlag = Chain.getValue(1); - - return DAG.getCopyFromReg(Chain, dl, X86::EAX, PtrVT, InFlag); + return GetTLSADDR(DAG, Chain, GA, &InFlag, PtrVT, X86::EAX); } // Lower ISD::GlobalTLSAddress using the "general dynamic" model, 64 bit static SDValue LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA, SelectionDAG &DAG, const MVT PtrVT) { - SDValue InFlag, Chain; - DebugLoc dl = GA->getDebugLoc(); // ? function entry point might be better - - Chain = GetTLSADDR(DAG, DAG.getEntryNode(), GA, NULL); - InFlag = Chain.getValue(1); - - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); - SDValue Ops1[] = { Chain, - DAG.getTargetExternalSymbol("__tls_get_addr", - PtrVT), - DAG.getRegister(X86::RDI, PtrVT), - InFlag }; - Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, Ops1, 4); - InFlag = Chain.getValue(1); - - return DAG.getCopyFromReg(Chain, dl, X86::RAX, PtrVT, InFlag); + return GetTLSADDR(DAG, DAG.getEntryNode(), GA, NULL, PtrVT, X86::RAX); } // Lower ISD::GlobalTLSAddress using the "initial exec" (for no-pic) or diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index e84d1368f46..728811ef098 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -1303,9 +1303,17 @@ def MOV64ri64i32 : Ii32<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64i32imm:$src), // Thread Local Storage Instructions //===----------------------------------------------------------------------===// -let hasSideEffects = 1, Defs = [RDI] in +// All calls clobber the non-callee saved registers. RSP is marked as +// a use to prevent stack-pointer assignments that appear immediately +// before calls from potentially appearing dead. +let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, + FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, ST1, + MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, + XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], + Uses = [RSP] in def TLS_addr64 : I<0, Pseudo, (outs), (ins i64imm:$sym), - ".byte\t0x66; leaq\t${sym:mem}(%rip), %rdi; .word\t0x6666; rex64", + ".byte\t0x66; leaq\t${sym:mem}(%rip), %rdi; .word\t0x6666; rex64;call\t__tls_get_addr@PLT", [(X86tlsaddr tglobaltlsaddr:$sym)]>, Requires<[In64BitMode]>; diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 462433bb27b..3aa344738d0 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -2977,9 +2977,16 @@ def MOV32r0 : I<0x31, MRMInitReg, (outs GR32:$dst), (ins), // Thread Local Storage Instructions // -let hasSideEffects = 1, Uses = [EBX], Defs = [EAX] in +// All calls clobber the non-callee saved registers. ESP is marked as +// a use to prevent stack-pointer assignments that appear immediately +// before calls from potentially appearing dead. +let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, + MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, + XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], + Uses = [ESP, EBX] in def TLS_addr32 : I<0, Pseudo, (outs), (ins i32imm:$sym), - "leal\t${sym:mem}(,%ebx,1), %eax", + "leal\t${sym:mem}(,%ebx,1), %eax; call\t___tls_get_addr@PLT", [(X86tlsaddr tglobaltlsaddr:$sym)]>, Requires<[In32BitMode]>; diff --git a/test/CodeGen/X86/2009-04-24.ll b/test/CodeGen/X86/2009-04-24.ll new file mode 100644 index 00000000000..cb41415dba2 --- /dev/null +++ b/test/CodeGen/X86/2009-04-24.ll @@ -0,0 +1,13 @@ +; RUN: llvm-as < %s | llc -march=x86 -mtriple=i386-linux-gnu -regalloc=local -relocation-model=pic > %t +; RUN: grep {leal.*TLSGD.*___tls_get_addr} %t +; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=x86_64-linux-gnu -regalloc=local -relocation-model=pic > %t2 +; RUN: grep {leaq.*TLSGD.*__tls_get_addr} %t2 +; PR/4004 + +@i = thread_local global i32 15 + +define i32 @f() { +entry: + %tmp1 = load i32* @i + ret i32 %tmp1 +}