[llvm] d1b526f - [LoongArch] Add codegen support of GlobalTLSAddress lowering

Weining Lu via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 11 03:11:25 PDT 2022


Author: wanglei
Date: 2022-10-11T18:10:13+08:00
New Revision: d1b526fb95c867ea816180194cbf4348f64d9c7e

URL: https://github.com/llvm/llvm-project/commit/d1b526fb95c867ea816180194cbf4348f64d9c7e
DIFF: https://github.com/llvm/llvm-project/commit/d1b526fb95c867ea816180194cbf4348f64d9c7e.diff

LOG: [LoongArch] Add codegen support of GlobalTLSAddress lowering

There are static and dynamic TLS address lowering in DAG stage according
to different TLS models.

TLS address will be lowered to pseudo instruction and then expanded by
the `LoongArch Pre-RA pseudo instruction expansion` pass.

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

Added: 
    llvm/test/CodeGen/LoongArch/tls-models.ll

Modified: 
    llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
    llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
    llvm/lib/Target/LoongArch/LoongArchISelLowering.h
    llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
    llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
index 08b3a0faa05a..1961444be8cf 100644
--- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
@@ -62,6 +62,18 @@ class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
   bool expandLoadAddressGot(MachineBasicBlock &MBB,
                             MachineBasicBlock::iterator MBBI,
                             MachineBasicBlock::iterator &NextMBBI);
+  bool expandLoadAddressTLSLE(MachineBasicBlock &MBB,
+                              MachineBasicBlock::iterator MBBI,
+                              MachineBasicBlock::iterator &NextMBBI);
+  bool expandLoadAddressTLSIE(MachineBasicBlock &MBB,
+                              MachineBasicBlock::iterator MBBI,
+                              MachineBasicBlock::iterator &NextMBBI);
+  bool expandLoadAddressTLSLD(MachineBasicBlock &MBB,
+                              MachineBasicBlock::iterator MBBI,
+                              MachineBasicBlock::iterator &NextMBBI);
+  bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,
+                              MachineBasicBlock::iterator MBBI,
+                              MachineBasicBlock::iterator &NextMBBI);
 };
 
 char LoongArchPreRAExpandPseudo::ID = 0;
@@ -96,6 +108,14 @@ bool LoongArchPreRAExpandPseudo::expandMI(
     return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);
   case LoongArch::PseudoLA_GOT:
     return expandLoadAddressGot(MBB, MBBI, NextMBBI);
+  case LoongArch::PseudoLA_TLS_LE:
+    return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI);
+  case LoongArch::PseudoLA_TLS_IE:
+    return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI);
+  case LoongArch::PseudoLA_TLS_LD:
+    return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI);
+  case LoongArch::PseudoLA_TLS_GD:
+    return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);
   }
   return false;
 }
@@ -154,6 +174,71 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
                                  SecondOpcode, LoongArchII::MO_GOT_PC_LO);
 }
 
+bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+    MachineBasicBlock::iterator &NextMBBI) {
+  // Code Sequence:
+  // lu12i.w $rd, %le_hi20(sym)
+  // ori $rd, $rd, %le_lo12(sym)
+  MachineFunction *MF = MBB.getParent();
+  MachineInstr &MI = *MBBI;
+  DebugLoc DL = MI.getDebugLoc();
+
+  Register DestReg = MI.getOperand(0).getReg();
+  Register ScratchReg =
+      MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
+  MachineOperand &Symbol = MI.getOperand(1);
+
+  BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), ScratchReg)
+      .addDisp(Symbol, 0, LoongArchII::MO_LE_HI);
+
+  BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), DestReg)
+      .addReg(ScratchReg)
+      .addDisp(Symbol, 0, LoongArchII::MO_LE_LO);
+
+  MI.eraseFromParent();
+  return true;
+}
+
+bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+    MachineBasicBlock::iterator &NextMBBI) {
+  // Code Sequence:
+  // pcalau12i $rd, %ie_pc_hi20(sym)
+  // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
+  MachineFunction *MF = MBB.getParent();
+  const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
+  unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
+  return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_IE_PC_HI,
+                                 SecondOpcode, LoongArchII::MO_IE_PC_LO);
+}
+
+bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+    MachineBasicBlock::iterator &NextMBBI) {
+  // Code Sequence:
+  // pcalau12i $rd, %ld_pc_hi20(sym)
+  // addi.w/d $rd, $rd, %got_pc_lo12(sym)
+  MachineFunction *MF = MBB.getParent();
+  const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
+  unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+  return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_LD_PC_HI,
+                                 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
+}
+
+bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+    MachineBasicBlock::iterator &NextMBBI) {
+  // Code Sequence:
+  // pcalau12i $rd, %gd_pc_hi20(sym)
+  // addi.w/d $rd, $rd, %got_pc_lo12(sym)
+  MachineFunction *MF = MBB.getParent();
+  const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
+  unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+  return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GD_PC_HI,
+                                 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
+}
+
 } // end namespace
 
 INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "LoongArch-prera-expand-pseudo",

diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 003a4ac6f2a2..2b00bb49eaeb 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -62,6 +62,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
                       ISD::JumpTable},
                      GRLenVT, Custom);
 
+  setOperationAction(ISD::GlobalTLSAddress, GRLenVT, Custom);
+
   setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
 
   setOperationAction(ISD::EH_DWARF_CFA, MVT::i32, Custom);
@@ -193,6 +195,8 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
     return lowerEH_DWARF_CFA(Op, DAG);
   case ISD::GlobalAddress:
     return lowerGlobalAddress(Op, DAG);
+  case ISD::GlobalTLSAddress:
+    return lowerGlobalTLSAddress(Op, DAG);
   case ISD::INTRINSIC_WO_CHAIN:
     return lowerINTRINSIC_WO_CHAIN(Op, DAG);
   case ISD::BlockAddress:
@@ -353,6 +357,85 @@ SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op,
   return getAddr(N, DAG, N->getGlobal()->isDSOLocal());
 }
 
+SDValue LoongArchTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N,
+                                                  SelectionDAG &DAG,
+                                                  unsigned Opc) const {
+  SDLoc DL(N);
+  EVT Ty = getPointerTy(DAG.getDataLayout());
+  MVT GRLenVT = Subtarget.getGRLenVT();
+
+  SDValue Addr = DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, 0);
+  SDValue Offset = SDValue(DAG.getMachineNode(Opc, DL, Ty, Addr), 0);
+
+  // Add the thread pointer.
+  return DAG.getNode(ISD::ADD, DL, Ty, Offset,
+                     DAG.getRegister(LoongArch::R2, GRLenVT));
+}
+
+SDValue LoongArchTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N,
+                                                   SelectionDAG &DAG,
+                                                   unsigned Opc) const {
+  SDLoc DL(N);
+  EVT Ty = getPointerTy(DAG.getDataLayout());
+  IntegerType *CallTy = Type::getIntNTy(*DAG.getContext(), Ty.getSizeInBits());
+
+  // Use a PC-relative addressing mode to access the dynamic GOT address.
+  SDValue Addr = DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, 0);
+  SDValue Load = SDValue(DAG.getMachineNode(Opc, 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
+LoongArchTargetLowering::lowerGlobalTLSAddress(SDValue Op,
+                                               SelectionDAG &DAG) const {
+  GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
+  assert(N->getOffset() == 0 && "unexpected offset in global node");
+
+  SDValue Addr;
+  TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal());
+
+  switch (Model) {
+  case TLSModel::GeneralDynamic:
+    // In this model, application code calls the dynamic linker function
+    // __tls_get_addr to locate TLS offsets into the dynamic thread vector at
+    // runtime.
+    Addr = getDynamicTLSAddr(N, DAG, LoongArch::PseudoLA_TLS_GD);
+    break;
+  case TLSModel::LocalDynamic:
+    // Same as GeneralDynamic, except for assembly modifiers and relocation
+    // records.
+    Addr = getDynamicTLSAddr(N, DAG, LoongArch::PseudoLA_TLS_LD);
+    break;
+  case TLSModel::InitialExec:
+    // This model uses the GOT to resolve TLS offsets.
+    Addr = getStaticTLSAddr(N, DAG, LoongArch::PseudoLA_TLS_IE);
+    break;
+  case TLSModel::LocalExec:
+    // This model is used when static linking as the TLS offsets are resolved
+    // during program linking.
+    Addr = getStaticTLSAddr(N, DAG, LoongArch::PseudoLA_TLS_LE);
+    break;
+  }
+
+  return Addr;
+}
+
 SDValue LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
                                                          SelectionDAG &DAG) const {
   unsigned IntNo = Op.getConstantOperandVal(0);

diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 084b269cd397..a0b9a8d8e3c7 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -138,9 +138,14 @@ class LoongArchTargetLowering : public TargetLowering {
 
   template <class NodeTy>
   SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const;
+  SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
+                           unsigned Opc) const;
+  SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
+                            unsigned Opc) const;
   SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
+  SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const;
 

diff  --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 4a0f6ed509b1..657c494dabe1 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -926,6 +926,18 @@ def PseudoLA_PCREL : Pseudo<(outs GPR:$dst), (ins grlenimm:$src), []>;
 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
 def PseudoLA_GOT : Pseudo<(outs GPR:$dst), (ins grlenimm:$src), []>;
 
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+def PseudoLA_TLS_LE : Pseudo<(outs GPR:$dst), (ins grlenimm:$src), []>;
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins grlenimm:$src), []>;
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+def PseudoLA_TLS_LD : Pseudo<(outs GPR:$dst), (ins grlenimm:$src), []>;
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins grlenimm:$src), []>;
+
 /// BSTRINS and BSTRPICK
 
 let Predicates = [IsLA32] in {

diff  --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
index af17ffc75988..40c98148ff79 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
@@ -53,6 +53,24 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
   case LoongArchII::MO_GOT_PC_LO:
     Kind = LoongArchMCExpr::VK_LoongArch_GOT_LO12;
     break;
+  case LoongArchII::MO_LE_HI:
+    Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20;
+    break;
+  case LoongArchII::MO_LE_LO:
+    Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12;
+    break;
+  case LoongArchII::MO_IE_PC_HI:
+    Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20;
+    break;
+  case LoongArchII::MO_IE_PC_LO:
+    Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
+    break;
+  case LoongArchII::MO_LD_PC_HI:
+    Kind = LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20;
+    break;
+  case LoongArchII::MO_GD_PC_HI:
+    Kind = LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20;
+    break;
     // TODO: Handle more target-flags.
   }
 

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
index 77938b997ec0..c5f072677999 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
@@ -33,6 +33,12 @@ enum {
   MO_PCREL_LO,
   MO_GOT_PC_HI,
   MO_GOT_PC_LO,
+  MO_LE_HI,
+  MO_LE_LO,
+  MO_IE_PC_HI,
+  MO_IE_PC_LO,
+  MO_LD_PC_HI,
+  MO_GD_PC_HI,
   // TODO: Add more flags.
 };
 } // end namespace LoongArchII

diff  --git a/llvm/test/CodeGen/LoongArch/tls-models.ll b/llvm/test/CodeGen/LoongArch/tls-models.ll
new file mode 100644
index 000000000000..1128532668e6
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/tls-models.ll
@@ -0,0 +1,166 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc --mtriple=loongarch32 --relocation-model=pic < %s | FileCheck %s --check-prefix=LA32PIC
+; RUN: llc --mtriple=loongarch64 --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64PIC
+; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32NOPIC
+; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64NOPIC
+
+;; Check that TLS symbols are lowered correctly based on the specified
+;; model. Make sure they're external to avoid them all being optimised to Local
+;; Exec for the executable.
+
+ at unspecified = external thread_local global i32
+ at ld = external thread_local(localdynamic) global i32
+ at ie = external thread_local(initialexec) global i32
+ at le = external thread_local(localexec) global i32
+
+;; No model specified (global dynamic)
+
+define ptr @f1() nounwind {
+; LA32PIC-LABEL: f1:
+; LA32PIC:       # %bb.0: # %entry
+; LA32PIC-NEXT:    addi.w $sp, $sp, -16
+; LA32PIC-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32PIC-NEXT:    pcalau12i $a0, %gd_pc_hi20(unspecified)
+; LA32PIC-NEXT:    addi.w $a0, $a0, %got_lo12(unspecified)
+; LA32PIC-NEXT:    bl %plt(__tls_get_addr)
+; LA32PIC-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32PIC-NEXT:    addi.w $sp, $sp, 16
+; LA32PIC-NEXT:    ret
+;
+; LA64PIC-LABEL: f1:
+; LA64PIC:       # %bb.0: # %entry
+; LA64PIC-NEXT:    addi.d $sp, $sp, -16
+; LA64PIC-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64PIC-NEXT:    pcalau12i $a0, %gd_pc_hi20(unspecified)
+; LA64PIC-NEXT:    addi.d $a0, $a0, %got_lo12(unspecified)
+; LA64PIC-NEXT:    bl %plt(__tls_get_addr)
+; LA64PIC-NEXT:    ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64PIC-NEXT:    addi.d $sp, $sp, 16
+; LA64PIC-NEXT:    ret
+;
+; LA32NOPIC-LABEL: f1:
+; LA32NOPIC:       # %bb.0: # %entry
+; LA32NOPIC-NEXT:    pcalau12i $a0, %ie_pc_hi20(unspecified)
+; LA32NOPIC-NEXT:    ld.w $a0, $a0, %ie_pc_lo12(unspecified)
+; LA32NOPIC-NEXT:    add.w $a0, $a0, $tp
+; LA32NOPIC-NEXT:    ret
+;
+; LA64NOPIC-LABEL: f1:
+; LA64NOPIC:       # %bb.0: # %entry
+; LA64NOPIC-NEXT:    pcalau12i $a0, %ie_pc_hi20(unspecified)
+; LA64NOPIC-NEXT:    ld.d $a0, $a0, %ie_pc_lo12(unspecified)
+; LA64NOPIC-NEXT:    add.d $a0, $a0, $tp
+; LA64NOPIC-NEXT:    ret
+entry:
+  ret ptr @unspecified
+}
+
+;; localdynamic specified
+
+define ptr @f2() nounwind {
+; LA32PIC-LABEL: f2:
+; LA32PIC:       # %bb.0: # %entry
+; LA32PIC-NEXT:    addi.w $sp, $sp, -16
+; LA32PIC-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32PIC-NEXT:    pcalau12i $a0, %ld_pc_hi20(ld)
+; LA32PIC-NEXT:    addi.w $a0, $a0, %got_lo12(ld)
+; LA32PIC-NEXT:    bl %plt(__tls_get_addr)
+; LA32PIC-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32PIC-NEXT:    addi.w $sp, $sp, 16
+; LA32PIC-NEXT:    ret
+;
+; LA64PIC-LABEL: f2:
+; LA64PIC:       # %bb.0: # %entry
+; LA64PIC-NEXT:    addi.d $sp, $sp, -16
+; LA64PIC-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64PIC-NEXT:    pcalau12i $a0, %ld_pc_hi20(ld)
+; LA64PIC-NEXT:    addi.d $a0, $a0, %got_lo12(ld)
+; LA64PIC-NEXT:    bl %plt(__tls_get_addr)
+; LA64PIC-NEXT:    ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64PIC-NEXT:    addi.d $sp, $sp, 16
+; LA64PIC-NEXT:    ret
+;
+; LA32NOPIC-LABEL: f2:
+; LA32NOPIC:       # %bb.0: # %entry
+; LA32NOPIC-NEXT:    pcalau12i $a0, %ie_pc_hi20(ld)
+; LA32NOPIC-NEXT:    ld.w $a0, $a0, %ie_pc_lo12(ld)
+; LA32NOPIC-NEXT:    add.w $a0, $a0, $tp
+; LA32NOPIC-NEXT:    ret
+;
+; LA64NOPIC-LABEL: f2:
+; LA64NOPIC:       # %bb.0: # %entry
+; LA64NOPIC-NEXT:    pcalau12i $a0, %ie_pc_hi20(ld)
+; LA64NOPIC-NEXT:    ld.d $a0, $a0, %ie_pc_lo12(ld)
+; LA64NOPIC-NEXT:    add.d $a0, $a0, $tp
+; LA64NOPIC-NEXT:    ret
+entry:
+  ret ptr @ld
+}
+
+;; initialexec specified
+
+define ptr @f3() nounwind {
+; LA32PIC-LABEL: f3:
+; LA32PIC:       # %bb.0: # %entry
+; LA32PIC-NEXT:    pcalau12i $a0, %ie_pc_hi20(ie)
+; LA32PIC-NEXT:    ld.w $a0, $a0, %ie_pc_lo12(ie)
+; LA32PIC-NEXT:    add.w $a0, $a0, $tp
+; LA32PIC-NEXT:    ret
+;
+; LA64PIC-LABEL: f3:
+; LA64PIC:       # %bb.0: # %entry
+; LA64PIC-NEXT:    pcalau12i $a0, %ie_pc_hi20(ie)
+; LA64PIC-NEXT:    ld.d $a0, $a0, %ie_pc_lo12(ie)
+; LA64PIC-NEXT:    add.d $a0, $a0, $tp
+; LA64PIC-NEXT:    ret
+;
+; LA32NOPIC-LABEL: f3:
+; LA32NOPIC:       # %bb.0: # %entry
+; LA32NOPIC-NEXT:    pcalau12i $a0, %ie_pc_hi20(ie)
+; LA32NOPIC-NEXT:    ld.w $a0, $a0, %ie_pc_lo12(ie)
+; LA32NOPIC-NEXT:    add.w $a0, $a0, $tp
+; LA32NOPIC-NEXT:    ret
+;
+; LA64NOPIC-LABEL: f3:
+; LA64NOPIC:       # %bb.0: # %entry
+; LA64NOPIC-NEXT:    pcalau12i $a0, %ie_pc_hi20(ie)
+; LA64NOPIC-NEXT:    ld.d $a0, $a0, %ie_pc_lo12(ie)
+; LA64NOPIC-NEXT:    add.d $a0, $a0, $tp
+; LA64NOPIC-NEXT:    ret
+entry:
+  ret ptr @ie
+}
+
+;; localexec specified
+
+define ptr @f4() nounwind {
+; LA32PIC-LABEL: f4:
+; LA32PIC:       # %bb.0: # %entry
+; LA32PIC-NEXT:    lu12i.w $a0, %le_hi20(le)
+; LA32PIC-NEXT:    ori $a0, $a0, %le_lo12(le)
+; LA32PIC-NEXT:    add.w $a0, $a0, $tp
+; LA32PIC-NEXT:    ret
+;
+; LA64PIC-LABEL: f4:
+; LA64PIC:       # %bb.0: # %entry
+; LA64PIC-NEXT:    lu12i.w $a0, %le_hi20(le)
+; LA64PIC-NEXT:    ori $a0, $a0, %le_lo12(le)
+; LA64PIC-NEXT:    add.d $a0, $a0, $tp
+; LA64PIC-NEXT:    ret
+;
+; LA32NOPIC-LABEL: f4:
+; LA32NOPIC:       # %bb.0: # %entry
+; LA32NOPIC-NEXT:    lu12i.w $a0, %le_hi20(le)
+; LA32NOPIC-NEXT:    ori $a0, $a0, %le_lo12(le)
+; LA32NOPIC-NEXT:    add.w $a0, $a0, $tp
+; LA32NOPIC-NEXT:    ret
+;
+; LA64NOPIC-LABEL: f4:
+; LA64NOPIC:       # %bb.0: # %entry
+; LA64NOPIC-NEXT:    lu12i.w $a0, %le_hi20(le)
+; LA64NOPIC-NEXT:    ori $a0, $a0, %le_lo12(le)
+; LA64NOPIC-NEXT:    add.d $a0, $a0, $tp
+; LA64NOPIC-NEXT:    ret
+entry:
+  ret ptr @le
+}


        


More information about the llvm-commits mailing list