[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