mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 20:36:06 +00:00
[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:
parent
ff6c0cac70
commit
eb148aecb3
@ -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()) {
|
||||
|
14
clang/test/CodeGen/LoongArch/tls-dialect.c
Normal file
14
clang/test/CodeGen/LoongArch/tls-dialect.c
Normal 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;
|
||||
}
|
@ -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"
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user