diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp @@ -176,7 +176,10 @@ } unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { - if (MI.getOpcode() == TargetOpcode::INLINEASM) { + unsigned Opcode = MI.getOpcode(); + + if (Opcode == TargetOpcode::INLINEASM || + Opcode == TargetOpcode::INLINEASM_BR) { const MachineFunction *MF = MI.getParent()->getParent(); const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo(); return getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI); diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -1159,6 +1159,7 @@ let mayLoad = 1; let mayStore = 1; let hasSideEffects = 0; + let Size = 36; } def PseudoMaskedAtomicSwap32 : PseudoMaskedAM; @@ -1172,6 +1173,7 @@ let mayLoad = 1; let mayStore = 1; let hasSideEffects = 0; + let Size = 24; } def PseudoAtomicSwap32 : PseudoAM; @@ -1192,6 +1194,7 @@ let mayLoad = 1; let mayStore = 1; let hasSideEffects = 0; + let Size = 48; } def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMUMinUMax; @@ -1206,6 +1209,7 @@ let mayLoad = 1; let mayStore = 1; let hasSideEffects = 0; + let Size = 36; } def PseudoCmpXchg32 : PseudoCmpXchg; @@ -1219,6 +1223,7 @@ let mayLoad = 1; let mayStore = 1; let hasSideEffects = 0; + let Size = 44; } class AtomicPat diff --git a/llvm/unittests/Target/LoongArch/CMakeLists.txt b/llvm/unittests/Target/LoongArch/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/llvm/unittests/Target/LoongArch/CMakeLists.txt @@ -0,0 +1,25 @@ +include_directories( + ${LLVM_MAIN_SRC_DIR}/lib/Target/LoongArch + ${LLVM_BINARY_DIR}/lib/Target/LoongArch + ) + +set(LLVM_LINK_COMPONENTS + AsmParser + CodeGen + Core + GlobalISel + LoongArchCodeGen + LoongArchDesc + LoongArchInfo + MC + MIRParser + SelectionDAG + Support + Target + ) + +add_llvm_target_unittest(LoongArchTests + InstSizes.cpp + ) + +set_property(TARGET LoongArchTests PROPERTY FOLDER "Tests/UnitTests/TargetTests") diff --git a/llvm/unittests/Target/LoongArch/InstSizes.cpp b/llvm/unittests/Target/LoongArch/InstSizes.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/Target/LoongArch/InstSizes.cpp @@ -0,0 +1,137 @@ +#include "LoongArchSubtarget.h" +#include "LoongArchTargetMachine.h" +#include "llvm/CodeGen/MIRParser/MIRParser.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/TargetSelect.h" + +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { +std::unique_ptr createTargetMachine() { + auto TT(Triple::normalize("loongarch64--")); + std::string CPU("generic-la64"); + std::string FS("+64bit"); + + LLVMInitializeLoongArchTargetInfo(); + LLVMInitializeLoongArchTarget(); + LLVMInitializeLoongArchTargetMC(); + + std::string Error; + const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); + + return std::unique_ptr( + static_cast(TheTarget->createTargetMachine( + TT, CPU, FS, TargetOptions(), None, None, CodeGenOpt::Default))); +} + +std::unique_ptr createInstrInfo(TargetMachine *TM) { + LoongArchSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()), + std::string(TM->getTargetCPU()), + std::string(TM->getTargetFeatureString()), "lp64d", + *TM); + return std::make_unique(ST); +} + +/// The \p InputIRSnippet is only needed for things that can't be expressed in +/// the \p InputMIRSnippet (global variables etc) +/// Inspired by AArch64 +void runChecks( + LLVMTargetMachine *TM, LoongArchInstrInfo *II, + const StringRef InputIRSnippet, const StringRef InputMIRSnippet, + std::function Checks) { + LLVMContext Context; + + auto MIRString = "--- |\n" + " declare void @sizes()\n" + + InputIRSnippet.str() + + "...\n" + "---\n" + "name: sizes\n" + "jumpTable:\n" + " kind: block-address\n" + " entries:\n" + " - id: 0\n" + " blocks: [ '%bb.0' ]\n" + "body: |\n" + " bb.0:\n" + + InputMIRSnippet.str(); + + std::unique_ptr MBuffer = MemoryBuffer::getMemBuffer(MIRString); + std::unique_ptr MParser = + createMIRParser(std::move(MBuffer), Context); + ASSERT_TRUE(MParser); + + std::unique_ptr M = MParser->parseIRModule(); + ASSERT_TRUE(M); + + M->setTargetTriple(TM->getTargetTriple().getTriple()); + M->setDataLayout(TM->createDataLayout()); + + MachineModuleInfo MMI(TM); + bool Res = MParser->parseMachineFunctions(*M, MMI); + ASSERT_FALSE(Res); + + auto F = M->getFunction("sizes"); + ASSERT_TRUE(F != nullptr); + auto &MF = MMI.getOrCreateMachineFunction(*F); + + Checks(*II, MF); +} + +} // anonymous namespace + +TEST(InstSizes, INLINEASM_BR) { + std::unique_ptr TM = createTargetMachine(); + std::unique_ptr II = createInstrInfo(TM.get()); + + runChecks(TM.get(), II.get(), "", + // clang-format off + " INLINEASM_BR &nop, 1 /* sideeffect attdialect */, 13 /* imm */, %jump-table.0\n", + // clang-format on + [](LoongArchInstrInfo &II, MachineFunction &MF) { + auto I = MF.begin()->begin(); + EXPECT_EQ(4u, II.getInstSizeInBytes(*I)); + }); +} + +TEST(InstSizes, SPACE) { + std::unique_ptr TM = createTargetMachine(); + std::unique_ptr II = createInstrInfo(TM.get()); + + runChecks(TM.get(), II.get(), "", " INLINEASM &\".space 1024\", 1\n", + [](LoongArchInstrInfo &II, MachineFunction &MF) { + auto I = MF.begin()->begin(); + EXPECT_EQ(1024u, II.getInstSizeInBytes(*I)); + }); +} + +TEST(InstSizes, AtomicPseudo) { + std::unique_ptr TM = createTargetMachine(); + std::unique_ptr II = createInstrInfo(TM.get()); + + runChecks( + TM.get(), II.get(), "", + // clang-format off + " dead early-clobber renamable $r10, dead early-clobber renamable $r11 = PseudoMaskedAtomicLoadAdd32 renamable $r7, renamable $r6, renamable $r8, 4\n" + " dead early-clobber renamable $r10, dead early-clobber renamable $r11 = PseudoAtomicLoadAdd32 renamable $r7, renamable $r6\n" + " dead early-clobber renamable $r5, dead early-clobber renamable $r9, dead early-clobber renamable $r10 = PseudoMaskedAtomicLoadUMax32 renamable $r7, renamable $r6, renamable $r8, 4\n" + " dead early-clobber renamable $r5, dead early-clobber renamable $r9 = PseudoCmpXchg32 renamable $r7, renamable $r4, renamable $r6\n" + " dead early-clobber renamable $r5, dead early-clobber renamable $r9 = PseudoMaskedCmpXchg32 killed renamable $r7, killed renamable $r4, killed renamable $r6, killed renamable $r8, 4\n", + // clang-format on + [](LoongArchInstrInfo &II, MachineFunction &MF) { + auto I = MF.begin()->begin(); + EXPECT_EQ(36u, II.getInstSizeInBytes(*I)); + ++I; + EXPECT_EQ(24u, II.getInstSizeInBytes(*I)); + ++I; + EXPECT_EQ(48u, II.getInstSizeInBytes(*I)); + ++I; + EXPECT_EQ(36u, II.getInstSizeInBytes(*I)); + ++I; + EXPECT_EQ(44u, II.getInstSizeInBytes(*I)); + }); +}