-
Notifications
You must be signed in to change notification settings - Fork 11k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[LoongArch][Codegen] Add support for TLSDESC #90159
[LoongArch][Codegen] Add support for TLSDESC #90159
Conversation
Created using spr 1.3.4 [skip ci]
Created using spr 1.3.4
@llvm/pr-subscribers-backend-loongarch @llvm/pr-subscribers-clang Author: wanglei (wangleiat) ChangesThe implementation only enables when the LoongArch's GCC has the same option(-mtls-dialet=) as RISC-V. Patch is 23.12 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/90159.diff 10 Files Affected:
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index b65b96db16bd79..a5000221f61903 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -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.isRISCV() || Triple.isLoongArch()) {
SupportedArgument = V == "desc" || V == "trad";
EnableTLSDESC = V == "desc";
} else if (Triple.isX86()) {
diff --git a/clang/test/CodeGen/LoongArch/tls-dialect.c b/clang/test/CodeGen/LoongArch/tls-dialect.c
new file mode 100644
index 00000000000000..03401ef8af03d4
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/tls-dialect.c
@@ -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;
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
index ad39658f698e7b..c136f5b3e515d7 100644
--- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
@@ -80,6 +80,9 @@ class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
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 @@ class LoongArchExpandPseudo : public MachineFunctionPass {
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) {
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 285d5c2a63b2da..e5c80644d4a83e 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -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>
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 4bb6c049f8d758..31b4d651956342 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -263,6 +263,8 @@ class LoongArchTargetLowering : public TargetLowering {
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;
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
index 6576100d3b3218..babb6632471bbf 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
@@ -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);
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 958803b52d4ec8..a7f6eb9a79ebc0 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -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 {
diff --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
index 98ad49f25e3f2f..d1d428241ebcc2 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
@@ -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.
}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
index 0692cb92b69440..3c3fed7d43ed98 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
@@ -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
diff --git a/llvm/test/CodeGen/LoongArch/tls-models.ll b/llvm/test/CodeGen/LoongArch/tls-models.ll
index 3994df1da7163f..6b250ec021624a 100644
--- a/llvm/test/CodeGen/LoongArch/tls-models.ll
+++ b/llvm/test/CodeGen/LoongArch/tls-models.ll
@@ -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: ...
[truncated]
|
@llvm/pr-subscribers-clang-driver Author: wanglei (wangleiat) ChangesThe implementation only enables when the LoongArch's GCC has the same option(-mtls-dialet=) as RISC-V. Patch is 23.12 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/90159.diff 10 Files Affected:
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index b65b96db16bd79..a5000221f61903 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -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.isRISCV() || Triple.isLoongArch()) {
SupportedArgument = V == "desc" || V == "trad";
EnableTLSDESC = V == "desc";
} else if (Triple.isX86()) {
diff --git a/clang/test/CodeGen/LoongArch/tls-dialect.c b/clang/test/CodeGen/LoongArch/tls-dialect.c
new file mode 100644
index 00000000000000..03401ef8af03d4
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/tls-dialect.c
@@ -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;
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
index ad39658f698e7b..c136f5b3e515d7 100644
--- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
@@ -80,6 +80,9 @@ class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
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 @@ class LoongArchExpandPseudo : public MachineFunctionPass {
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) {
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 285d5c2a63b2da..e5c80644d4a83e 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -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>
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 4bb6c049f8d758..31b4d651956342 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -263,6 +263,8 @@ class LoongArchTargetLowering : public TargetLowering {
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;
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
index 6576100d3b3218..babb6632471bbf 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
@@ -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);
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 958803b52d4ec8..a7f6eb9a79ebc0 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -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 {
diff --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
index 98ad49f25e3f2f..d1d428241ebcc2 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
@@ -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.
}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
index 0692cb92b69440..3c3fed7d43ed98 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
@@ -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
diff --git a/llvm/test/CodeGen/LoongArch/tls-models.ll b/llvm/test/CodeGen/LoongArch/tls-models.ll
index 3994df1da7163f..6b250ec021624a 100644
--- a/llvm/test/CodeGen/LoongArch/tls-models.ll
+++ b/llvm/test/CodeGen/LoongArch/tls-models.ll
@@ -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: ...
[truncated]
|
Hmm, it looks like the target branch is wrong? |
I used the SPR for stack-style submissions for the first time, and according to the documentation, it seems to be correct. |
Ok, I didn't know SPR. Stupid I... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM except a nit.
Created using spr 1.3.4 [skip ci]
Created using spr 1.3.4
Add a test to clang/test/Driver/tls-dialect.c |
Created using spr 1.3.4
Created using spr 1.3.4 [skip ci]
Created using spr 1.3.4 [skip ci]
Created using spr 1.3.4 [skip ci]
The implementation only enables when the
-enable-tlsdesc
option ispassed and the TLS model is
dynamic
.LoongArch's GCC has the same option(-mtls-dialet=) as RISC-V.