[llvm] r363771 - [RISCV] Add lowering of global TLS addresses

Lewis Revill via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 19 01:40:59 PDT 2019


Author: lewis-revill
Date: Wed Jun 19 01:40:59 2019
New Revision: 363771

URL: http://llvm.org/viewvc/llvm-project?rev=363771&view=rev
Log:
[RISCV] Add lowering of global TLS addresses

This patch adds lowering for global TLS addresses for the TLS models of
InitialExec, GlobalDynamic, LocalExec and LocalDynamic.

LocalExec support required using a 4-operand add instruction, which uses
the fourth operand to express a relocation on the symbol. The necessary
fixup is emitted when the instruction is emitted.

Differential Revision: https://reviews.llvm.org/D55305


Added:
    llvm/trunk/test/CodeGen/RISCV/tls-models.ll
Modified:
    llvm/trunk/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
    llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp
    llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h
    llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp
    llvm/trunk/lib/Target/RISCV/RISCVMCInstLower.cpp
    llvm/trunk/lib/Target/RISCV/Utils/RISCVBaseInfo.h

Modified: llvm/trunk/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp?rev=363771&r1=363770&r2=363771&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp Wed Jun 19 01:40:59 2019
@@ -64,6 +64,12 @@ private:
   bool expandLoadAddress(MachineBasicBlock &MBB,
                          MachineBasicBlock::iterator MBBI,
                          MachineBasicBlock::iterator &NextMBBI);
+  bool expandLoadTLSIEAddress(MachineBasicBlock &MBB,
+                              MachineBasicBlock::iterator MBBI,
+                              MachineBasicBlock::iterator &NextMBBI);
+  bool expandLoadTLSGDAddress(MachineBasicBlock &MBB,
+                              MachineBasicBlock::iterator MBBI,
+                              MachineBasicBlock::iterator &NextMBBI);
 };
 
 char RISCVExpandPseudo::ID = 0;
@@ -131,6 +137,10 @@ bool RISCVExpandPseudo::expandMI(Machine
     return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
   case RISCV::PseudoLA:
     return expandLoadAddress(MBB, MBBI, NextMBBI);
+  case RISCV::PseudoLA_TLS_IE:
+    return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);
+  case RISCV::PseudoLA_TLS_GD:
+    return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI);
   }
 
   return false;
@@ -677,6 +687,24 @@ bool RISCVExpandPseudo::expandLoadAddres
   return expandAuipcInstPair(MBB, MBBI, NextMBBI, FlagsHi, SecondOpcode);
 }
 
+bool RISCVExpandPseudo::expandLoadTLSIEAddress(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+    MachineBasicBlock::iterator &NextMBBI) {
+  MachineFunction *MF = MBB.getParent();
+
+  const auto &STI = MF->getSubtarget<RISCVSubtarget>();
+  unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
+  return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI,
+                             SecondOpcode);
+}
+
+bool RISCVExpandPseudo::expandLoadTLSGDAddress(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+    MachineBasicBlock::iterator &NextMBBI) {
+  return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI,
+                             RISCV::ADDI);
+}
+
 } // end of anonymous namespace
 
 INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",

Modified: llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp?rev=363771&r1=363770&r2=363771&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp Wed Jun 19 01:40:59 2019
@@ -178,6 +178,8 @@ RISCVTargetLowering::RISCVTargetLowering
   setOperationAction(ISD::BlockAddress, XLenVT, Custom);
   setOperationAction(ISD::ConstantPool, XLenVT, Custom);
 
+  setOperationAction(ISD::GlobalTLSAddress, XLenVT, Custom);
+
   if (Subtarget.hasStdExtA()) {
     setMaxAtomicSizeInBitsSupported(Subtarget.getXLen());
     setMinCmpXchgSizeInBits(32);
@@ -358,6 +360,8 @@ SDValue RISCVTargetLowering::LowerOperat
     return lowerBlockAddress(Op, DAG);
   case ISD::ConstantPool:
     return lowerConstantPool(Op, DAG);
+  case ISD::GlobalTLSAddress:
+    return lowerGlobalTLSAddress(Op, DAG);
   case ISD::SELECT:
     return lowerSELECT(Op, DAG);
   case ISD::VASTART:
@@ -480,6 +484,116 @@ SDValue RISCVTargetLowering::lowerConsta
   return getAddr(N, DAG);
 }
 
+SDValue RISCVTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N,
+                                              SelectionDAG &DAG,
+                                              bool UseGOT) const {
+  SDLoc DL(N);
+  EVT Ty = getPointerTy(DAG.getDataLayout());
+  const GlobalValue *GV = N->getGlobal();
+  MVT XLenVT = Subtarget.getXLenVT();
+
+  if (UseGOT) {
+    // Use PC-relative addressing to access the GOT for this TLS symbol, then
+    // load the address from the GOT and add the thread pointer. This generates
+    // the pattern (PseudoLA_TLS_IE sym), which expands to
+    // (ld (auipc %tls_ie_pcrel_hi(sym)) %pcrel_lo(auipc)).
+    SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, Ty, 0, 0);
+    SDValue Load =
+        SDValue(DAG.getMachineNode(RISCV::PseudoLA_TLS_IE, DL, Ty, Addr), 0);
+
+    // Add the thread pointer.
+    SDValue TPReg = DAG.getRegister(RISCV::X4, XLenVT);
+    return DAG.getNode(ISD::ADD, DL, Ty, Load, TPReg);
+  }
+
+  // Generate a sequence for accessing the address relative to the thread
+  // pointer, with the appropriate adjustment for the thread pointer offset.
+  // This generates the pattern
+  // (add (add_tprel (lui %tprel_hi(sym)) tp %tprel_add(sym)) %tprel_lo(sym))
+  SDValue AddrHi =
+      DAG.getTargetGlobalAddress(GV, DL, Ty, 0, RISCVII::MO_TPREL_HI);
+  SDValue AddrAdd =
+      DAG.getTargetGlobalAddress(GV, DL, Ty, 0, RISCVII::MO_TPREL_ADD);
+  SDValue AddrLo =
+      DAG.getTargetGlobalAddress(GV, DL, Ty, 0, RISCVII::MO_TPREL_LO);
+
+  SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, AddrHi), 0);
+  SDValue TPReg = DAG.getRegister(RISCV::X4, XLenVT);
+  SDValue MNAdd = SDValue(
+      DAG.getMachineNode(RISCV::PseudoAddTPRel, DL, Ty, MNHi, TPReg, AddrAdd),
+      0);
+  return SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNAdd, AddrLo), 0);
+}
+
+SDValue RISCVTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N,
+                                               SelectionDAG &DAG) const {
+  SDLoc DL(N);
+  EVT Ty = getPointerTy(DAG.getDataLayout());
+  IntegerType *CallTy = Type::getIntNTy(*DAG.getContext(), Ty.getSizeInBits());
+  const GlobalValue *GV = N->getGlobal();
+
+  // Use a PC-relative addressing mode to access the global dynamic GOT address.
+  // This generates the pattern (PseudoLA_TLS_GD sym), which expands to
+  // (addi (auipc %tls_gd_pcrel_hi(sym)) %pcrel_lo(auipc)).
+  SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, Ty, 0, 0);
+  SDValue Load =
+      SDValue(DAG.getMachineNode(RISCV::PseudoLA_TLS_GD, DL, Ty, Addr), 0);
+
+  // Prepare argument list to generate call.
+  ArgListTy Args;
+  ArgListEntry Entry;
+  Entry.Node = Load;
+  Entry.Ty = CallTy;
+  Args.push_back(Entry);
+
+  // Setup call to __tls_get_addr.
+  TargetLowering::CallLoweringInfo CLI(DAG);
+  CLI.setDebugLoc(DL)
+      .setChain(DAG.getEntryNode())
+      .setLibCallee(CallingConv::C, CallTy,
+                    DAG.getExternalSymbol("__tls_get_addr", Ty),
+                    std::move(Args));
+
+  return LowerCallTo(CLI).first;
+}
+
+SDValue RISCVTargetLowering::lowerGlobalTLSAddress(SDValue Op,
+                                                   SelectionDAG &DAG) const {
+  SDLoc DL(Op);
+  EVT Ty = Op.getValueType();
+  GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
+  int64_t Offset = N->getOffset();
+  MVT XLenVT = Subtarget.getXLenVT();
+
+  // Non-PIC TLS lowering should always use the LocalExec model.
+  TLSModel::Model Model = isPositionIndependent()
+                              ? getTargetMachine().getTLSModel(N->getGlobal())
+                              : TLSModel::LocalExec;
+
+  SDValue Addr;
+  switch (Model) {
+  case TLSModel::LocalExec:
+    Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/false);
+    break;
+  case TLSModel::InitialExec:
+    Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/true);
+    break;
+  case TLSModel::LocalDynamic:
+  case TLSModel::GeneralDynamic:
+    Addr = getDynamicTLSAddr(N, DAG);
+    break;
+  }
+
+  // In order to maximise the opportunity for common subexpression elimination,
+  // emit a separate ADD node for the global address offset instead of folding
+  // it in the global address node. Later peephole optimisations may choose to
+  // fold it back in when profitable.
+  if (Offset != 0)
+    return DAG.getNode(ISD::ADD, DL, Ty, Addr,
+                       DAG.getConstant(Offset, DL, XLenVT));
+  return Addr;
+}
+
 SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
   SDValue CondV = Op.getOperand(0);
   SDValue TrueV = Op.getOperand(1);

Modified: llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h?rev=363771&r1=363770&r2=363771&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h Wed Jun 19 01:40:59 2019
@@ -159,10 +159,15 @@ private:
   template <class NodeTy>
   SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const;
 
+  SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
+                           bool UseGOT) const;
+  SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG) const;
+
   bool shouldConsiderGEPOffsetSplit() const override { return true; }
   SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
+  SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;

Modified: llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp?rev=363771&r1=363770&r2=363771&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp Wed Jun 19 01:40:59 2019
@@ -440,6 +440,8 @@ unsigned RISCVInstrInfo::getInstSizeInBy
   case RISCV::PseudoTAIL:
   case RISCV::PseudoLLA:
   case RISCV::PseudoLA:
+  case RISCV::PseudoLA_TLS_IE:
+  case RISCV::PseudoLA_TLS_GD:
     return 8;
   case TargetOpcode::INLINEASM:
   case TargetOpcode::INLINEASM_BR: {

Modified: llvm/trunk/lib/Target/RISCV/RISCVMCInstLower.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVMCInstLower.cpp?rev=363771&r1=363770&r2=363771&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVMCInstLower.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVMCInstLower.cpp Wed Jun 19 01:40:59 2019
@@ -57,6 +57,21 @@ static MCOperand lowerSymbolOperand(cons
   case RISCVII::MO_GOT_HI:
     Kind = RISCVMCExpr::VK_RISCV_GOT_HI;
     break;
+  case RISCVII::MO_TPREL_LO:
+    Kind = RISCVMCExpr::VK_RISCV_TPREL_LO;
+    break;
+  case RISCVII::MO_TPREL_HI:
+    Kind = RISCVMCExpr::VK_RISCV_TPREL_HI;
+    break;
+  case RISCVII::MO_TPREL_ADD:
+    Kind = RISCVMCExpr::VK_RISCV_TPREL_ADD;
+    break;
+  case RISCVII::MO_TLS_GOT_HI:
+    Kind = RISCVMCExpr::VK_RISCV_TLS_GOT_HI;
+    break;
+  case RISCVII::MO_TLS_GD_HI:
+    Kind = RISCVMCExpr::VK_RISCV_TLS_GD_HI;
+    break;
   }
 
   const MCExpr *ME =

Modified: llvm/trunk/lib/Target/RISCV/Utils/RISCVBaseInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/Utils/RISCVBaseInfo.h?rev=363771&r1=363770&r2=363771&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/Utils/RISCVBaseInfo.h (original)
+++ llvm/trunk/lib/Target/RISCV/Utils/RISCVBaseInfo.h Wed Jun 19 01:40:59 2019
@@ -55,6 +55,11 @@ enum {
   MO_PCREL_LO,
   MO_PCREL_HI,
   MO_GOT_HI,
+  MO_TPREL_LO,
+  MO_TPREL_HI,
+  MO_TPREL_ADD,
+  MO_TLS_GOT_HI,
+  MO_TLS_GD_HI,
 };
 } // namespace RISCVII
 

Added: llvm/trunk/test/CodeGen/RISCV/tls-models.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/tls-models.ll?rev=363771&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/tls-models.ll (added)
+++ llvm/trunk/test/CodeGen/RISCV/tls-models.ll Wed Jun 19 01:40:59 2019
@@ -0,0 +1,155 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -relocation-model=pic < %s \
+; RUN:     | FileCheck -check-prefix=RV32-PIC %s
+; RUN: llc -mtriple=riscv64 -relocation-model=pic < %s \
+; RUN:     | FileCheck -check-prefix=RV64-PIC %s
+; RUN: llc -mtriple=riscv32 < %s | FileCheck -check-prefix=NOPIC %s
+; RUN: llc -mtriple=riscv64 < %s | FileCheck -check-prefix=NOPIC %s
+
+; Check that TLS symbols are lowered correctly based on the specified
+; model.
+
+ at unspecified = thread_local global i32 42
+ at ld = thread_local(localdynamic) global i32 42
+ at ie = thread_local(initialexec) global i32 42
+ at le = thread_local(localexec) global i32 42
+
+
+; No model specified
+
+define i32* @f1() nounwind {
+; RV32-PIC-LABEL: f1:
+; RV32-PIC:       # %bb.0: # %entry
+; RV32-PIC-NEXT:    addi sp, sp, -16
+; RV32-PIC-NEXT:    sw ra, 12(sp)
+; RV32-PIC-NEXT:  .LBB0_1: # %entry
+; RV32-PIC-NEXT:    # Label of block must be emitted
+; RV32-PIC-NEXT:    auipc a0, %tls_gd_pcrel_hi(unspecified)
+; RV32-PIC-NEXT:    addi a0, a0, %pcrel_lo(.LBB0_1)
+; RV32-PIC-NEXT:    call __tls_get_addr at plt
+; RV32-PIC-NEXT:    lw ra, 12(sp)
+; RV32-PIC-NEXT:    addi sp, sp, 16
+; RV32-PIC-NEXT:    ret
+;
+; RV64-PIC-LABEL: f1:
+; RV64-PIC:       # %bb.0: # %entry
+; RV64-PIC-NEXT:    addi sp, sp, -16
+; RV64-PIC-NEXT:    sd ra, 8(sp)
+; RV64-PIC-NEXT:  .LBB0_1: # %entry
+; RV64-PIC-NEXT:    # Label of block must be emitted
+; RV64-PIC-NEXT:    auipc a0, %tls_gd_pcrel_hi(unspecified)
+; RV64-PIC-NEXT:    addi a0, a0, %pcrel_lo(.LBB0_1)
+; RV64-PIC-NEXT:    call __tls_get_addr at plt
+; RV64-PIC-NEXT:    ld ra, 8(sp)
+; RV64-PIC-NEXT:    addi sp, sp, 16
+; RV64-PIC-NEXT:    ret
+;
+; NOPIC-LABEL: f1:
+; NOPIC:       # %bb.0: # %entry
+; NOPIC-NEXT:    lui a0, %tprel_hi(unspecified)
+; NOPIC-NEXT:    add a0, a0, tp, %tprel_add(unspecified)
+; NOPIC-NEXT:    addi a0, a0, %tprel_lo(unspecified)
+; NOPIC-NEXT:    ret
+entry:
+  ret i32* @unspecified
+}
+
+
+; localdynamic specified
+
+define i32* @f2() nounwind {
+; RV32-PIC-LABEL: f2:
+; RV32-PIC:       # %bb.0: # %entry
+; RV32-PIC-NEXT:    addi sp, sp, -16
+; RV32-PIC-NEXT:    sw ra, 12(sp)
+; RV32-PIC-NEXT:  .LBB1_1: # %entry
+; RV32-PIC-NEXT:    # Label of block must be emitted
+; RV32-PIC-NEXT:    auipc a0, %tls_gd_pcrel_hi(ld)
+; RV32-PIC-NEXT:    addi a0, a0, %pcrel_lo(.LBB1_1)
+; RV32-PIC-NEXT:    call __tls_get_addr at plt
+; RV32-PIC-NEXT:    lw ra, 12(sp)
+; RV32-PIC-NEXT:    addi sp, sp, 16
+; RV32-PIC-NEXT:    ret
+;
+; RV64-PIC-LABEL: f2:
+; RV64-PIC:       # %bb.0: # %entry
+; RV64-PIC-NEXT:    addi sp, sp, -16
+; RV64-PIC-NEXT:    sd ra, 8(sp)
+; RV64-PIC-NEXT:  .LBB1_1: # %entry
+; RV64-PIC-NEXT:    # Label of block must be emitted
+; RV64-PIC-NEXT:    auipc a0, %tls_gd_pcrel_hi(ld)
+; RV64-PIC-NEXT:    addi a0, a0, %pcrel_lo(.LBB1_1)
+; RV64-PIC-NEXT:    call __tls_get_addr at plt
+; RV64-PIC-NEXT:    ld ra, 8(sp)
+; RV64-PIC-NEXT:    addi sp, sp, 16
+; RV64-PIC-NEXT:    ret
+;
+; NOPIC-LABEL: f2:
+; NOPIC:       # %bb.0: # %entry
+; NOPIC-NEXT:    lui a0, %tprel_hi(ld)
+; NOPIC-NEXT:    add a0, a0, tp, %tprel_add(ld)
+; NOPIC-NEXT:    addi a0, a0, %tprel_lo(ld)
+; NOPIC-NEXT:    ret
+entry:
+  ret i32* @ld
+}
+
+
+; initialexec specified
+
+define i32* @f3() nounwind {
+; RV32-PIC-LABEL: f3:
+; RV32-PIC:       # %bb.0: # %entry
+; RV32-PIC-NEXT:  .LBB2_1: # %entry
+; RV32-PIC-NEXT:    # Label of block must be emitted
+; RV32-PIC-NEXT:    auipc a0, %tls_ie_pcrel_hi(ie)
+; RV32-PIC-NEXT:    lw a0, %pcrel_lo(.LBB2_1)(a0)
+; RV32-PIC-NEXT:    add a0, a0, tp
+; RV32-PIC-NEXT:    ret
+;
+; RV64-PIC-LABEL: f3:
+; RV64-PIC:       # %bb.0: # %entry
+; RV64-PIC-NEXT:  .LBB2_1: # %entry
+; RV64-PIC-NEXT:    # Label of block must be emitted
+; RV64-PIC-NEXT:    auipc a0, %tls_ie_pcrel_hi(ie)
+; RV64-PIC-NEXT:    ld a0, %pcrel_lo(.LBB2_1)(a0)
+; RV64-PIC-NEXT:    add a0, a0, tp
+; RV64-PIC-NEXT:    ret
+;
+; NOPIC-LABEL: f3:
+; NOPIC:       # %bb.0: # %entry
+; NOPIC-NEXT:    lui a0, %tprel_hi(ie)
+; NOPIC-NEXT:    add a0, a0, tp, %tprel_add(ie)
+; NOPIC-NEXT:    addi a0, a0, %tprel_lo(ie)
+; NOPIC-NEXT:    ret
+entry:
+  ret i32* @ie
+}
+
+
+; localexec specified
+
+define i32* @f4() nounwind {
+; RV32-PIC-LABEL: f4:
+; RV32-PIC:       # %bb.0: # %entry
+; RV32-PIC-NEXT:    lui a0, %tprel_hi(le)
+; RV32-PIC-NEXT:    add a0, a0, tp, %tprel_add(le)
+; RV32-PIC-NEXT:    addi a0, a0, %tprel_lo(le)
+; RV32-PIC-NEXT:    ret
+;
+; RV64-PIC-LABEL: f4:
+; RV64-PIC:       # %bb.0: # %entry
+; RV64-PIC-NEXT:    lui a0, %tprel_hi(le)
+; RV64-PIC-NEXT:    add a0, a0, tp, %tprel_add(le)
+; RV64-PIC-NEXT:    addi a0, a0, %tprel_lo(le)
+; RV64-PIC-NEXT:    ret
+;
+; NOPIC-LABEL: f4:
+; NOPIC:       # %bb.0: # %entry
+; NOPIC-NEXT:    lui a0, %tprel_hi(le)
+; NOPIC-NEXT:    add a0, a0, tp, %tprel_add(le)
+; NOPIC-NEXT:    addi a0, a0, %tprel_lo(le)
+; NOPIC-NEXT:    ret
+entry:
+  ret i32* @le
+}




More information about the llvm-commits mailing list