diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index fec11c7e716fd..6796b43a15502 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.isLoongArch() || Triple.isRISCV()) { 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 0000000000000..03401ef8af03d --- /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/clang/test/Driver/tls-dialect.c b/clang/test/Driver/tls-dialect.c index a808dd81531ce..3471b55b0ebae 100644 --- a/clang/test/Driver/tls-dialect.c +++ b/clang/test/Driver/tls-dialect.c @@ -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" diff --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp index ad39658f698e7..c136f5b3e515d 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(); + 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().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 285d5c2a63b2d..e5c80644d4a83 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(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 diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h index 4bb6c049f8d75..31b4d65195634 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 6576100d3b321..babb6632471bb 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 958803b52d4ec..a7f6eb9a79ebc 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 98ad49f25e3f2..d1d428241ebcc 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 0692cb92b6944..3c3fed7d43ed9 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 3994df1da7163..6b250ec021624 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: 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 }