[llvm] 00786d3 - [LoongArch] Support CodeModel::Large codegen
Weining Lu via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 21 01:42:47 PDT 2023
Author: WANG Xuerui
Date: 2023-06-21T16:41:10+08:00
New Revision: 00786d3a5f229b11a41dcbc4c6081edeaa7ee5b7
URL: https://github.com/llvm/llvm-project/commit/00786d3a5f229b11a41dcbc4c6081edeaa7ee5b7
DIFF: https://github.com/llvm/llvm-project/commit/00786d3a5f229b11a41dcbc4c6081edeaa7ee5b7.diff
LOG: [LoongArch] Support CodeModel::Large codegen
This is intended to behave like GCC's `-mcmodel=extreme`.
Technically the true GCC equivalent would be `-mcmodel=large` which is
not yet implemented there, and we probably do not want to take the
"Large" name until things settle in GCC side, but:
* LLVM does not have a `CodeModel::Extreme`, and it seems too early to
have such a variant added just for enabling LoongArch; and
* `CodeModel::Small` is already being used for GCC `-mcmodel=normal`
which is already a case of divergent naming.
Regarding the codegen, loads/stores immediately after a PC-relative
large address load (that ends with something like `add.d $addr, $addr,
$tmp`) should get merged with the addition into corresponding `ldx/stx`
ops, but is currently not done. This is because pseudo-instructions are
expanded after instruction selection, and is best fixed with a separate
change.
Reviewed By: SixWeining
Differential Revision: https://reviews.llvm.org/D150522
Added:
llvm/test/CodeGen/LoongArch/code-models.ll
Modified:
llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
llvm/lib/Target/LoongArch/LoongArchISelLowering.h
llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
llvm/test/CodeGen/LoongArch/global-address.ll
llvm/test/CodeGen/LoongArch/tls-models.ll
Removed:
llvm/test/CodeGen/LoongArch/codemodel-medium.ll
################################################################################
diff --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
index bad39dc3a14fe..dd0b2cfde544b 100644
--- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
@@ -19,8 +19,11 @@
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/Register.h"
#include "llvm/MC/MCContext.h"
#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
@@ -57,24 +60,39 @@ class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
MachineBasicBlock::iterator &NextMBBI,
unsigned FlagsHi, unsigned SecondOpcode,
unsigned FlagsLo);
+ bool expandLargeAddressLoad(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ MachineBasicBlock::iterator &NextMBBI,
+ unsigned LastOpcode, unsigned IdentifyingMO);
+ bool expandLargeAddressLoad(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ MachineBasicBlock::iterator &NextMBBI,
+ unsigned LastOpcode, unsigned IdentifyingMO,
+ const MachineOperand &Symbol, Register DestReg,
+ bool EraseFromParent);
bool expandLoadAddressPcrel(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
- MachineBasicBlock::iterator &NextMBBI);
+ MachineBasicBlock::iterator &NextMBBI,
+ bool Large = false);
bool expandLoadAddressGot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
- MachineBasicBlock::iterator &NextMBBI);
+ MachineBasicBlock::iterator &NextMBBI,
+ bool Large = false);
bool expandLoadAddressTLSLE(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI);
bool expandLoadAddressTLSIE(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
- MachineBasicBlock::iterator &NextMBBI);
+ MachineBasicBlock::iterator &NextMBBI,
+ bool Large = false);
bool expandLoadAddressTLSLD(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
- MachineBasicBlock::iterator &NextMBBI);
+ MachineBasicBlock::iterator &NextMBBI,
+ bool Large = false);
bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
- MachineBasicBlock::iterator &NextMBBI);
+ MachineBasicBlock::iterator &NextMBBI,
+ bool Large = false);
bool expandFunctionCALL(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI,
@@ -111,16 +129,26 @@ bool LoongArchPreRAExpandPseudo::expandMI(
switch (MBBI->getOpcode()) {
case LoongArch::PseudoLA_PCREL:
return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);
+ case LoongArch::PseudoLA_PCREL_LARGE:
+ return expandLoadAddressPcrel(MBB, MBBI, NextMBBI, /*Large=*/true);
case LoongArch::PseudoLA_GOT:
return expandLoadAddressGot(MBB, MBBI, NextMBBI);
+ case LoongArch::PseudoLA_GOT_LARGE:
+ return expandLoadAddressGot(MBB, MBBI, NextMBBI, /*Large=*/true);
case LoongArch::PseudoLA_TLS_LE:
return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI);
case LoongArch::PseudoLA_TLS_IE:
return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI);
+ case LoongArch::PseudoLA_TLS_IE_LARGE:
+ return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI, /*Large=*/true);
case LoongArch::PseudoLA_TLS_LD:
return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI);
+ case LoongArch::PseudoLA_TLS_LD_LARGE:
+ return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI, /*Large=*/true);
case LoongArch::PseudoLA_TLS_GD:
return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);
+ case LoongArch::PseudoLA_TLS_GD_LARGE:
+ return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI, /*Large=*/true);
case LoongArch::PseudoCALL:
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
case LoongArch::PseudoTAIL:
@@ -157,9 +185,118 @@ bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
return true;
}
+bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+ MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
+ unsigned IdentifyingMO) {
+ MachineInstr &MI = *MBBI;
+ return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO,
+ MI.getOperand(2), MI.getOperand(0).getReg(),
+ true);
+}
+
+bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+ MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,
+ unsigned IdentifyingMO, const MachineOperand &Symbol, Register DestReg,
+ bool EraseFromParent) {
+ // Code Sequence:
+ //
+ // Part1: pcalau12i $scratch, %MO1(sym)
+ // Part0: addi.d $dest, $zero, %MO0(sym)
+ // Part2: lu32i.d $dest, %MO2(sym)
+ // Part3: lu52i.d $dest, $dest, %MO3(sym)
+ // Fin: LastOpcode $dest, $dest, $scratch
+
+ unsigned MO0, MO1, MO2, MO3;
+ switch (IdentifyingMO) {
+ default:
+ llvm_unreachable("unsupported identifying MO");
+ case LoongArchII::MO_PCREL_LO:
+ MO0 = IdentifyingMO;
+ MO1 = LoongArchII::MO_PCREL_HI;
+ MO2 = LoongArchII::MO_PCREL64_LO;
+ MO3 = LoongArchII::MO_PCREL64_HI;
+ break;
+ case LoongArchII::MO_GOT_PC_HI:
+ case LoongArchII::MO_LD_PC_HI:
+ case LoongArchII::MO_GD_PC_HI:
+ // These cases relocate just like the GOT case, except for Part1.
+ MO0 = LoongArchII::MO_GOT_PC_LO;
+ MO1 = IdentifyingMO;
+ MO2 = LoongArchII::MO_GOT_PC64_LO;
+ MO3 = LoongArchII::MO_GOT_PC64_HI;
+ break;
+ case LoongArchII::MO_IE_PC_LO:
+ MO0 = IdentifyingMO;
+ MO1 = LoongArchII::MO_IE_PC_HI;
+ MO2 = LoongArchII::MO_IE_PC64_LO;
+ MO3 = LoongArchII::MO_IE_PC64_HI;
+ break;
+ }
+
+ MachineFunction *MF = MBB.getParent();
+ MachineInstr &MI = *MBBI;
+ DebugLoc DL = MI.getDebugLoc();
+
+ assert(MF->getSubtarget<LoongArchSubtarget>().is64Bit() &&
+ "Large code model requires LA64");
+
+ Register TmpPart1 =
+ MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
+ Register TmpPart0 =
+ DestReg.isVirtual()
+ ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
+ : DestReg;
+ Register TmpParts02 =
+ DestReg.isVirtual()
+ ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
+ : DestReg;
+ Register TmpParts023 =
+ DestReg.isVirtual()
+ ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
+ : DestReg;
+
+ auto Part1 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), TmpPart1);
+ auto Part0 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), TmpPart0)
+ .addReg(LoongArch::R0);
+ auto Part2 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), TmpParts02)
+ // "rj" is needed due to InstrInfo pattern requirement.
+ .addReg(TmpPart0, RegState::Kill);
+ auto Part3 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), TmpParts023)
+ .addReg(TmpParts02, RegState::Kill);
+ BuildMI(MBB, MBBI, DL, TII->get(LastOpcode), DestReg)
+ .addReg(TmpParts023)
+ .addReg(TmpPart1, RegState::Kill);
+
+ if (Symbol.getType() == MachineOperand::MO_ExternalSymbol) {
+ const char *SymName = Symbol.getSymbolName();
+ Part0.addExternalSymbol(SymName, MO0);
+ Part1.addExternalSymbol(SymName, MO1);
+ Part2.addExternalSymbol(SymName, MO2);
+ Part3.addExternalSymbol(SymName, MO3);
+ } else {
+ Part0.addDisp(Symbol, 0, MO0);
+ Part1.addDisp(Symbol, 0, MO1);
+ Part2.addDisp(Symbol, 0, MO2);
+ Part3.addDisp(Symbol, 0, MO3);
+ }
+
+ if (EraseFromParent)
+ MI.eraseFromParent();
+
+ return true;
+}
+
bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
- MachineBasicBlock::iterator &NextMBBI) {
+ MachineBasicBlock::iterator &NextMBBI, bool Large) {
+ if (Large)
+ // Emit the 5-insn large address load sequence with the `%pc` family of
+ // relocs.
+ return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
+ LoongArchII::MO_PCREL_LO);
+
// Code Sequence:
// pcalau12i $rd, %pc_hi20(sym)
// addi.w/d $rd, $rd, %pc_lo12(sym)
@@ -172,7 +309,13 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
- MachineBasicBlock::iterator &NextMBBI) {
+ MachineBasicBlock::iterator &NextMBBI, bool Large) {
+ if (Large)
+ // Emit the 5-insn large address load sequence with the `%got_pc` family
+ // of relocs, loading the result from GOT with `ldx.d` in the end.
+ return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
+ LoongArchII::MO_GOT_PC_HI);
+
// Code Sequence:
// pcalau12i $rd, %got_pc_hi20(sym)
// ld.w/d $rd, $rd, %got_pc_lo12(sym)
@@ -189,29 +332,57 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
// Code Sequence:
// lu12i.w $rd, %le_hi20(sym)
// ori $rd, $rd, %le_lo12(sym)
+ //
+ // And additionally if generating code using the large code model:
+ //
+ // lu32i.d $rd, %le64_lo20(sym)
+ // lu52i.d $rd, $rd, %le64_hi12(sym)
MachineFunction *MF = MBB.getParent();
MachineInstr &MI = *MBBI;
DebugLoc DL = MI.getDebugLoc();
+ bool Large = MF->getTarget().getCodeModel() == CodeModel::Large;
Register DestReg = MI.getOperand(0).getReg();
- Register ScratchReg =
+ Register Parts01 =
+ Large ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
+ : DestReg;
+ Register Part1 =
MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
MachineOperand &Symbol = MI.getOperand(1);
- BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), ScratchReg)
+ BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1)
.addDisp(Symbol, 0, LoongArchII::MO_LE_HI);
- BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), DestReg)
- .addReg(ScratchReg)
+ BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01)
+ .addReg(Part1, RegState::Kill)
.addDisp(Symbol, 0, LoongArchII::MO_LE_LO);
+ if (Large) {
+ Register Parts012 =
+ MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
+
+ BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Parts012)
+ // "rj" is needed due to InstrInfo pattern requirement.
+ .addReg(Parts01, RegState::Kill)
+ .addDisp(Symbol, 0, LoongArchII::MO_LE64_LO);
+ BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), DestReg)
+ .addReg(Parts012, RegState::Kill)
+ .addDisp(Symbol, 0, LoongArchII::MO_LE64_HI);
+ }
+
MI.eraseFromParent();
return true;
}
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
- MachineBasicBlock::iterator &NextMBBI) {
+ MachineBasicBlock::iterator &NextMBBI, bool Large) {
+ if (Large)
+ // Emit the 5-insn large address load sequence with the `%ie_pc` family
+ // of relocs, loading the result with `ldx.d` in the end.
+ return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,
+ LoongArchII::MO_IE_PC_LO);
+
// Code Sequence:
// pcalau12i $rd, %ie_pc_hi20(sym)
// ld.w/d $rd, $rd, %ie_pc_lo12(sym)
@@ -224,7 +395,13 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
- MachineBasicBlock::iterator &NextMBBI) {
+ MachineBasicBlock::iterator &NextMBBI, bool Large) {
+ if (Large)
+ // Emit the 5-insn large address load sequence with the `%got_pc` family
+ // of relocs, with the `pcalau12i` insn relocated with `%ld_pc_hi20`.
+ return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
+ LoongArchII::MO_LD_PC_HI);
+
// Code Sequence:
// pcalau12i $rd, %ld_pc_hi20(sym)
// addi.w/d $rd, $rd, %got_pc_lo12(sym)
@@ -237,7 +414,13 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
- MachineBasicBlock::iterator &NextMBBI) {
+ MachineBasicBlock::iterator &NextMBBI, bool Large) {
+ if (Large)
+ // Emit the 5-insn large address load sequence with the `%got_pc` family
+ // of relocs, with the `pcalau12i` insn relocated with `%gd_pc_hi20`.
+ return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,
+ LoongArchII::MO_GD_PC_HI);
+
// Code Sequence:
// pcalau12i $rd, %gd_pc_hi20(sym)
// addi.w/d $rd, $rd, %got_pc_lo12(sym)
@@ -299,6 +482,25 @@ bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
CALL.addGlobalAddress(GV, 0, LoongArchII::MO_PCREL_LO);
break;
}
+ case CodeModel::Large: {
+ // Emit the 5-insn large address load sequence, either directly or
+ // indirectly in case of going through the GOT, then JIRL_TAIL or
+ // JIRL_CALL to $addr.
+ Opcode =
+ IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
+ Register AddrReg =
+ IsTailCall
+ ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)
+ : LoongArch::R1;
+
+ bool UseGOT = Func.isGlobal() && !Func.getGlobal()->isDSOLocal();
+ unsigned MO = UseGOT ? LoongArchII::MO_GOT_PC_HI : LoongArchII::MO_PCREL_LO;
+ unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D;
+ expandLargeAddressLoad(MBB, MBBI, NextMBBI, LAOpcode, MO, Func, AddrReg,
+ false);
+ CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(AddrReg).addImm(0);
+ break;
+ }
}
// Transfer implicit operands.
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 74a16bf3f8208..57d870ed29753 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -22,9 +22,12 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/RuntimeLibcalls.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/IntrinsicsLoongArch.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/MathExtras.h"
@@ -467,16 +470,44 @@ SDValue LoongArchTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
SDLoc DL(N);
EVT Ty = getPointerTy(DAG.getDataLayout());
SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
- // TODO: Check CodeModel.
- if (IsLocal)
- // This generates the pattern (PseudoLA_PCREL sym), which expands to
- // (addi.w/d (pcalau12i %pc_hi20(sym)) %pc_lo12(sym)).
- return SDValue(DAG.getMachineNode(LoongArch::PseudoLA_PCREL, DL, Ty, Addr),
- 0);
- // This generates the pattern (PseudoLA_GOT sym), which expands to (ld.w/d
- // (pcalau12i %got_pc_hi20(sym)) %got_pc_lo12(sym)).
- return SDValue(DAG.getMachineNode(LoongArch::PseudoLA_GOT, DL, Ty, Addr), 0);
+ switch (DAG.getTarget().getCodeModel()) {
+ default:
+ report_fatal_error("Unsupported code model");
+
+ case CodeModel::Large: {
+ assert(Subtarget.is64Bit() && "Large code model requires LA64");
+
+ // This is not actually used, but is necessary for successfully matching
+ // the PseudoLA_*_LARGE nodes.
+ SDValue Tmp = DAG.getConstant(0, DL, Ty);
+ if (IsLocal)
+ // This generates the pattern (PseudoLA_PCREL_LARGE tmp sym), that
+ // eventually becomes the desired 5-insn code sequence.
+ return SDValue(DAG.getMachineNode(LoongArch::PseudoLA_PCREL_LARGE, DL, Ty,
+ Tmp, Addr),
+ 0);
+
+ // This generates the pattern (PseudoLA_GOT_LARGE tmp sym), that eventually
+ // becomes the desired 5-insn code sequence.
+ return SDValue(
+ DAG.getMachineNode(LoongArch::PseudoLA_GOT_LARGE, DL, Ty, Tmp, Addr),
+ 0);
+ }
+
+ case CodeModel::Small:
+ case CodeModel::Medium:
+ if (IsLocal)
+ // This generates the pattern (PseudoLA_PCREL sym), which expands to
+ // (addi.w/d (pcalau12i %pc_hi20(sym)) %pc_lo12(sym)).
+ return SDValue(
+ DAG.getMachineNode(LoongArch::PseudoLA_PCREL, DL, Ty, Addr), 0);
+
+ // This generates the pattern (PseudoLA_GOT sym), which expands to (ld.w/d
+ // (pcalau12i %got_pc_hi20(sym)) %got_pc_lo12(sym)).
+ return SDValue(DAG.getMachineNode(LoongArch::PseudoLA_GOT, DL, Ty, Addr),
+ 0);
+ }
}
SDValue LoongArchTargetLowering::lowerBlockAddress(SDValue Op,
@@ -503,13 +534,19 @@ SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op,
SDValue LoongArchTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N,
SelectionDAG &DAG,
- unsigned Opc) const {
+ unsigned Opc,
+ bool Large) const {
SDLoc DL(N);
EVT Ty = getPointerTy(DAG.getDataLayout());
MVT GRLenVT = Subtarget.getGRLenVT();
+ // This is not actually used, but is necessary for successfully matching the
+ // PseudoLA_*_LARGE nodes.
+ SDValue Tmp = DAG.getConstant(0, DL, Ty);
SDValue Addr = DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, 0);
- SDValue Offset = SDValue(DAG.getMachineNode(Opc, DL, Ty, Addr), 0);
+ SDValue Offset = Large
+ ? SDValue(DAG.getMachineNode(Opc, DL, Ty, Tmp, Addr), 0)
+ : SDValue(DAG.getMachineNode(Opc, DL, Ty, Addr), 0);
// Add the thread pointer.
return DAG.getNode(ISD::ADD, DL, Ty, Offset,
@@ -518,14 +555,20 @@ SDValue LoongArchTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N,
SDValue LoongArchTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N,
SelectionDAG &DAG,
- unsigned Opc) const {
+ unsigned Opc,
+ bool Large) const {
SDLoc DL(N);
EVT Ty = getPointerTy(DAG.getDataLayout());
IntegerType *CallTy = Type::getIntNTy(*DAG.getContext(), Ty.getSizeInBits());
+ // 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 dynamic GOT address.
SDValue Addr = DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, 0);
- SDValue Load = SDValue(DAG.getMachineNode(Opc, DL, Ty, Addr), 0);
+ SDValue Load = Large ? SDValue(DAG.getMachineNode(Opc, DL, Ty, Tmp, Addr), 0)
+ : SDValue(DAG.getMachineNode(Opc, DL, Ty, Addr), 0);
// Prepare argument list to generate call.
ArgListTy Args;
@@ -552,6 +595,9 @@ LoongArchTargetLowering::lowerGlobalTLSAddress(SDValue Op,
CallingConv::GHC)
report_fatal_error("In GHC calling convention TLS is not supported");
+ bool Large = DAG.getTarget().getCodeModel() == CodeModel::Large;
+ assert((!Large || Subtarget.is64Bit()) && "Large code model requires LA64");
+
GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
assert(N->getOffset() == 0 && "unexpected offset in global node");
@@ -561,20 +607,31 @@ LoongArchTargetLowering::lowerGlobalTLSAddress(SDValue Op,
// 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, LoongArch::PseudoLA_TLS_GD);
+ Addr = 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, LoongArch::PseudoLA_TLS_LD);
+ Addr = 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, LoongArch::PseudoLA_TLS_IE);
+ Addr = 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;
}
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index dab8944c50a78..3fae3d5669187 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -230,9 +230,9 @@ class LoongArchTargetLowering : public TargetLowering {
template <class NodeTy>
SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const;
SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
- unsigned Opc) const;
+ unsigned Opc, bool Large = false) const;
SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
- unsigned Opc) const;
+ 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 a7c5e4d918477..f5e32c452933b 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
@@ -478,12 +478,20 @@ LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
{MO_CALL_PLT, "loongarch-call-plt"},
{MO_PCREL_HI, "loongarch-pcrel-hi"},
{MO_PCREL_LO, "loongarch-pcrel-lo"},
+ {MO_PCREL64_LO, "loongarch-pcrel64-lo"},
+ {MO_PCREL64_HI, "loongarch-pcrel64-hi"},
{MO_GOT_PC_HI, "loongarch-got-pc-hi"},
{MO_GOT_PC_LO, "loongarch-got-pc-lo"},
+ {MO_GOT_PC64_LO, "loongarch-got-pc64-lo"},
+ {MO_GOT_PC64_HI, "loongarch-got-pc64-hi"},
{MO_LE_HI, "loongarch-le-hi"},
{MO_LE_LO, "loongarch-le-lo"},
+ {MO_LE64_LO, "loongarch-le64-lo"},
+ {MO_LE64_HI, "loongarch-le64-hi"},
{MO_IE_PC_HI, "loongarch-ie-pc-hi"},
{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_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/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
index 64f08e2603812..5daa9481c9072 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
@@ -47,24 +47,48 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
case LoongArchII::MO_PCREL_LO:
Kind = LoongArchMCExpr::VK_LoongArch_PCALA_LO12;
break;
+ case LoongArchII::MO_PCREL64_LO:
+ Kind = LoongArchMCExpr::VK_LoongArch_PCALA64_LO20;
+ break;
+ case LoongArchII::MO_PCREL64_HI:
+ Kind = LoongArchMCExpr::VK_LoongArch_PCALA64_HI12;
+ break;
case LoongArchII::MO_GOT_PC_HI:
Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20;
break;
case LoongArchII::MO_GOT_PC_LO:
Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12;
break;
+ case LoongArchII::MO_GOT_PC64_LO:
+ Kind = LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20;
+ break;
+ case LoongArchII::MO_GOT_PC64_HI:
+ Kind = LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12;
+ break;
case LoongArchII::MO_LE_HI:
Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20;
break;
case LoongArchII::MO_LE_LO:
Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12;
break;
+ case LoongArchII::MO_LE64_LO:
+ Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20;
+ break;
+ case LoongArchII::MO_LE64_HI:
+ Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12;
+ break;
case LoongArchII::MO_IE_PC_HI:
Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20;
break;
case LoongArchII::MO_IE_PC_LO:
Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
break;
+ case LoongArchII::MO_IE_PC64_LO:
+ Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20;
+ break;
+ case LoongArchII::MO_IE_PC64_HI:
+ Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12;
+ break;
case LoongArchII::MO_LD_PC_HI:
Kind = LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20;
break;
diff --git a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
index da294fcb980e1..46e4a06f6bc01 100644
--- a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
@@ -21,6 +21,7 @@
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/Transforms/Scalar.h"
#include <optional>
@@ -54,13 +55,33 @@ static Reloc::Model getEffectiveRelocModel(const Triple &TT,
return RM.value_or(Reloc::Static);
}
+static CodeModel::Model
+getEffectiveLoongArchCodeModel(const Triple &TT,
+ std::optional<CodeModel::Model> CM) {
+ if (!CM)
+ return CodeModel::Small;
+
+ switch (*CM) {
+ case CodeModel::Small:
+ case CodeModel::Medium:
+ return *CM;
+ case CodeModel::Large:
+ if (!TT.isArch64Bit())
+ report_fatal_error("Large code model requires LA64");
+ return *CM;
+ default:
+ report_fatal_error(
+ "Only small, medium and large code models are allowed on LoongArch");
+ }
+}
+
LoongArchTargetMachine::LoongArchTargetMachine(
const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
const TargetOptions &Options, std::optional<Reloc::Model> RM,
std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
: LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
getEffectiveRelocModel(TT, RM),
- getEffectiveCodeModel(CM, CodeModel::Small), OL),
+ getEffectiveLoongArchCodeModel(TT, CM), OL),
TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
initAsmInfo();
}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
index cdbd1f5699dfd..4ba7858ecc363 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
@@ -31,12 +31,20 @@ enum {
MO_CALL_PLT,
MO_PCREL_HI,
MO_PCREL_LO,
+ MO_PCREL64_LO,
+ MO_PCREL64_HI,
MO_GOT_PC_HI,
MO_GOT_PC_LO,
+ MO_GOT_PC64_LO,
+ MO_GOT_PC64_HI,
MO_LE_HI,
MO_LE_LO,
+ MO_LE64_LO,
+ MO_LE64_HI,
MO_IE_PC_HI,
MO_IE_PC_LO,
+ MO_IE_PC64_LO,
+ MO_IE_PC64_HI,
MO_LD_PC_HI,
MO_GD_PC_HI,
// TODO: Add more flags.
diff --git a/llvm/test/CodeGen/LoongArch/codemodel-medium.ll b/llvm/test/CodeGen/LoongArch/code-models.ll
similarity index 61%
rename from llvm/test/CodeGen/LoongArch/codemodel-medium.ll
rename to llvm/test/CodeGen/LoongArch/code-models.ll
index d4d97e7df804d..c610f645a06ae 100644
--- a/llvm/test/CodeGen/LoongArch/codemodel-medium.ll
+++ b/llvm/test/CodeGen/LoongArch/code-models.ll
@@ -3,6 +3,8 @@
; RUN: FileCheck --check-prefix=SMALL %s
; RUN: llc --mtriple=loongarch64 --code-model=medium < %s | \
; RUN: FileCheck --check-prefix=MEDIUM %s
+; RUN: llc --mtriple=loongarch64 --code-model=large < %s | \
+; RUN: FileCheck --check-prefix=LARGE %s
declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)
declare i32 @callee(i32)
@@ -26,6 +28,20 @@ define i32 @call_globaladdress(i32 %a) nounwind {
; MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; MEDIUM-NEXT: addi.d $sp, $sp, 16
; MEDIUM-NEXT: ret
+;
+; LARGE-LABEL: call_globaladdress:
+; LARGE: # %bb.0:
+; LARGE-NEXT: addi.d $sp, $sp, -16
+; LARGE-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LARGE-NEXT: pcalau12i $a1, %got_pc_hi20(callee)
+; LARGE-NEXT: addi.d $ra, $zero, %got_pc_lo12(callee)
+; LARGE-NEXT: lu32i.d $ra, %got64_pc_lo20(callee)
+; LARGE-NEXT: lu52i.d $ra, $ra, %got64_pc_hi12(callee)
+; LARGE-NEXT: ldx.d $ra, $ra, $a1
+; LARGE-NEXT: jirl $ra, $ra, 0
+; LARGE-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LARGE-NEXT: addi.d $sp, $sp, 16
+; LARGE-NEXT: ret
%1 = call i32 @callee(i32 %a)
ret i32 %1
}
@@ -57,6 +73,24 @@ define void @call_external_sym(ptr %dst) {
; MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; MEDIUM-NEXT: addi.d $sp, $sp, 16
; MEDIUM-NEXT: ret
+;
+; LARGE-LABEL: call_external_sym:
+; LARGE: # %bb.0: # %entry
+; LARGE-NEXT: addi.d $sp, $sp, -16
+; LARGE-NEXT: .cfi_def_cfa_offset 16
+; LARGE-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LARGE-NEXT: .cfi_offset 1, -8
+; LARGE-NEXT: ori $a2, $zero, 1000
+; LARGE-NEXT: move $a1, $zero
+; LARGE-NEXT: pcalau12i $a3, %pc_hi20(memset)
+; LARGE-NEXT: addi.d $ra, $zero, %pc_lo12(memset)
+; LARGE-NEXT: lu32i.d $ra, %pc64_lo20(memset)
+; LARGE-NEXT: lu52i.d $ra, $ra, %pc64_hi12(memset)
+; LARGE-NEXT: add.d $ra, $ra, $a3
+; LARGE-NEXT: jirl $ra, $ra, 0
+; LARGE-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LARGE-NEXT: addi.d $sp, $sp, 16
+; LARGE-NEXT: ret
entry:
call void @llvm.memset.p0.i64(ptr %dst, i8 0, i64 1000, i1 false)
ret void
@@ -73,6 +107,15 @@ define i32 @caller_tail(i32 %i) nounwind {
; MEDIUM: # %bb.0: # %entry
; MEDIUM-NEXT: pcalau12i $a1, %pc_hi20(callee_tail)
; MEDIUM-NEXT: jirl $zero, $a1, %pc_lo12(callee_tail)
+;
+; LARGE-LABEL: caller_tail:
+; LARGE: # %bb.0: # %entry
+; LARGE-NEXT: pcalau12i $a1, %got_pc_hi20(callee_tail)
+; LARGE-NEXT: addi.d $a2, $zero, %got_pc_lo12(callee_tail)
+; LARGE-NEXT: lu32i.d $a2, %got64_pc_lo20(callee_tail)
+; LARGE-NEXT: lu52i.d $a2, $a2, %got64_pc_hi12(callee_tail)
+; LARGE-NEXT: ldx.d $a1, $a2, $a1
+; LARGE-NEXT: jr $a1
entry:
%r = tail call i32 @callee_tail(i32 %i)
ret i32 %r
diff --git a/llvm/test/CodeGen/LoongArch/global-address.ll b/llvm/test/CodeGen/LoongArch/global-address.ll
index 258c4e8691567..a8f0ef648aa7c 100644
--- a/llvm/test/CodeGen/LoongArch/global-address.ll
+++ b/llvm/test/CodeGen/LoongArch/global-address.ll
@@ -3,6 +3,8 @@
; RUN: llc --mtriple=loongarch32 --relocation-model=pic < %s | FileCheck %s --check-prefix=LA32PIC
; RUN: llc --mtriple=loongarch64 --relocation-model=static < %s | FileCheck %s --check-prefix=LA64NOPIC
; RUN: llc --mtriple=loongarch64 --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64PIC
+; RUN: llc --mtriple=loongarch64 --code-model=large --relocation-model=static < %s | FileCheck %s --check-prefix=LA64LARGENOPIC
+; RUN: llc --mtriple=loongarch64 --code-model=large --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64LARGEPIC
@g = dso_local global i32 zeroinitializer, align 4
@G = global i32 zeroinitializer, align 4
@@ -47,6 +49,38 @@ define void @foo() nounwind {
; LA64PIC-NEXT: addi.d $a0, $a0, %pc_lo12(.Lg$local)
; LA64PIC-NEXT: ld.w $a0, $a0, 0
; LA64PIC-NEXT: ret
+;
+; LA64LARGENOPIC-LABEL: foo:
+; LA64LARGENOPIC: # %bb.0:
+; LA64LARGENOPIC-NEXT: pcalau12i $a0, %got_pc_hi20(G)
+; LA64LARGENOPIC-NEXT: addi.d $a1, $zero, %got_pc_lo12(G)
+; LA64LARGENOPIC-NEXT: lu32i.d $a1, %got64_pc_lo20(G)
+; LA64LARGENOPIC-NEXT: lu52i.d $a1, $a1, %got64_pc_hi12(G)
+; LA64LARGENOPIC-NEXT: ldx.d $a0, $a1, $a0
+; LA64LARGENOPIC-NEXT: ld.w $a0, $a0, 0
+; LA64LARGENOPIC-NEXT: pcalau12i $a0, %pc_hi20(g)
+; LA64LARGENOPIC-NEXT: addi.d $a1, $zero, %pc_lo12(g)
+; LA64LARGENOPIC-NEXT: lu32i.d $a1, %pc64_lo20(g)
+; LA64LARGENOPIC-NEXT: lu52i.d $a1, $a1, %pc64_hi12(g)
+; LA64LARGENOPIC-NEXT: add.d $a0, $a1, $a0
+; LA64LARGENOPIC-NEXT: ld.w $a0, $a0, 0
+; LA64LARGENOPIC-NEXT: ret
+;
+; LA64LARGEPIC-LABEL: foo:
+; LA64LARGEPIC: # %bb.0:
+; LA64LARGEPIC-NEXT: pcalau12i $a0, %got_pc_hi20(G)
+; LA64LARGEPIC-NEXT: addi.d $a1, $zero, %got_pc_lo12(G)
+; LA64LARGEPIC-NEXT: lu32i.d $a1, %got64_pc_lo20(G)
+; LA64LARGEPIC-NEXT: lu52i.d $a1, $a1, %got64_pc_hi12(G)
+; LA64LARGEPIC-NEXT: ldx.d $a0, $a1, $a0
+; LA64LARGEPIC-NEXT: ld.w $a0, $a0, 0
+; LA64LARGEPIC-NEXT: pcalau12i $a0, %pc_hi20(.Lg$local)
+; LA64LARGEPIC-NEXT: addi.d $a1, $zero, %pc_lo12(.Lg$local)
+; LA64LARGEPIC-NEXT: lu32i.d $a1, %pc64_lo20(.Lg$local)
+; LA64LARGEPIC-NEXT: lu52i.d $a1, $a1, %pc64_hi12(.Lg$local)
+; LA64LARGEPIC-NEXT: add.d $a0, $a1, $a0
+; LA64LARGEPIC-NEXT: ld.w $a0, $a0, 0
+; LA64LARGEPIC-NEXT: ret
%V = load volatile i32, ptr @G
%v = load volatile i32, ptr @g
ret void
diff --git a/llvm/test/CodeGen/LoongArch/tls-models.ll b/llvm/test/CodeGen/LoongArch/tls-models.ll
index d973cd45da012..a2a3792a6a54b 100644
--- a/llvm/test/CodeGen/LoongArch/tls-models.ll
+++ b/llvm/test/CodeGen/LoongArch/tls-models.ll
@@ -1,8 +1,10 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc --mtriple=loongarch32 --relocation-model=pic < %s | FileCheck %s --check-prefix=LA32PIC
; RUN: llc --mtriple=loongarch64 --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64PIC
+; RUN: llc --mtriple=loongarch64 --code-model=large --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64LARGEPIC
; 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
;; 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
@@ -38,6 +40,25 @@ define ptr @f1() nounwind {
; LA64PIC-NEXT: addi.d $sp, $sp, 16
; LA64PIC-NEXT: ret
;
+; LA64LARGEPIC-LABEL: f1:
+; LA64LARGEPIC: # %bb.0: # %entry
+; LA64LARGEPIC-NEXT: addi.d $sp, $sp, -16
+; LA64LARGEPIC-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64LARGEPIC-NEXT: pcalau12i $a0, %gd_pc_hi20(unspecified)
+; LA64LARGEPIC-NEXT: addi.d $a1, $zero, %got_pc_lo12(unspecified)
+; LA64LARGEPIC-NEXT: lu32i.d $a1, %got64_pc_lo20(unspecified)
+; LA64LARGEPIC-NEXT: lu52i.d $a1, $a1, %got64_pc_hi12(unspecified)
+; LA64LARGEPIC-NEXT: add.d $a0, $a1, $a0
+; LA64LARGEPIC-NEXT: pcalau12i $a1, %pc_hi20(__tls_get_addr)
+; LA64LARGEPIC-NEXT: addi.d $ra, $zero, %pc_lo12(__tls_get_addr)
+; LA64LARGEPIC-NEXT: lu32i.d $ra, %pc64_lo20(__tls_get_addr)
+; LA64LARGEPIC-NEXT: lu52i.d $ra, $ra, %pc64_hi12(__tls_get_addr)
+; LA64LARGEPIC-NEXT: add.d $ra, $ra, $a1
+; LA64LARGEPIC-NEXT: jirl $ra, $ra, 0
+; LA64LARGEPIC-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64LARGEPIC-NEXT: addi.d $sp, $sp, 16
+; LA64LARGEPIC-NEXT: ret
+;
; LA32NOPIC-LABEL: f1:
; LA32NOPIC: # %bb.0: # %entry
; LA32NOPIC-NEXT: pcalau12i $a0, %ie_pc_hi20(unspecified)
@@ -51,6 +72,16 @@ define ptr @f1() nounwind {
; LA64NOPIC-NEXT: ld.d $a0, $a0, %ie_pc_lo12(unspecified)
; LA64NOPIC-NEXT: add.d $a0, $a0, $tp
; LA64NOPIC-NEXT: ret
+;
+; LA64LARGENOPIC-LABEL: f1:
+; LA64LARGENOPIC: # %bb.0: # %entry
+; LA64LARGENOPIC-NEXT: pcalau12i $a0, %ie_pc_hi20(unspecified)
+; LA64LARGENOPIC-NEXT: addi.d $a1, $zero, %ie_pc_lo12(unspecified)
+; LA64LARGENOPIC-NEXT: lu32i.d $a1, %ie64_pc_lo20(unspecified)
+; LA64LARGENOPIC-NEXT: lu52i.d $a1, $a1, %ie64_pc_hi12(unspecified)
+; LA64LARGENOPIC-NEXT: ldx.d $a0, $a1, $a0
+; LA64LARGENOPIC-NEXT: add.d $a0, $a0, $tp
+; LA64LARGENOPIC-NEXT: ret
entry:
ret ptr @unspecified
}
@@ -80,6 +111,25 @@ define ptr @f2() nounwind {
; LA64PIC-NEXT: addi.d $sp, $sp, 16
; LA64PIC-NEXT: ret
;
+; LA64LARGEPIC-LABEL: f2:
+; LA64LARGEPIC: # %bb.0: # %entry
+; LA64LARGEPIC-NEXT: addi.d $sp, $sp, -16
+; LA64LARGEPIC-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64LARGEPIC-NEXT: pcalau12i $a0, %ld_pc_hi20(ld)
+; LA64LARGEPIC-NEXT: addi.d $a1, $zero, %got_pc_lo12(ld)
+; LA64LARGEPIC-NEXT: lu32i.d $a1, %got64_pc_lo20(ld)
+; LA64LARGEPIC-NEXT: lu52i.d $a1, $a1, %got64_pc_hi12(ld)
+; LA64LARGEPIC-NEXT: add.d $a0, $a1, $a0
+; LA64LARGEPIC-NEXT: pcalau12i $a1, %pc_hi20(__tls_get_addr)
+; LA64LARGEPIC-NEXT: addi.d $ra, $zero, %pc_lo12(__tls_get_addr)
+; LA64LARGEPIC-NEXT: lu32i.d $ra, %pc64_lo20(__tls_get_addr)
+; LA64LARGEPIC-NEXT: lu52i.d $ra, $ra, %pc64_hi12(__tls_get_addr)
+; LA64LARGEPIC-NEXT: add.d $ra, $ra, $a1
+; LA64LARGEPIC-NEXT: jirl $ra, $ra, 0
+; LA64LARGEPIC-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64LARGEPIC-NEXT: addi.d $sp, $sp, 16
+; LA64LARGEPIC-NEXT: ret
+;
; LA32NOPIC-LABEL: f2:
; LA32NOPIC: # %bb.0: # %entry
; LA32NOPIC-NEXT: pcalau12i $a0, %ie_pc_hi20(ld)
@@ -93,6 +143,16 @@ define ptr @f2() nounwind {
; LA64NOPIC-NEXT: ld.d $a0, $a0, %ie_pc_lo12(ld)
; LA64NOPIC-NEXT: add.d $a0, $a0, $tp
; LA64NOPIC-NEXT: ret
+;
+; LA64LARGENOPIC-LABEL: f2:
+; LA64LARGENOPIC: # %bb.0: # %entry
+; LA64LARGENOPIC-NEXT: pcalau12i $a0, %ie_pc_hi20(ld)
+; LA64LARGENOPIC-NEXT: addi.d $a1, $zero, %ie_pc_lo12(ld)
+; LA64LARGENOPIC-NEXT: lu32i.d $a1, %ie64_pc_lo20(ld)
+; LA64LARGENOPIC-NEXT: lu52i.d $a1, $a1, %ie64_pc_hi12(ld)
+; LA64LARGENOPIC-NEXT: ldx.d $a0, $a1, $a0
+; LA64LARGENOPIC-NEXT: add.d $a0, $a0, $tp
+; LA64LARGENOPIC-NEXT: ret
entry:
ret ptr @ld
}
@@ -114,6 +174,16 @@ define ptr @f3() nounwind {
; LA64PIC-NEXT: add.d $a0, $a0, $tp
; LA64PIC-NEXT: ret
;
+; LA64LARGEPIC-LABEL: f3:
+; LA64LARGEPIC: # %bb.0: # %entry
+; LA64LARGEPIC-NEXT: pcalau12i $a0, %ie_pc_hi20(ie)
+; LA64LARGEPIC-NEXT: addi.d $a1, $zero, %ie_pc_lo12(ie)
+; LA64LARGEPIC-NEXT: lu32i.d $a1, %ie64_pc_lo20(ie)
+; LA64LARGEPIC-NEXT: lu52i.d $a1, $a1, %ie64_pc_hi12(ie)
+; LA64LARGEPIC-NEXT: ldx.d $a0, $a1, $a0
+; LA64LARGEPIC-NEXT: add.d $a0, $a0, $tp
+; LA64LARGEPIC-NEXT: ret
+;
; LA32NOPIC-LABEL: f3:
; LA32NOPIC: # %bb.0: # %entry
; LA32NOPIC-NEXT: pcalau12i $a0, %ie_pc_hi20(ie)
@@ -127,6 +197,16 @@ define ptr @f3() nounwind {
; LA64NOPIC-NEXT: ld.d $a0, $a0, %ie_pc_lo12(ie)
; LA64NOPIC-NEXT: add.d $a0, $a0, $tp
; LA64NOPIC-NEXT: ret
+;
+; LA64LARGENOPIC-LABEL: f3:
+; LA64LARGENOPIC: # %bb.0: # %entry
+; LA64LARGENOPIC-NEXT: pcalau12i $a0, %ie_pc_hi20(ie)
+; LA64LARGENOPIC-NEXT: addi.d $a1, $zero, %ie_pc_lo12(ie)
+; LA64LARGENOPIC-NEXT: lu32i.d $a1, %ie64_pc_lo20(ie)
+; LA64LARGENOPIC-NEXT: lu52i.d $a1, $a1, %ie64_pc_hi12(ie)
+; LA64LARGENOPIC-NEXT: ldx.d $a0, $a1, $a0
+; LA64LARGENOPIC-NEXT: add.d $a0, $a0, $tp
+; LA64LARGENOPIC-NEXT: ret
entry:
ret ptr @ie
}
@@ -148,6 +228,15 @@ define ptr @f4() nounwind {
; LA64PIC-NEXT: add.d $a0, $a0, $tp
; LA64PIC-NEXT: ret
;
+; LA64LARGEPIC-LABEL: f4:
+; LA64LARGEPIC: # %bb.0: # %entry
+; LA64LARGEPIC-NEXT: lu12i.w $a0, %le_hi20(le)
+; LA64LARGEPIC-NEXT: ori $a0, $a0, %le_lo12(le)
+; LA64LARGEPIC-NEXT: lu32i.d $a0, %le64_lo20(le)
+; LA64LARGEPIC-NEXT: lu52i.d $a0, $a0, %le64_hi12(le)
+; LA64LARGEPIC-NEXT: add.d $a0, $a0, $tp
+; LA64LARGEPIC-NEXT: ret
+;
; LA32NOPIC-LABEL: f4:
; LA32NOPIC: # %bb.0: # %entry
; LA32NOPIC-NEXT: lu12i.w $a0, %le_hi20(le)
@@ -161,6 +250,15 @@ define ptr @f4() nounwind {
; LA64NOPIC-NEXT: ori $a0, $a0, %le_lo12(le)
; LA64NOPIC-NEXT: add.d $a0, $a0, $tp
; LA64NOPIC-NEXT: ret
+;
+; LA64LARGENOPIC-LABEL: f4:
+; LA64LARGENOPIC: # %bb.0: # %entry
+; LA64LARGENOPIC-NEXT: lu12i.w $a0, %le_hi20(le)
+; LA64LARGENOPIC-NEXT: ori $a0, $a0, %le_lo12(le)
+; LA64LARGENOPIC-NEXT: lu32i.d $a0, %le64_lo20(le)
+; LA64LARGENOPIC-NEXT: lu52i.d $a0, $a0, %le64_hi12(le)
+; LA64LARGENOPIC-NEXT: add.d $a0, $a0, $tp
+; LA64LARGENOPIC-NEXT: ret
entry:
ret ptr @le
}
More information about the llvm-commits
mailing list