[LoongArch][Codegen] Add support for TLSDESC

The implementation only enables when the `-enable-tlsdesc` option is
passed and the TLS model is `dynamic`.

LoongArch's GCC has the same option(-mtls-dialet=) as RISC-V.

Reviewers: heiher, MaskRay, SixWeining

Reviewed By: SixWeining, MaskRay

Pull Request: https://github.com/llvm/llvm-project/pull/90159
This commit is contained in:
wanglei 2024-04-30 15:14:44 +08:00 committed by GitHub
parent ff6c0cac70
commit eb148aecb3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 343 additions and 16 deletions

View File

@ -737,7 +737,7 @@ bool tools::isTLSDESCEnabled(const ToolChain &TC,
StringRef V = A->getValue();
bool SupportedArgument = false, EnableTLSDESC = false;
bool Unsupported = !Triple.isOSBinFormatELF();
if (Triple.isRISCV()) {
if (Triple.isLoongArch() || Triple.isRISCV()) {
SupportedArgument = V == "desc" || V == "trad";
EnableTLSDESC = V == "desc";
} else if (Triple.isX86()) {

View File

@ -0,0 +1,14 @@
// REQUIRES: loongarch-registered-target
/// cc1 -enable-tlsdesc (due to -mtls-dialect=desc) enables TLSDESC.
// RUN: %clang_cc1 -triple loongarch64 -S -mrelocation-model pic -pic-level 1 -enable-tlsdesc %s -o - | FileCheck %s --check-prefix=DESC
// RUN: %clang_cc1 -triple loongarch64 -S -mrelocation-model pic -pic-level 1 %s -o - | FileCheck %s --check-prefix=NODESC
__thread int x;
// DESC: %desc_pc_hi20
// DESC-NOT: %gd_pc_hi20
// NODESC: %gd_pc_hi20
// NODESC-NOT: %desc_pc_hi20
int use() {
return x;
}

View File

@ -1,3 +1,5 @@
// RUN: %clang -### --target=loongarch64-linux -mtls-dialect=trad %s 2>&1 | FileCheck --check-prefix=NODESC %s
// RUN: %clang -### --target=loongarch64-linux %s 2>&1 | FileCheck --check-prefix=NODESC %s
// RUN: %clang -### --target=riscv64-freebsd -mtls-dialect=desc %s 2>&1 | FileCheck --check-prefix=DESC %s
// RUN: %clang -### --target=riscv64-linux -mtls-dialect=trad %s 2>&1 | FileCheck --check-prefix=NODESC %s
// RUN: %clang -### --target=riscv64-linux %s 2>&1 | FileCheck --check-prefix=NODESC %s
@ -9,6 +11,8 @@
// RUN: %clang -### --target=riscv64-android %s 2>&1 | FileCheck --check-prefix=DESC %s
/// LTO
// RUN: %clang -### --target=loongarch64-linux -flto -mtls-dialect=desc %s 2>&1 | FileCheck --check-prefix=LTO-DESC %s
// RUN: %clang -### --target=loongarch64-linux -flto %s 2>&1 | FileCheck --check-prefix=LTO-NODESC %s
// RUN: %clang -### --target=riscv64-linux -flto -mtls-dialect=desc %s 2>&1 | FileCheck --check-prefix=LTO-DESC %s
// RUN: %clang -### --target=riscv64-linux -flto %s 2>&1 | FileCheck --check-prefix=LTO-NODESC %s
@ -18,6 +22,7 @@
// RUN: not %clang --target=x86_64-apple-macos -mtls-dialect=desc -flto %s 2>&1 | FileCheck -check-prefix=UNSUPPORTED-TARGET %s
/// Unsupported argument
// RUN: not %clang -### --target=loongarch64-linux -mtls-dialect=gnu2 %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED-ARG %s
// RUN: not %clang -### --target=riscv64-linux -mtls-dialect=gnu2 %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED-ARG %s
// DESC: "-cc1" {{.*}}"-enable-tlsdesc"

View File

@ -80,6 +80,9 @@ private:
bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI);
bool expandLoadAddressTLSDesc(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI);
};
char LoongArchPreRAExpandPseudo::ID = 0;
@ -122,6 +125,8 @@ bool LoongArchPreRAExpandPseudo::expandMI(
return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI);
case LoongArch::PseudoLA_TLS_GD:
return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);
case LoongArch::PseudoLA_TLS_DESC_PC:
return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI);
}
return false;
}
@ -267,6 +272,52 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
SecondOpcode, LoongArchII::MO_GOT_PC_LO);
}
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI) {
// Code Sequence:
// pcalau12i $a0, %desc_pc_hi20(sym)
// addi.w/d $a0, $a0, %desc_pc_lo12(sym)
// ld.w/d $ra, $a0, %desc_ld(sym)
// jirl $ra, $ra, %desc_ld(sym)
// add.d $dst, $a0, $tp
MachineFunction *MF = MBB.getParent();
MachineInstr &MI = *MBBI;
DebugLoc DL = MI.getDebugLoc();
const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
unsigned ADD = STI.is64Bit() ? LoongArch::ADD_D : LoongArch::ADD_W;
unsigned ADDI = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
unsigned LD = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
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::PCALAU12I), ScratchReg)
.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_HI);
BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)
.addReg(ScratchReg)
.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_LO);
BuildMI(MBB, MBBI, DL, TII->get(LD), LoongArch::R1)
.addReg(LoongArch::R4)
.addDisp(Symbol, 0, LoongArchII::MO_DESC_LD);
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)
.addReg(LoongArch::R1)
.addDisp(Symbol, 0, LoongArchII::MO_DESC_CALL);
BuildMI(MBB, MBBI, DL, TII->get(ADD), DestReg)
.addReg(LoongArch::R4)
.addReg(LoongArch::R2);
MI.eraseFromParent();
return true;
}
class LoongArchExpandPseudo : public MachineFunctionPass {
public:
const LoongArchInstrInfo *TII;
@ -313,6 +364,9 @@ private:
bool expandLoadAddressTLSGDLarge(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI);
bool expandLoadAddressTLSDescPcLarge(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI);
bool expandFunctionCALL(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI,
@ -361,6 +415,8 @@ bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,
return expandLoadAddressTLSLDLarge(MBB, MBBI, NextMBBI);
case LoongArch::PseudoLA_TLS_GD_LARGE:
return expandLoadAddressTLSGDLarge(MBB, MBBI, NextMBBI);
case LoongArch::PseudoLA_TLS_DESC_PC_LARGE:
return expandLoadAddressTLSDescPcLarge(MBB, MBBI, NextMBBI);
case LoongArch::PseudoCALL:
case LoongArch::PseudoCALL_MEDIUM:
case LoongArch::PseudoCALL_LARGE:
@ -560,6 +616,58 @@ bool LoongArchExpandPseudo::expandLoadAddressTLSGDLarge(
LoongArchII::MO_GD_PC_HI);
}
bool LoongArchExpandPseudo::expandLoadAddressTLSDescPcLarge(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI) {
// Code Sequence:
//
// pcalau12i $a0, %desc_pc_hi20(sym)
// addi.d $t8, $zero, %desc_pc_lo12(sym)
// lu32i.d $t8, %desc64_pc_lo20(sym)
// lu52i.d $t8, $t8, %desc64_pc_hi12(sym)
// add.d $a0, $a0, $t8
// ld.d $ra, $a0, %desc_ld(sym)
// jirl $ra, $ra, %desc_call(sym)
// add.d $dst, $a0, $tp
MachineInstr &MI = *MBBI;
DebugLoc DL = MI.getDebugLoc();
Register DestReg = MI.getOperand(0).getReg();
MachineOperand &Symbol = MI.getOperand(2);
Register ScratchReg = LoongArch::R20; // $t8
assert(MBB.getParent()->getSubtarget<LoongArchSubtarget>().is64Bit() &&
"Large code model requires LA64");
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), LoongArch::R4)
.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_HI);
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), ScratchReg)
.addReg(LoongArch::R0)
.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_LO);
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), ScratchReg)
.addReg(ScratchReg)
.addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_LO);
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), ScratchReg)
.addReg(ScratchReg)
.addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_HI);
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADD_D), LoongArch::R4)
.addReg(ScratchReg)
.addReg(LoongArch::R4);
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LD_D), LoongArch::R1)
.addReg(LoongArch::R4)
.addDisp(Symbol, 0, LoongArchII::MO_DESC_LD);
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)
.addReg(LoongArch::R1)
.addDisp(Symbol, 0, LoongArchII::MO_DESC_CALL);
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADD_D), DestReg)
.addReg(LoongArch::R4)
.addReg(LoongArch::R2);
MI.eraseFromParent();
return true;
}
bool LoongArchExpandPseudo::expandFunctionCALL(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {

View File

@ -903,6 +903,24 @@ SDValue LoongArchTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N,
return LowerCallTo(CLI).first;
}
SDValue LoongArchTargetLowering::getTLSDescAddr(GlobalAddressSDNode *N,
SelectionDAG &DAG, unsigned Opc,
bool Large) const {
SDLoc DL(N);
EVT Ty = getPointerTy(DAG.getDataLayout());
const GlobalValue *GV = N->getGlobal();
// This is not actually used, but is necessary for successfully matching the
// PseudoLA_*_LARGE nodes.
SDValue Tmp = DAG.getConstant(0, DL, Ty);
// Use a PC-relative addressing mode to access the global dynamic GOT address.
// This generates the pattern (PseudoLA_TLS_DESC_PC{,LARGE} sym).
SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, Ty, 0, 0);
return Large ? SDValue(DAG.getMachineNode(Opc, DL, Ty, Tmp, Addr), 0)
: SDValue(DAG.getMachineNode(Opc, DL, Ty, Addr), 0);
}
SDValue
LoongArchTargetLowering::lowerGlobalTLSAddress(SDValue Op,
SelectionDAG &DAG) const {
@ -916,42 +934,46 @@ LoongArchTargetLowering::lowerGlobalTLSAddress(SDValue Op,
GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
assert(N->getOffset() == 0 && "unexpected offset in global node");
SDValue Addr;
bool IsDesc = DAG.getTarget().useTLSDESC();
switch (getTargetMachine().getTLSModel(N->getGlobal())) {
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,
Large ? LoongArch::PseudoLA_TLS_GD_LARGE
: LoongArch::PseudoLA_TLS_GD,
Large);
if (!IsDesc)
return getDynamicTLSAddr(N, DAG,
Large ? LoongArch::PseudoLA_TLS_GD_LARGE
: LoongArch::PseudoLA_TLS_GD,
Large);
break;
case TLSModel::LocalDynamic:
// Same as GeneralDynamic, except for assembly modifiers and relocation
// records.
Addr = getDynamicTLSAddr(N, DAG,
Large ? LoongArch::PseudoLA_TLS_LD_LARGE
: LoongArch::PseudoLA_TLS_LD,
Large);
if (!IsDesc)
return getDynamicTLSAddr(N, DAG,
Large ? LoongArch::PseudoLA_TLS_LD_LARGE
: LoongArch::PseudoLA_TLS_LD,
Large);
break;
case TLSModel::InitialExec:
// This model uses the GOT to resolve TLS offsets.
Addr = getStaticTLSAddr(N, DAG,
return getStaticTLSAddr(N, DAG,
Large ? LoongArch::PseudoLA_TLS_IE_LARGE
: LoongArch::PseudoLA_TLS_IE,
Large);
break;
case TLSModel::LocalExec:
// This model is used when static linking as the TLS offsets are resolved
// during program linking.
//
// This node doesn't need an extra argument for the large code model.
Addr = getStaticTLSAddr(N, DAG, LoongArch::PseudoLA_TLS_LE);
break;
return getStaticTLSAddr(N, DAG, LoongArch::PseudoLA_TLS_LE);
}
return Addr;
return getTLSDescAddr(N, DAG,
Large ? LoongArch::PseudoLA_TLS_DESC_PC_LARGE
: LoongArch::PseudoLA_TLS_DESC_PC,
Large);
}
template <unsigned N>

View File

@ -263,6 +263,8 @@ private:
unsigned Opc, bool Large = false) const;
SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
unsigned Opc, bool Large = false) const;
SDValue getTLSDescAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
unsigned Opc, bool Large = false) const;
SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;

View File

@ -530,6 +530,12 @@ LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
{MO_IE_PC_LO, "loongarch-ie-pc-lo"},
{MO_IE_PC64_LO, "loongarch-ie-pc64-lo"},
{MO_IE_PC64_HI, "loongarch-ie-pc64-hi"},
{MO_DESC_PC_HI, "loongarch-desc-pc-hi"},
{MO_DESC_PC_LO, "loongarch-desc-pc-lo"},
{MO_DESC64_PC_LO, "loongarch-desc64-pc-lo"},
{MO_DESC64_PC_HI, "loongarch-desc64-pc-hi"},
{MO_DESC_LD, "loongarch-desc-ld"},
{MO_DESC_CALL, "loongarch-desc-call"},
{MO_LD_PC_HI, "loongarch-ld-pc-hi"},
{MO_GD_PC_HI, "loongarch-gd-pc-hi"}};
return ArrayRef(TargetFlags);

View File

@ -1607,6 +1607,13 @@ def PseudoLA_TLS_GD_LARGE : Pseudo<(outs GPR:$dst),
} // Defs = [R20], Size = 20
}
// Used for expand PseudoLA_TLS_DESC_* instructions.
let isCall = 1, isBarrier = 1, hasSideEffects = 0, mayStore = 0, mayLoad = 0,
Defs = [R4], Uses = [R4] in
def PseudoDESC_CALL : Pseudo<(outs GPR:$rd), (ins GPR:$rj, simm16_lsl2:$imm16)>,
PseudoInstExpansion<(JIRL GPR:$rd, GPR:$rj,
simm16_lsl2:$imm16)>;
// TLSDESC
let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
isAsmParserOnly = 1, Defs = [R1] in {

View File

@ -98,6 +98,24 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
case LoongArchII::MO_CALL36:
Kind = LoongArchMCExpr::VK_LoongArch_CALL36;
break;
case LoongArchII::MO_DESC_PC_HI:
Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20;
break;
case LoongArchII::MO_DESC_PC_LO:
Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12;
break;
case LoongArchII::MO_DESC64_PC_LO:
Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20;
break;
case LoongArchII::MO_DESC64_PC_HI:
Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12;
break;
case LoongArchII::MO_DESC_LD:
Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD;
break;
case LoongArchII::MO_DESC_CALL:
Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL;
break;
// TODO: Handle more target-flags.
}

View File

@ -47,7 +47,13 @@ enum {
MO_IE_PC64_HI,
MO_LD_PC_HI,
MO_GD_PC_HI,
MO_CALL36
MO_CALL36,
MO_DESC_PC_HI,
MO_DESC_PC_LO,
MO_DESC64_PC_HI,
MO_DESC64_PC_LO,
MO_DESC_LD,
MO_DESC_CALL,
// TODO: Add more flags.
};
} // end namespace LoongArchII

View File

@ -5,6 +5,12 @@
; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32NOPIC
; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64NOPIC
; RUN: llc --mtriple=loongarch64 --code-model=large < %s | FileCheck %s --check-prefix=LA64LARGENOPIC
; RUN: llc --mtriple=loongarch32 --relocation-model=pic --enable-tlsdesc < %s \
; RUN: | FileCheck %s --check-prefix=LA32DESC
; RUN: llc --mtriple=loongarch64 --relocation-model=pic --enable-tlsdesc < %s \
; RUN: | FileCheck %s --check-prefix=LA64DESC
; RUN: llc --mtriple=loongarch64 --relocation-model=pic --enable-tlsdesc \
; RUN: --code-model=large < %s | FileCheck %s --check-prefix=DESC64
;; 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
@ -82,6 +88,49 @@ define ptr @f1() nounwind {
; LA64LARGENOPIC-NEXT: ldx.d $a0, $t8, $a0
; LA64LARGENOPIC-NEXT: add.d $a0, $a0, $tp
; LA64LARGENOPIC-NEXT: ret
;
; LA32DESC-LABEL: f1:
; LA32DESC: # %bb.0: # %entry
; LA32DESC-NEXT: addi.w $sp, $sp, -16
; LA32DESC-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
; LA32DESC-NEXT: pcalau12i $a0, %desc_pc_hi20(unspecified)
; LA32DESC-NEXT: addi.w $a0, $a0, %desc_pc_lo12(unspecified)
; LA32DESC-NEXT: ld.w $ra, $a0, %desc_ld(unspecified)
; LA32DESC-NEXT: jirl $ra, $ra, %desc_call(unspecified)
; LA32DESC-NEXT: add.w $a0, $a0, $tp
; LA32DESC-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
; LA32DESC-NEXT: addi.w $sp, $sp, 16
; LA32DESC-NEXT: ret
;
; LA64DESC-LABEL: f1:
; LA64DESC: # %bb.0: # %entry
; LA64DESC-NEXT: addi.d $sp, $sp, -16
; LA64DESC-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; LA64DESC-NEXT: pcalau12i $a0, %desc_pc_hi20(unspecified)
; LA64DESC-NEXT: addi.d $a0, $a0, %desc_pc_lo12(unspecified)
; LA64DESC-NEXT: ld.d $ra, $a0, %desc_ld(unspecified)
; LA64DESC-NEXT: jirl $ra, $ra, %desc_call(unspecified)
; LA64DESC-NEXT: add.d $a0, $a0, $tp
; LA64DESC-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; LA64DESC-NEXT: addi.d $sp, $sp, 16
; LA64DESC-NEXT: ret
;
; DESC64-LABEL: f1:
; DESC64: # %bb.0: # %entry
; DESC64-NEXT: addi.d $sp, $sp, -16
; DESC64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; DESC64-NEXT: pcalau12i $a0, %desc_pc_hi20(unspecified)
; DESC64-NEXT: addi.d $t8, $zero, %desc_pc_lo12(unspecified)
; DESC64-NEXT: lu32i.d $t8, %desc64_pc_lo20(unspecified)
; DESC64-NEXT: lu52i.d $t8, $t8, %desc64_pc_hi12(unspecified)
; DESC64-NEXT: add.d $a0, $t8, $a0
; DESC64-NEXT: ld.d $ra, $a0, %desc_ld(unspecified)
; DESC64-NEXT: jirl $ra, $ra, %desc_call(unspecified)
; DESC64-NEXT: add.d $a1, $a0, $tp
; DESC64-NEXT: move $a0, $a1
; DESC64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; DESC64-NEXT: addi.d $sp, $sp, 16
; DESC64-NEXT: ret
entry:
ret ptr @unspecified
}
@ -153,6 +202,49 @@ define ptr @f2() nounwind {
; LA64LARGENOPIC-NEXT: ldx.d $a0, $t8, $a0
; LA64LARGENOPIC-NEXT: add.d $a0, $a0, $tp
; LA64LARGENOPIC-NEXT: ret
;
; LA32DESC-LABEL: f2:
; LA32DESC: # %bb.0: # %entry
; LA32DESC-NEXT: addi.w $sp, $sp, -16
; LA32DESC-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
; LA32DESC-NEXT: pcalau12i $a0, %desc_pc_hi20(ld)
; LA32DESC-NEXT: addi.w $a0, $a0, %desc_pc_lo12(ld)
; LA32DESC-NEXT: ld.w $ra, $a0, %desc_ld(ld)
; LA32DESC-NEXT: jirl $ra, $ra, %desc_call(ld)
; LA32DESC-NEXT: add.w $a0, $a0, $tp
; LA32DESC-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
; LA32DESC-NEXT: addi.w $sp, $sp, 16
; LA32DESC-NEXT: ret
;
; LA64DESC-LABEL: f2:
; LA64DESC: # %bb.0: # %entry
; LA64DESC-NEXT: addi.d $sp, $sp, -16
; LA64DESC-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; LA64DESC-NEXT: pcalau12i $a0, %desc_pc_hi20(ld)
; LA64DESC-NEXT: addi.d $a0, $a0, %desc_pc_lo12(ld)
; LA64DESC-NEXT: ld.d $ra, $a0, %desc_ld(ld)
; LA64DESC-NEXT: jirl $ra, $ra, %desc_call(ld)
; LA64DESC-NEXT: add.d $a0, $a0, $tp
; LA64DESC-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; LA64DESC-NEXT: addi.d $sp, $sp, 16
; LA64DESC-NEXT: ret
;
; DESC64-LABEL: f2:
; DESC64: # %bb.0: # %entry
; DESC64-NEXT: addi.d $sp, $sp, -16
; DESC64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; DESC64-NEXT: pcalau12i $a0, %desc_pc_hi20(ld)
; DESC64-NEXT: addi.d $t8, $zero, %desc_pc_lo12(ld)
; DESC64-NEXT: lu32i.d $t8, %desc64_pc_lo20(ld)
; DESC64-NEXT: lu52i.d $t8, $t8, %desc64_pc_hi12(ld)
; DESC64-NEXT: add.d $a0, $t8, $a0
; DESC64-NEXT: ld.d $ra, $a0, %desc_ld(ld)
; DESC64-NEXT: jirl $ra, $ra, %desc_call(ld)
; DESC64-NEXT: add.d $a1, $a0, $tp
; DESC64-NEXT: move $a0, $a1
; DESC64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; DESC64-NEXT: addi.d $sp, $sp, 16
; DESC64-NEXT: ret
entry:
ret ptr @ld
}
@ -207,6 +299,30 @@ define ptr @f3() nounwind {
; LA64LARGENOPIC-NEXT: ldx.d $a0, $t8, $a0
; LA64LARGENOPIC-NEXT: add.d $a0, $a0, $tp
; LA64LARGENOPIC-NEXT: ret
;
; LA32DESC-LABEL: f3:
; LA32DESC: # %bb.0: # %entry
; LA32DESC-NEXT: pcalau12i $a0, %ie_pc_hi20(ie)
; LA32DESC-NEXT: ld.w $a0, $a0, %ie_pc_lo12(ie)
; LA32DESC-NEXT: add.w $a0, $a0, $tp
; LA32DESC-NEXT: ret
;
; LA64DESC-LABEL: f3:
; LA64DESC: # %bb.0: # %entry
; LA64DESC-NEXT: pcalau12i $a0, %ie_pc_hi20(ie)
; LA64DESC-NEXT: ld.d $a0, $a0, %ie_pc_lo12(ie)
; LA64DESC-NEXT: add.d $a0, $a0, $tp
; LA64DESC-NEXT: ret
;
; DESC64-LABEL: f3:
; DESC64: # %bb.0: # %entry
; DESC64-NEXT: pcalau12i $a0, %ie_pc_hi20(ie)
; DESC64-NEXT: addi.d $t8, $zero, %ie_pc_lo12(ie)
; DESC64-NEXT: lu32i.d $t8, %ie64_pc_lo20(ie)
; DESC64-NEXT: lu52i.d $t8, $t8, %ie64_pc_hi12(ie)
; DESC64-NEXT: ldx.d $a0, $t8, $a0
; DESC64-NEXT: add.d $a0, $a0, $tp
; DESC64-NEXT: ret
entry:
ret ptr @ie
}
@ -259,6 +375,29 @@ define ptr @f4() nounwind {
; LA64LARGENOPIC-NEXT: lu52i.d $a0, $a0, %le64_hi12(le)
; LA64LARGENOPIC-NEXT: add.d $a0, $a0, $tp
; LA64LARGENOPIC-NEXT: ret
;
; LA32DESC-LABEL: f4:
; LA32DESC: # %bb.0: # %entry
; LA32DESC-NEXT: lu12i.w $a0, %le_hi20(le)
; LA32DESC-NEXT: ori $a0, $a0, %le_lo12(le)
; LA32DESC-NEXT: add.w $a0, $a0, $tp
; LA32DESC-NEXT: ret
;
; LA64DESC-LABEL: f4:
; LA64DESC: # %bb.0: # %entry
; LA64DESC-NEXT: lu12i.w $a0, %le_hi20(le)
; LA64DESC-NEXT: ori $a0, $a0, %le_lo12(le)
; LA64DESC-NEXT: add.d $a0, $a0, $tp
; LA64DESC-NEXT: ret
;
; DESC64-LABEL: f4:
; DESC64: # %bb.0: # %entry
; DESC64-NEXT: lu12i.w $a0, %le_hi20(le)
; DESC64-NEXT: ori $a0, $a0, %le_lo12(le)
; DESC64-NEXT: lu32i.d $a0, %le64_lo20(le)
; DESC64-NEXT: lu52i.d $a0, $a0, %le64_hi12(le)
; DESC64-NEXT: add.d $a0, $a0, $tp
; DESC64-NEXT: ret
entry:
ret ptr @le
}