From 6625eff8ec38095e9dab31294a86555a489e56a4 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Sun, 4 May 2008 21:36:32 +0000 Subject: [PATCH] Add General Dynamic TLS model for X86-64. Some parts looks really ugly (look for tlsaddr pattern), but should work. Work is in progress, more models will follow git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50630 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ATTAsmPrinter.cpp | 4 +- lib/Target/X86/X86ISelLowering.cpp | 57 ++++++++++++++++++++++++----- lib/Target/X86/X86Instr64bit.td | 7 ++++ lib/Target/X86/X86InstrInfo.td | 10 ++--- 4 files changed, 62 insertions(+), 16 deletions(-) diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp index 78240b36333..6909da1b245 100644 --- a/lib/Target/X86/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/X86ATTAsmPrinter.cpp @@ -347,7 +347,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, if (GV->hasExternalWeakLinkage()) ExtWeakSymbols.insert(GV); - + int Offset = MO.getOffset(); if (Offset > 0) O << "+" << Offset; @@ -355,7 +355,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, O << Offset; if (isThreadLocal) { - if (TM.getRelocationModel() == Reloc::PIC_) + if (TM.getRelocationModel() == Reloc::PIC_ || Subtarget->is64Bit()) O << "@TLSGD"; // general dynamic TLS model else if (GV->isDeclaration()) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 440839933df..e90c9303f3d 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -267,6 +267,8 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) setOperationAction(ISD::JumpTable , MVT::i32 , Custom); setOperationAction(ISD::GlobalAddress , MVT::i32 , Custom); setOperationAction(ISD::GlobalTLSAddress, MVT::i32 , Custom); + if (Subtarget->is64Bit()) + setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); setOperationAction(ISD::ExternalSymbol , MVT::i32 , Custom); if (Subtarget->is64Bit()) { setOperationAction(ISD::ConstantPool , MVT::i64 , Custom); @@ -4001,10 +4003,10 @@ X86TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) { return Result; } -// Lower ISD::GlobalTLSAddress using the "general dynamic" model +// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit static SDOperand -LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, SelectionDAG &DAG, - const MVT::ValueType PtrVT) { +LowerToTLSGeneralDynamicModel32(GlobalAddressSDNode *GA, SelectionDAG &DAG, + const MVT::ValueType PtrVT) { SDOperand InFlag; SDOperand Chain = DAG.getCopyToReg(DAG.getEntryNode(), X86::EBX, DAG.getNode(X86ISD::GlobalBaseReg, @@ -4039,6 +4041,39 @@ LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, SelectionDAG &DAG, return DAG.getCopyFromReg(Chain, X86::EAX, PtrVT, InFlag); } +// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 64 bit +static SDOperand +LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA, SelectionDAG &DAG, + const MVT::ValueType PtrVT) { + SDOperand InFlag, Chain; + + // emit leaq symbol@TLSGD(%rip), %rdi + SDVTList NodeTys = DAG.getVTList(PtrVT, MVT::Other, MVT::Flag); + SDOperand TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), + GA->getValueType(0), + GA->getOffset()); + SDOperand Ops[] = { DAG.getEntryNode(), TGA}; + SDOperand Result = DAG.getNode(X86ISD::TLSADDR, 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, X86::RDI, Result, InFlag); + InFlag = Chain.getValue(1); + + NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SDOperand Ops1[] = { Chain, + DAG.getTargetExternalSymbol("___tls_get_addr", + PtrVT), + DAG.getRegister(X86::RDI, PtrVT), + InFlag }; + Chain = DAG.getNode(X86ISD::CALL, NodeTys, Ops1, 4); + InFlag = Chain.getValue(1); + + return DAG.getCopyFromReg(Chain, X86::RAX, PtrVT, InFlag); +} + // Lower ISD::GlobalTLSAddress using the "initial exec" (for no-pic) or // "local exec" model. static SDOperand @@ -4066,15 +4101,19 @@ SDOperand X86TargetLowering::LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG) { // TODO: implement the "local dynamic" model // TODO: implement the "initial exec"model for pic executables - assert(!Subtarget->is64Bit() && Subtarget->isTargetELF() && - "TLS not implemented for non-ELF and 64-bit targets"); + assert(Subtarget->isTargetELF() && + "TLS not implemented for non-ELF targets"); GlobalAddressSDNode *GA = cast(Op); // If the relocation model is PIC, use the "General Dynamic" TLS Model, // otherwise use the "Local Exec"TLS Model - if (getTargetMachine().getRelocationModel() == Reloc::PIC_) - return LowerToTLSGeneralDynamicModel(GA, DAG, getPointerTy()); - else - return LowerToTLSExecModel(GA, DAG, getPointerTy()); + if (Subtarget->is64Bit()) { + return LowerToTLSGeneralDynamicModel64(GA, DAG, getPointerTy()); + } else { + if (getTargetMachine().getRelocationModel() == Reloc::PIC_) + return LowerToTLSGeneralDynamicModel32(GA, DAG, getPointerTy()); + else + return LowerToTLSExecModel(GA, DAG, getPointerTy()); + } } SDOperand diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index 1bf1b1aedb1..25a7b56ace0 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -1102,6 +1102,13 @@ def MOV64ri64i32 : Ii32<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64i32imm:$src), "mov{l}\t{$src, ${dst:subreg32}|${dst:subreg32}, $src}", [(set GR64:$dst, i64immZExt32:$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))]>; //===----------------------------------------------------------------------===// // Atomic Instructions diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index bea4798f52d..c539eca940c 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -109,7 +109,7 @@ def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", SDTX86Wrapper>; def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR, - [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>; + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; def X86TLStp : SDNode<"X86ISD::THREAD_POINTER", SDT_X86TLSTP, []>; def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET, @@ -2500,12 +2500,12 @@ def MOV32_mr : I<0x89, MRMDestMem, (outs), (ins i32mem:$dst, GR32_:$src), // let Uses = [EBX] in -def TLS_addr : I<0, Pseudo, (outs GR32:$dst), (ins i32imm:$sym), - "leal\t${sym:mem}(,%ebx,1), $dst", - [(set GR32:$dst, (X86tlsaddr tglobaltlsaddr:$sym))]>; +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 AddedComplexity = 10 in -def TLS_gs_rr : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src), +def TLS_gs_rr : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src), "movl\t%gs:($src), $dst", [(set GR32:$dst, (load (add X86TLStp, GR32:$src)))]>;