[llvm] r261218 - [Hexagon] Implement TLS support
Krzysztof Parzyszek via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 18 07:42:57 PST 2016
Author: kparzysz
Date: Thu Feb 18 09:42:57 2016
New Revision: 261218
URL: http://llvm.org/viewvc/llvm-project?rev=261218&view=rev
Log:
[Hexagon] Implement TLS support
Patch by Anand Kodnani.
Added:
llvm/trunk/test/CodeGen/Hexagon/tls_pic.ll
llvm/trunk/test/CodeGen/Hexagon/tls_static.ll
Modified:
llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp
llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.h
llvm/trunk/lib/Target/Hexagon/HexagonMCInstLower.cpp
llvm/trunk/lib/Target/Hexagon/HexagonRegisterInfo.cpp
llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
Modified: llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp?rev=261218&r1=261217&r2=261218&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp Thu Feb 18 09:42:57 2016
@@ -1518,7 +1518,7 @@ HexagonTargetLowering::LowerBlockAddress
Reloc::Model RM = HTM.getRelocationModel();
if (RM == Reloc::Static) {
- SDValue A = DAG.getTargetBlockAddress(BA, PtrVT);
+ SDValue A = DAG.getTargetBlockAddress(BA, PtrVT);
return DAG.getNode(HexagonISD::CONST32_GP, dl, PtrVT, A);
}
@@ -1535,6 +1535,158 @@ HexagonTargetLowering::LowerGLOBAL_OFFSE
return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), PtrVT, GOTSym);
}
+SDValue
+HexagonTargetLowering::GetDynamicTLSAddr(SelectionDAG &DAG, SDValue Chain,
+ GlobalAddressSDNode *GA, SDValue *InFlag, EVT PtrVT, unsigned ReturnReg,
+ unsigned char OperandFlags) const {
+ MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
+ SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
+ SDLoc dl(GA);
+ SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
+ GA->getValueType(0),
+ GA->getOffset(),
+ OperandFlags);
+ // Create Operands for the call.The Operands should have the following:
+ // 1. Chain SDValue
+ // 2. Callee which in this case is the Global address value.
+ // 3. Registers live into the call.In this case its R0, as we
+ // have just one argument to be passed.
+ // 4. InFlag if there is any.
+ // Note: The order is important.
+
+ if (InFlag) {
+ SDValue Ops[] = { Chain, TGA,
+ DAG.getRegister(Hexagon::R0, PtrVT), *InFlag };
+ Chain = DAG.getNode(HexagonISD::CALLv3, dl, NodeTys, Ops);
+ } else {
+ SDValue Ops[] = { Chain, TGA, DAG.getRegister(Hexagon::R0, PtrVT)};
+ Chain = DAG.getNode(HexagonISD::CALLv3, dl, NodeTys, Ops);
+ }
+
+ // Inform MFI that function has calls.
+ MFI->setAdjustsStack(true);
+
+ SDValue Flag = Chain.getValue(1);
+ return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Flag);
+}
+
+//
+// Lower using the intial executable model for TLS addresses
+//
+SDValue
+HexagonTargetLowering::LowerToTLSInitialExecModel(GlobalAddressSDNode *GA,
+ SelectionDAG &DAG) const {
+ SDLoc dl(GA);
+ int64_t Offset = GA->getOffset();
+ auto PtrVT = getPointerTy(DAG.getDataLayout());
+
+ // Get the thread pointer.
+ SDValue TP = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Hexagon::UGP, PtrVT);
+
+ Reloc::Model RM = HTM.getRelocationModel();
+ unsigned char TF = (RM == Reloc::PIC_) ? HexagonII::MO_IEGOT
+ : HexagonII::MO_IE;
+
+ // First generate the TLS symbol address
+ SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT,
+ Offset, TF);
+
+ SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
+
+ if (RM == Reloc::PIC_) {
+ // Generate the GOT pointer in case of position independent code
+ SDValue GOT = LowerGLOBAL_OFFSET_TABLE(Sym, DAG);
+
+ // Add the TLS Symbol address to GOT pointer.This gives
+ // GOT relative relocation for the symbol.
+ Sym = DAG.getNode(ISD::ADD, dl, PtrVT, GOT, Sym);
+ }
+
+ // Load the offset value for TLS symbol.This offset is relative to
+ // thread pointer.
+ SDValue LoadOffset = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Sym,
+ MachinePointerInfo(),
+ false, false, false, 0);
+
+ // Address of the thread local variable is the add of thread
+ // pointer and the offset of the variable.
+ return DAG.getNode(ISD::ADD, dl, PtrVT, TP, LoadOffset);
+}
+
+//
+// Lower using the local executable model for TLS addresses
+//
+SDValue
+HexagonTargetLowering::LowerToTLSLocalExecModel(GlobalAddressSDNode *GA,
+ SelectionDAG &DAG) const {
+ SDLoc dl(GA);
+ int64_t Offset = GA->getOffset();
+ auto PtrVT = getPointerTy(DAG.getDataLayout());
+
+ // Get the thread pointer.
+ SDValue TP = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Hexagon::UGP, PtrVT);
+ // Generate the TLS symbol address
+ SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT, Offset,
+ HexagonII::MO_TPREL);
+ SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
+
+ // Address of the thread local variable is the add of thread
+ // pointer and the offset of the variable.
+ return DAG.getNode(ISD::ADD, dl, PtrVT, TP, Sym);
+}
+
+//
+// Lower using the general dynamic model for TLS addresses
+//
+SDValue
+HexagonTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,
+ SelectionDAG &DAG) const {
+ SDLoc dl(GA);
+ int64_t Offset = GA->getOffset();
+ auto PtrVT = getPointerTy(DAG.getDataLayout());
+
+ // First generate the TLS symbol address
+ SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT, Offset,
+ HexagonII::MO_GDGOT);
+
+ // Then, generate the GOT pointer
+ SDValue GOT = LowerGLOBAL_OFFSET_TABLE(TGA, DAG);
+
+ // Add the TLS symbol and the GOT pointer
+ SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
+ SDValue Chain = DAG.getNode(ISD::ADD, dl, PtrVT, GOT, Sym);
+
+ // Copy over the argument to R0
+ SDValue InFlag;
+ Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, Hexagon::R0, Chain, InFlag);
+ InFlag = Chain.getValue(1);
+
+ return GetDynamicTLSAddr(DAG, Chain, GA, &InFlag, PtrVT,
+ Hexagon::R0, HexagonII::MO_GDPLT);
+}
+
+//
+// Lower TLS addresses.
+//
+// For now for dynamic models, we only support the general dynamic model.
+//
+SDValue
+HexagonTargetLowering::LowerGlobalTLSAddress(SDValue Op,
+ SelectionDAG &DAG) const {
+ GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
+
+ switch (HTM.getTLSModel(GA->getGlobal())) {
+ case TLSModel::GeneralDynamic:
+ case TLSModel::LocalDynamic:
+ return LowerToTLSGeneralDynamicModel(GA, DAG);
+ case TLSModel::InitialExec:
+ return LowerToTLSInitialExecModel(GA, DAG);
+ case TLSModel::LocalExec:
+ return LowerToTLSLocalExecModel(GA, DAG);
+ }
+ llvm_unreachable("Bogus TLS model");
+}
+
//===----------------------------------------------------------------------===//
// TargetLowering Implementation
//===----------------------------------------------------------------------===//
@@ -1638,6 +1790,7 @@ HexagonTargetLowering::HexagonTargetLowe
setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);
setOperationAction(ISD::GLOBAL_OFFSET_TABLE, MVT::i32, Custom);
+ setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
// Custom legalize GlobalAddress nodes into CONST32.
@@ -2626,6 +2779,7 @@ HexagonTargetLowering::LowerOperation(SD
// Frame & Return address. Currently unimplemented.
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
+ case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG);
case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG);
case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
Modified: llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.h?rev=261218&r1=261217&r2=261218&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.h (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.h Thu Feb 18 09:42:57 2016
@@ -136,6 +136,16 @@ bool isPositiveHalfWord(SDNode *N);
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const override;
SDValue LowerGLOBALADDRESS(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,
+ SelectionDAG &DAG) const;
+ SDValue LowerToTLSInitialExecModel(GlobalAddressSDNode *GA,
+ SelectionDAG &DAG) const;
+ SDValue LowerToTLSLocalExecModel(GlobalAddressSDNode *GA,
+ SelectionDAG &DAG) const;
+ SDValue GetDynamicTLSAddr(SelectionDAG &DAG, SDValue Chain,
+ GlobalAddressSDNode *GA, SDValue *InFlag, EVT PtrVT,
+ unsigned ReturnReg, unsigned char OperandFlags) const;
SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
Modified: llvm/trunk/lib/Target/Hexagon/HexagonMCInstLower.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonMCInstLower.cpp?rev=261218&r1=261217&r2=261218&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonMCInstLower.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonMCInstLower.cpp Thu Feb 18 09:42:57 2016
@@ -58,6 +58,21 @@ static MCOperand GetSymbolRef(const Mach
case HexagonII::MO_GPREL:
RelocationType = MCSymbolRefExpr::VK_Hexagon_GPREL;
break;
+ case HexagonII::MO_GDGOT:
+ RelocationType = MCSymbolRefExpr::VK_Hexagon_GD_GOT;
+ break;
+ case HexagonII::MO_GDPLT:
+ RelocationType = MCSymbolRefExpr::VK_Hexagon_GD_PLT;
+ break;
+ case HexagonII::MO_IE:
+ RelocationType = MCSymbolRefExpr::VK_Hexagon_IE;
+ break;
+ case HexagonII::MO_IEGOT:
+ RelocationType = MCSymbolRefExpr::VK_Hexagon_IE_GOT;
+ break;
+ case HexagonII::MO_TPREL:
+ RelocationType = MCSymbolRefExpr::VK_TPREL;
+ break;
}
ME = MCSymbolRefExpr::create(Symbol, RelocationType, MC);
Modified: llvm/trunk/lib/Target/Hexagon/HexagonRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonRegisterInfo.cpp?rev=261218&r1=261217&r2=261218&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonRegisterInfo.cpp Thu Feb 18 09:42:57 2016
@@ -121,6 +121,7 @@ BitVector HexagonRegisterInfo::getReserv
Reserved.set(Hexagon::LC1);
Reserved.set(Hexagon::SA0);
Reserved.set(Hexagon::SA1);
+ Reserved.set(Hexagon::UGP);
Reserved.set(Hexagon::GP);
Reserved.set(Hexagon::CS0);
Reserved.set(Hexagon::CS1);
Modified: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h?rev=261218&r1=261217&r2=261218&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h (original)
+++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h Thu Feb 18 09:42:57 2016
@@ -227,7 +227,27 @@ namespace HexagonII {
MO_LO16, MO_HI16,
// Offset from the base of the SDA.
- MO_GPREL
+ MO_GPREL,
+
+ // MO_GDGOT - indicates GOT relative relocation for TLS
+ // GeneralDynamic method
+ MO_GDGOT,
+
+ // MO_GDPLT - indicates PLT relative relocation for TLS
+ // GeneralDynamic method
+ MO_GDPLT,
+
+ // MO_IE - indicates non PIC relocation for TLS
+ // Initial Executable method
+ MO_IE,
+
+ // MO_IEGOT - indicates PIC relocation for TLS
+ // Initial Executable method
+ MO_IEGOT,
+
+ // MO_TPREL - indicates relocation for TLS
+ // local Executable method
+ MO_TPREL
};
// Hexagon Sub-instruction classes.
Added: llvm/trunk/test/CodeGen/Hexagon/tls_pic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Hexagon/tls_pic.ll?rev=261218&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Hexagon/tls_pic.ll (added)
+++ llvm/trunk/test/CodeGen/Hexagon/tls_pic.ll Thu Feb 18 09:42:57 2016
@@ -0,0 +1,37 @@
+; RUN: llc -O2 -march=hexagon -relocation-model=pic < %s | FileCheck %s
+
+ at dst_ie = thread_local(initialexec) global i32 0, align 4
+ at src_ie = thread_local(initialexec) global i32 0, align 4
+
+; CHECK-LABEL: test_initial_exec
+; CHECK: = add(pc, ##_GLOBAL_OFFSET_TABLE_ at PCREL)
+; CHECK-DAG: = ##src_ie at IEGOT
+; CHECK-DAG: = ##dst_ie at IEGOT
+; CHECK-DAG-NOT: call
+define i32 @test_initial_exec() nounwind {
+entry:
+ %0 = load i32, i32* @src_ie, align 4
+ store i32 %0, i32* @dst_ie, align 4
+ ret i32 0
+}
+
+ at dst_gd = external thread_local global i32
+ at src_gd = external thread_local global i32
+
+; At the moment, the local-dynamic model uses the same code as the
+; general-dynamic model.
+
+; CHECK-LABEL: test_dynamic
+; CHECK: = add(pc, ##_GLOBAL_OFFSET_TABLE_ at PCREL)
+; CHECK-DAG: = ##src_gd at GDGOT
+; CHECK-DAG: = ##dst_gd at GDGOT
+; CHECK-DAG: call src_gd at GDPLT
+; CHECK-DAG: call dst_gd at GDPLT
+
+define i32 @test_dynamic() nounwind {
+entry:
+ %0 = load i32, i32* @src_gd, align 4
+ store i32 %0, i32* @dst_gd, align 4
+ ret i32 0
+}
+
Added: llvm/trunk/test/CodeGen/Hexagon/tls_static.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Hexagon/tls_static.ll?rev=261218&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Hexagon/tls_static.ll (added)
+++ llvm/trunk/test/CodeGen/Hexagon/tls_static.ll Thu Feb 18 09:42:57 2016
@@ -0,0 +1,28 @@
+; RUN: llc -O2 -march=hexagon -relocation-model=static < %s | FileCheck %s
+
+ at dst_le = thread_local global i32 0, align 4
+ at src_le = thread_local global i32 0, align 4
+
+; CHECK-LABEL: test_local_exec
+; CHECK-DAG: = ##src_le at TPREL
+; CHECK-DAG: = ##dst_le at TPREL
+define i32 @test_local_exec() nounwind {
+entry:
+ %0 = load i32, i32* @src_le, align 4
+ store i32 %0, i32* @dst_le, align 4
+ ret i32 0
+}
+
+ at dst_ie = external thread_local global i32
+ at src_ie = external thread_local global i32
+
+; CHECK-LABEL: test_initial_exec:
+; CHECK-DAG: = memw(##src_ie at IE)
+; CHECK-DAG: = memw(##dst_ie at IE)
+define i32 @test_initial_exec() nounwind {
+entry:
+ %0 = load i32, i32* @src_ie, align 4
+ store i32 %0, i32* @dst_ie, align 4
+ ret i32 0
+}
+
More information about the llvm-commits
mailing list