Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down
14 changes: 14 additions & 0 deletions clang/test/CodeGen/LoongArch/tls-dialect.c
Original file line number Diff line number Diff line change
@@ -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;
}
5 changes: 5 additions & 0 deletions clang/test/Driver/tls-dialect.c
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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

Expand All @@ -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"
Expand Down
108 changes: 108 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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) {
Expand Down
50 changes: 36 additions & 14 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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>
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}

Expand Down
8 changes: 7 additions & 1 deletion llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading