[llvm] r257039 - ARM: support TLS accesses on Darwin platforms

Tim Northover via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 7 01:03:04 PST 2016


Author: tnorthover
Date: Thu Jan  7 03:03:03 2016
New Revision: 257039

URL: http://llvm.org/viewvc/llvm-project?rev=257039&view=rev
Log:
ARM: support TLS accesses on Darwin platforms

Darwin TLS accesses most closely resemble ELF's general-dynamic situation,
since they have to be able to handle all possible situations. The descriptors
and so on are obviously slightly different though.

Added:
    llvm/trunk/test/CodeGen/ARM/darwin-tls.ll
Modified:
    llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp
    llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h
    llvm/trunk/lib/Target/ARM/ARMCallingConv.td
    llvm/trunk/lib/Target/ARM/ARMFastISel.cpp
    llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp
    llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
    llvm/trunk/lib/Target/ARM/ARMISelLowering.h
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
    llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td

Modified: llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp?rev=257039&r1=257038&r2=257039&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp Thu Jan  7 03:03:03 2016
@@ -106,6 +106,14 @@ ARMBaseRegisterInfo::getNoPreservedMask(
 }
 
 const uint32_t *
+ARMBaseRegisterInfo::getTLSCallPreservedMask(const MachineFunction &MF) const {
+  assert(MF.getSubtarget<ARMSubtarget>().isTargetDarwin() &&
+         "only know about special TLS call on Darwin");
+  return CSR_iOS_TLSCall_RegMask;
+}
+
+
+const uint32_t *
 ARMBaseRegisterInfo::getThisReturnPreservedMask(const MachineFunction &MF,
                                                 CallingConv::ID CC) const {
   const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();

Modified: llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h?rev=257039&r1=257038&r2=257039&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h Thu Jan  7 03:03:03 2016
@@ -95,6 +95,7 @@ public:
   const uint32_t *getCallPreservedMask(const MachineFunction &MF,
                                        CallingConv::ID) const override;
   const uint32_t *getNoPreservedMask() const override;
+  const uint32_t *getTLSCallPreservedMask(const MachineFunction &MF) const;
 
   /// getThisReturnPreservedMask - Returns a call preserved mask specific to the
   /// case that 'returned' is on an i32 first argument if the calling convention

Modified: llvm/trunk/lib/Target/ARM/ARMCallingConv.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMCallingConv.td?rev=257039&r1=257038&r2=257039&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMCallingConv.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMCallingConv.td Thu Jan  7 03:03:03 2016
@@ -225,6 +225,10 @@ def CSR_iOS : CalleeSavedRegs<(add LR, R
 def CSR_iOS_ThisReturn : CalleeSavedRegs<(add LR, R7, R6, R5, R4,
                                          (sub CSR_AAPCS_ThisReturn, R9))>;
 
+def CSR_iOS_TLSCall : CalleeSavedRegs<(add LR, SP,
+                                           (sequence "R%u", 12, 1),
+                                           (sequence "D%u", 31, 0))>;
+
 // The "interrupt" attribute is used to generate code that is acceptable in
 // exception-handlers of various kinds. It makes us use a different return
 // instruction (handled elsewhere) and affects which registers we must return to

Modified: llvm/trunk/lib/Target/ARM/ARMFastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMFastISel.cpp?rev=257039&r1=257038&r2=257039&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMFastISel.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMFastISel.cpp Thu Jan  7 03:03:03 2016
@@ -578,7 +578,7 @@ unsigned ARMFastISel::ARMMaterializeInt(
 
 unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, MVT VT) {
   // For now 32-bit only.
-  if (VT != MVT::i32) return 0;
+  if (VT != MVT::i32 || GV->isThreadLocal()) return 0;
 
   Reloc::Model RelocM = TM.getRelocationModel();
   bool IsIndirect = Subtarget->GVIsIndirectSymbol(GV, RelocM);

Modified: llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp?rev=257039&r1=257038&r2=257039&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp Thu Jan  7 03:03:03 2016
@@ -622,7 +622,8 @@ bool ARMDAGToDAGISel::SelectAddrModeImm1
     }
 
     if (N.getOpcode() == ARMISD::Wrapper &&
-        N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
+        N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
+        N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
       Base = N.getOperand(0);
     } else
       Base = N;
@@ -801,7 +802,8 @@ AddrMode2Type ARMDAGToDAGISel::SelectAdd
       Base = CurDAG->getTargetFrameIndex(
           FI, TLI->getPointerTy(CurDAG->getDataLayout()));
     } else if (N.getOpcode() == ARMISD::Wrapper &&
-               N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
+               N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
+               N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
       Base = N.getOperand(0);
     }
     Offset = CurDAG->getRegister(0, MVT::i32);
@@ -1067,7 +1069,8 @@ bool ARMDAGToDAGISel::SelectAddrMode5(SD
       Base = CurDAG->getTargetFrameIndex(
           FI, TLI->getPointerTy(CurDAG->getDataLayout()));
     } else if (N.getOpcode() == ARMISD::Wrapper &&
-               N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
+               N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
+               N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
       Base = N.getOperand(0);
     }
     Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
@@ -1186,7 +1189,8 @@ ARMDAGToDAGISel::SelectThumbAddrModeImm5
     if (N.getOpcode() == ISD::ADD) {
       return false; // We want to select register offset instead
     } else if (N.getOpcode() == ARMISD::Wrapper &&
-               N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
+        N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
+        N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
       Base = N.getOperand(0);
     } else {
       Base = N;
@@ -1292,7 +1296,8 @@ bool ARMDAGToDAGISel::SelectT2AddrModeIm
     }
 
     if (N.getOpcode() == ARMISD::Wrapper &&
-        N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) {
+        N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress &&
+        N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) {
       Base = N.getOperand(0);
       if (Base.getOpcode() == ISD::TargetConstantPool)
         return false;  // We want to select t2LDRpci instead.

Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=257039&r1=257038&r2=257039&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Thu Jan  7 03:03:03 2016
@@ -2530,6 +2530,72 @@ SDValue ARMTargetLowering::LowerBlockAdd
   return DAG.getNode(ARMISD::PIC_ADD, DL, PtrVT, Result, PICLabel);
 }
 
+/// \brief Convert a TLS address reference into the correct sequence of loads
+/// and calls to compute the variable's address for Darwin, and return an
+/// SDValue containing the final node.
+
+/// Darwin only has one TLS scheme which must be capable of dealing with the
+/// fully general situation, in the worst case. This means:
+///     + "extern __thread" declaration.
+///     + Defined in a possibly unknown dynamic library.
+///
+/// The general system is that each __thread variable has a [3 x i32] descriptor
+/// which contains information used by the runtime to calculate the address. The
+/// only part of this the compiler needs to know about is the first word, which
+/// contains a function pointer that must be called with the address of the
+/// entire descriptor in "r0".
+///
+/// Since this descriptor may be in a different unit, in general access must
+/// proceed along the usual ARM rules. A common sequence to produce is:
+///
+///     movw rT1, :lower16:_var$non_lazy_ptr
+///     movt rT1, :upper16:_var$non_lazy_ptr
+///     ldr r0, [rT1]
+///     ldr rT2, [r0]
+///     blx rT2
+///     [...address now in r0...]
+SDValue
+ARMTargetLowering::LowerGlobalTLSAddressDarwin(SDValue Op,
+                                               SelectionDAG &DAG) const {
+  assert(Subtarget->isTargetDarwin() && "TLS only supported on Darwin");
+  SDLoc DL(Op);
+
+  // First step is to get the address of the actua global symbol. This is where
+  // the TLS descriptor lives.
+  SDValue DescAddr = LowerGlobalAddressDarwin(Op, DAG);
+
+  // The first entry in the descriptor is a function pointer that we must call
+  // to obtain the address of the variable.
+  SDValue Chain = DAG.getEntryNode();
+  SDValue FuncTLVGet =
+      DAG.getLoad(MVT::i32, DL, Chain, DescAddr,
+                  MachinePointerInfo::getGOT(DAG.getMachineFunction()),
+                  false, true, true, 4);
+  Chain = FuncTLVGet.getValue(1);
+
+  MachineFunction &F = DAG.getMachineFunction();
+  MachineFrameInfo *MFI = F.getFrameInfo();
+  MFI->setAdjustsStack(true);
+
+  // TLS calls preserve all registers except those that absolutely must be
+  // trashed: R0 (it takes an argument), LR (it's a call) and CPSR (let's not be
+  // silly).
+  auto TRI =
+      getTargetMachine().getSubtargetImpl(*F.getFunction())->getRegisterInfo();
+  auto ARI = static_cast<const ARMRegisterInfo *>(TRI);
+  const uint32_t *Mask = ARI->getTLSCallPreservedMask(DAG.getMachineFunction());
+
+  // Finally, we can make the call. This is just a degenerate version of a
+  // normal AArch64 call node: r0 takes the address of the descriptor, and
+  // returns the address of the variable in this thread.
+  Chain = DAG.getCopyToReg(Chain, DL, ARM::R0, DescAddr, SDValue());
+  Chain =
+      DAG.getNode(ARMISD::CALL, DL, DAG.getVTList(MVT::Other, MVT::Glue),
+                  Chain, FuncTLVGet, DAG.getRegister(ARM::R0, MVT::i32),
+                  DAG.getRegisterMask(Mask), Chain.getValue(1));
+  return DAG.getCopyFromReg(Chain, DL, ARM::R0, MVT::i32, Chain.getValue(1));
+}
+
 // Lower ISD::GlobalTLSAddress using the "general dynamic" model
 SDValue
 ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,
@@ -2631,9 +2697,11 @@ ARMTargetLowering::LowerToTLSExecModels(
 
 SDValue
 ARMTargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
+  if (Subtarget->isTargetDarwin())
+    return LowerGlobalTLSAddressDarwin(Op, DAG);
+
   // TODO: implement the "local dynamic" model
-  assert(Subtarget->isTargetELF() &&
-         "TLS not implemented for non-ELF targets");
+  assert(Subtarget->isTargetELF() && "Only ELF implemented here");
   GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
   if (DAG.getTarget().Options.EmulatedTLS)
     return LowerToTLSEmulatedModel(GA, DAG);

Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.h?rev=257039&r1=257038&r2=257039&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.h Thu Jan  7 03:03:03 2016
@@ -526,6 +526,8 @@ namespace llvm {
     SDValue LowerToTLSExecModels(GlobalAddressSDNode *GA,
                                  SelectionDAG &DAG,
                                  TLSModel::Model model) const;
+    SDValue LowerGlobalTLSAddressDarwin(SDValue Op, SelectionDAG &DAG) const;
+    SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerXALUO(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const;

Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=257039&r1=257038&r2=257039&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Thu Jan  7 03:03:03 2016
@@ -5398,6 +5398,27 @@ def MOV_ga_pcrel_ldr : PseudoInst<(outs
                     Requires<[IsARM, UseMovt]>;
 } // isReMaterializable
 
+// The many different faces of TLS access.
+def : ARMPat<(ARMWrapper tglobaltlsaddr :$dst),
+             (MOVi32imm tglobaltlsaddr :$dst)>,
+      Requires<[IsARM, UseMovt]>;
+
+def : Pat<(ARMWrapper tglobaltlsaddr:$src),
+          (LDRLIT_ga_abs tglobaltlsaddr:$src)>,
+      Requires<[IsARM, DontUseMovt]>;
+
+def : Pat<(ARMWrapperPIC tglobaltlsaddr:$addr),
+          (MOV_ga_pcrel tglobaltlsaddr:$addr)>, Requires<[IsARM, UseMovt]>;
+
+def : Pat<(ARMWrapperPIC tglobaltlsaddr:$addr),
+          (LDRLIT_ga_pcrel tglobaltlsaddr:$addr)>,
+      Requires<[IsARM, DontUseMovt]>;
+let AddedComplexity = 10 in
+def : Pat<(load (ARMWrapperPIC tglobaltlsaddr:$addr)),
+          (MOV_ga_pcrel_ldr tglobaltlsaddr:$addr)>,
+      Requires<[IsARM, UseMovt]>;
+
+
 // ConstantPool, GlobalAddress, and JumpTable
 def : ARMPat<(ARMWrapper  tconstpool  :$dst), (LEApcrel tconstpool  :$dst)>;
 def : ARMPat<(ARMWrapper  tglobaladdr :$dst), (MOVi32imm tglobaladdr :$dst)>,

Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb.td?rev=257039&r1=257038&r2=257039&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Thu Jan  7 03:03:03 2016
@@ -1366,6 +1366,14 @@ def tLDRLIT_ga_abs : PseudoInst<(outs tG
                                       (ARMWrapper tglobaladdr:$src))]>,
                      Requires<[IsThumb, DontUseMovt]>;
 
+// TLS globals
+def : Pat<(ARMWrapperPIC tglobaltlsaddr:$addr),
+          (tLDRLIT_ga_pcrel tglobaltlsaddr:$addr)>,
+      Requires<[IsThumb, DontUseMovt]>;
+def : Pat<(ARMWrapper tglobaltlsaddr:$addr),
+          (tLDRLIT_ga_abs tglobaltlsaddr:$addr)>,
+      Requires<[IsThumb, DontUseMovt]>;
+
 
 // JumpTable
 def : T1Pat<(ARMWrapperJT tjumptable:$dst),

Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=257039&r1=257038&r2=257039&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Thu Jan  7 03:03:03 2016
@@ -3875,6 +3875,13 @@ def t2MOV_ga_pcrel : PseudoInst<(outs rG
 
 }
 
+def : T2Pat<(ARMWrapperPIC tglobaltlsaddr :$dst),
+            (t2MOV_ga_pcrel tglobaltlsaddr:$dst)>,
+      Requires<[IsThumb2, UseMovt]>;
+def : T2Pat<(ARMWrapper tglobaltlsaddr:$dst),
+            (t2MOVi32imm tglobaltlsaddr:$dst)>,
+      Requires<[IsThumb2, UseMovt]>;
+
 // ConstantPool, GlobalAddress, and JumpTable
 def : T2Pat<(ARMWrapper  tconstpool  :$dst), (t2LEApcrel tconstpool  :$dst)>;
 def : T2Pat<(ARMWrapper  tglobaladdr :$dst), (t2MOVi32imm tglobaladdr :$dst)>,

Added: llvm/trunk/test/CodeGen/ARM/darwin-tls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/darwin-tls.ll?rev=257039&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/darwin-tls.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/darwin-tls.ll Thu Jan  7 03:03:03 2016
@@ -0,0 +1,165 @@
+; RUN: llc -mtriple=thumbv7s-apple-ios7.0 -o - -fast-isel %s | FileCheck %s --check-prefix=T2-MOVT-PIC
+; RUN: llc -mtriple=thumbv7s-apple-ios7.0 -o - %s -mattr=+no-movt | FileCheck %s --check-prefix=T2-LIT-PIC
+; RUN: llc -mtriple=thumbv7s-apple-ios7.0 -o - %s -relocation-model=static | FileCheck %s --check-prefix=T2-MOVT-STATIC
+; RUN: llc -mtriple=thumbv7s-apple-ios7.0 -o - %s -mattr=+no-movt -relocation-model=static | FileCheck %s --check-prefix=T2-LIT-STATIC
+; RUN: llc -mtriple=armv7s-apple-ios7.0 -o - %s | FileCheck %s --check-prefix=ARM-MOVT-PIC
+; RUN: llc -mtriple=armv7s-apple-ios7.0 -o - %s -mattr=+no-movt | FileCheck %s --check-prefix=ARM-LIT-PIC
+; RUN: llc -mtriple=armv7s-apple-ios7.0 -o - %s -relocation-model=static | FileCheck %s --check-prefix=ARM-MOVT-STATIC
+; RUN: llc -mtriple=armv7s-apple-ios7.0 -o - %s -mattr=+no-movt -relocation-model=static | FileCheck %s --check-prefix=ARM-LIT-STATIC
+
+
+ at local_tls_var = thread_local global i32 0
+ at external_tls_var = external thread_local global i32
+
+define i32 @test_local_tls() {
+; T2-MOVT-PIC-LABEL: test_local_tls:
+; T2-MOVT-PIC: movw r0, :lower16:(_local_tls_var-([[PCREL_LOC:LPC[0-9]+_[0-9]+]]+4))
+; T2-MOVT-PIC: movt r0, :upper16:(_local_tls_var-([[PCREL_LOC]]+4))
+; T2-MOVT-PIC: [[PCREL_LOC]]:
+; T2-MOVT-PIC-NEXT: add r0, pc
+; T2-MOVT-PIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; T2-MOVT-PIC: blx [[TLV_GET_ADDR]]
+; T2-MOVT-PIC: ldr r0, [r0]
+
+; T2-LIT-PIC-LABEL: test_local_tls:
+; T2-LIT-PIC: ldr r0, [[LOCAL_VAR_ADDR:LCPI[0-9]+_[0-9]+]]
+; T2-LIT-PIC: [[PCREL_LOC:LPC[0-9]+_[0-9]+]]:
+; T2-LIT-PIC-NEXT: add r0, pc
+; T2-LIT-PIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; T2-LIT-PIC: blx [[TLV_GET_ADDR]]
+; T2-LIT-PIC: ldr r0, [r0]
+; T2-LIT-PIC: [[LOCAL_VAR_ADDR]]:
+; T2-LIT-PIC-NEXT: .long _local_tls_var-([[PCREL_LOC]]+4)
+
+; T2-MOVT-STATIC-LABEL: test_local_tls:
+; T2-MOVT-STATIC: movw r0, :lower16:_local_tls_var
+; T2-MOVT-STATIC: movt r0, :upper16:_local_tls_var
+; T2-MOVT-STATIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; T2-MOVT-STATIC: blx [[TLV_GET_ADDR]]
+; T2-MOVT-STATIC: ldr r0, [r0]
+
+; T2-LIT-STATIC-LABEL: test_local_tls:
+; T2-LIT-STATIC: ldr r0, [[LOCAL_VAR_ADDR:LCPI[0-9]+_[0-9]+]]
+; T2-LIT-STATIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; T2-LIT-STATIC: blx [[TLV_GET_ADDR]]
+; T2-LIT-STATIC: ldr r0, [r0]
+; T2-LIT-STATIC: [[LOCAL_VAR_ADDR]]:
+; T2-LIT-STATIC-NEXT: .long _local_tls_var
+
+; ARM-MOVT-PIC-LABEL: test_local_tls:
+; ARM-MOVT-PIC: movw [[VARPC1:r[0-9]+]], :lower16:(_local_tls_var-([[PCREL_LOC1:LPC[0-9]+_[0-9]+]]+8))
+; ARM-MOVT-PIC: movt [[VARPC1]], :upper16:(_local_tls_var-([[PCREL_LOC1]]+8))
+; ARM-MOVT-PIC: [[PCREL_LOC1]]:
+; ARM-MOVT-PIC: add r0, pc, [[VARPC1]]
+; ARM-MOVT-PIC: movw [[VARPC2:r[0-9]+]], :lower16:(_local_tls_var-([[PCREL_LOC2:LPC[0-9]+_[0-9]+]]+8))
+; ARM-MOVT-PIC: movt [[VARPC2]], :upper16:(_local_tls_var-([[PCREL_LOC2]]+8))
+; ARM-MOVT-PIC: [[PCREL_LOC2]]:
+; ARM-MOVT-PIC-NEXT: ldr [[TLV_GET_ADDR:r[0-9]+]], [pc, [[VARPC2]]]
+; ARM-MOVT-PIC: blx [[TLV_GET_ADDR]]
+; ARM-MOVT-PIC: ldr r0, [r0]
+
+; ARM-LIT-PIC-LABEL: test_local_tls:
+; ARM-LIT-PIC: ldr r0, [[LOCAL_VAR_ADDR:LCPI[0-9]+_[0-9]+]]
+; ARM-LIT-PIC: [[PCREL_LOC:LPC[0-9]+_[0-9]+]]:
+; ARM-LIT-PIC-NEXT: add r0, pc
+; ARM-LIT-PIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; ARM-LIT-PIC: blx [[TLV_GET_ADDR]]
+; ARM-LIT-PIC: ldr r0, [r0]
+; ARM-LIT-PIC: [[LOCAL_VAR_ADDR]]:
+; ARM-LIT-PIC-NEXT: .long _local_tls_var-([[PCREL_LOC]]+8)
+
+; ARM-MOVT-STATIC-LABEL: test_local_tls:
+; ARM-MOVT-STATIC: movw r0, :lower16:_local_tls_var
+; ARM-MOVT-STATIC: movt r0, :upper16:_local_tls_var
+; ARM-MOVT-STATIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; ARM-MOVT-STATIC: blx [[TLV_GET_ADDR]]
+; ARM-MOVT-STATIC: ldr r0, [r0]
+
+; ARM-LIT-STATIC-LABEL: test_local_tls:
+; ARM-LIT-STATIC: ldr r0, [[LOCAL_VAR_ADDR:LCPI[0-9]+_[0-9]+]]
+; ARM-LIT-STATIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; ARM-LIT-STATIC: blx [[TLV_GET_ADDR]]
+; ARM-LIT-STATIC: ldr r0, [r0]
+; ARM-LIT-STATIC: [[LOCAL_VAR_ADDR]]:
+; ARM-LIT-STATIC-NEXT: .long _local_tls_var
+
+
+  %val = load i32, i32* @local_tls_var, align 4
+  ret i32 %val
+}
+
+define i32 @test_external_tls() {
+; T2-MOVT-PIC-LABEL: test_external_tls:
+; T2-MOVT-PIC: movw r[[EXTGOT:[0-9]+]], :lower16:(L_external_tls_var$non_lazy_ptr-([[PCREL_LOC:LPC[0-9]+_[0-9]+]]+4))
+; T2-MOVT-PIC: movt r[[EXTGOT]], :upper16:(L_external_tls_var$non_lazy_ptr-([[PCREL_LOC]]+4))
+; T2-MOVT-PIC: [[PCREL_LOC]]:
+; T2-MOVT-PIC-NEXT: add r[[EXTGOT]], pc
+; T2-MOVT-PIC: ldr r0, [r[[EXTGOT]]]
+; T2-MOVT-PIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; T2-MOVT-PIC: blx [[TLV_GET_ADDR]]
+; T2-MOVT-PIC: ldr r0, [r0]
+
+; T2-LIT-PIC-LABEL: test_external_tls:
+; T2-LIT-PIC: ldr r[[EXTGOT:[0-9]+]], [[EXTERNAL_VAR_ADDR:LCPI[0-9]+_[0-9]+]]
+; T2-LIT-PIC: [[PCREL_LOC:LPC[0-9]+_[0-9]+]]:
+; T2-LIT-PIC-NEXT: add r[[EXTGOT]], pc
+; T2-LIT-PIC: ldr r0, [r[[EXTGOT]]]
+; T2-LIT-PIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; T2-LIT-PIC: blx [[TLV_GET_ADDR]]
+; T2-LIT-PIC: ldr r0, [r0]
+; T2-LIT-PIC: [[EXTERNAL_VAR_ADDR]]:
+; T2-LIT-PIC-NEXT: .long L_external_tls_var$non_lazy_ptr-([[PCREL_LOC]]+4)
+
+; T2-MOVT-STATIC-LABEL: test_external_tls:
+; T2-MOVT-STATIC: movw r0, :lower16:_external_tls_var
+; T2-MOVT-STATIC: movt r0, :upper16:_external_tls_var
+; T2-MOVT-STATIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; T2-MOVT-STATIC: blx [[TLV_GET_ADDR]]
+; T2-MOVT-STATIC: ldr r0, [r0]
+
+; T2-LIT-STATIC-LABEL: test_external_tls:
+; T2-LIT-STATIC: ldr r0, [[EXTERNAL_VAR_ADDR:LCPI[0-9]+_[0-9]+]]
+; T2-LIT-STATIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; T2-LIT-STATIC: blx [[TLV_GET_ADDR]]
+; T2-LIT-STATIC: ldr r0, [r0]
+; T2-LIT-STATIC: [[EXTERNAL_VAR_ADDR]]:
+; T2-LIT-STATIC-NEXT: .long _external_tls_var
+
+; ARM-MOVT-PIC-LABEL: test_external_tls:
+; ARM-MOVT-PIC: movw r[[EXTGOT:[0-9]+]], :lower16:(L_external_tls_var$non_lazy_ptr-([[PCREL_LOC:LPC[0-9]+_[0-9]+]]+8))
+; ARM-MOVT-PIC: movt r[[EXTGOT]], :upper16:(L_external_tls_var$non_lazy_ptr-([[PCREL_LOC]]+8))
+; ARM-MOVT-PIC: [[PCREL_LOC]]:
+; ARM-MOVT-PIC-NEXT: ldr r0, [pc, r[[EXTGOT]]]
+; ARM-MOVT-PIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; ARM-MOVT-PIC: blx [[TLV_GET_ADDR]]
+; ARM-MOVT-PIC: ldr r0, [r0]
+
+; ARM-LIT-PIC-LABEL: test_external_tls:
+; ARM-LIT-PIC: ldr r[[EXTGOT:[0-9]+]], [[EXTERNAL_VAR_ADDR:LCPI[0-9]+_[0-9]+]]
+; ARM-LIT-PIC: [[PCREL_LOC:LPC[0-9]+_[0-9]+]]:
+; ARM-LIT-PIC-NEXT: add r[[EXTGOT]], pc
+; ARM-LIT-PIC: ldr r0, [r[[EXTGOT]]]
+; ARM-LIT-PIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; ARM-LIT-PIC: blx [[TLV_GET_ADDR]]
+; ARM-LIT-PIC: ldr r0, [r0]
+; ARM-LIT-PIC: [[EXTERNAL_VAR_ADDR]]:
+; ARM-LIT-PIC-NEXT: .long L_external_tls_var$non_lazy_ptr-([[PCREL_LOC]]+8)
+
+; ARM-MOVT-STATIC-LABEL: test_external_tls:
+; ARM-MOVT-STATIC: movw r0, :lower16:_external_tls_var
+; ARM-MOVT-STATIC: movt r0, :upper16:_external_tls_var
+; ARM-MOVT-STATIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; ARM-MOVT-STATIC: blx [[TLV_GET_ADDR]]
+; ARM-MOVT-STATIC: ldr r0, [r0]
+
+; ARM-LIT-STATIC-LABEL: test_external_tls:
+; ARM-LIT-STATIC: ldr r0, [[EXTERNAL_VAR_ADDR:LCPI[0-9]+_[0-9]+]]
+; ARM-LIT-STATIC: ldr [[TLV_GET_ADDR:r[0-9]+]], [r0]
+; ARM-LIT-STATIC: blx [[TLV_GET_ADDR]]
+; ARM-LIT-STATIC: ldr r0, [r0]
+; ARM-LIT-STATIC: [[EXTERNAL_VAR_ADDR]]:
+; ARM-LIT-STATIC-NEXT: .long _external_tls_var
+
+  %val = load i32, i32* @external_tls_var, align 4
+  ret i32 %val
+}




More information about the llvm-commits mailing list