1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
#include "LoongArchSubtarget.h"
#include "LoongArchTargetMachine.h"
#include "llvm/CodeGen/MIRParser/MIRParser.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/TargetSelect.h"
#include <optional>
#include "gtest/gtest.h"
using namespace llvm;
namespace {
std::unique_ptr<LLVMTargetMachine> 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<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>(
TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), std::nullopt,
std::nullopt, CodeGenOptLevel::Default)));
}
std::unique_ptr<LoongArchInstrInfo> 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<LoongArchInstrInfo>(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<void(LoongArchInstrInfo &, MachineFunction &)> 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<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRString);
std::unique_ptr<MIRParser> MParser =
createMIRParser(std::move(MBuffer), Context);
ASSERT_TRUE(MParser);
std::unique_ptr<Module> 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<LLVMTargetMachine> TM = createTargetMachine();
std::unique_ptr<LoongArchInstrInfo> 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<LLVMTargetMachine> TM = createTargetMachine();
std::unique_ptr<LoongArchInstrInfo> 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<LLVMTargetMachine> TM = createTargetMachine();
std::unique_ptr<LoongArchInstrInfo> 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, renamable $r8\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"
" early-clobber renamable $r9, dead early-clobber renamable $r10, dead early-clobber renamable $r11 = PseudoMaskedAtomicLoadMax32 killed renamable $r6, killed renamable $r5, killed renamable $r7, killed renamable $r8, 4\n"
" dead early-clobber renamable $r5, dead early-clobber renamable $r9 = PseudoCmpXchg32 renamable $r7, renamable $r4, renamable $r6, 4\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(56u, II.getInstSizeInBytes(*I));
++I;
EXPECT_EQ(36u, II.getInstSizeInBytes(*I));
++I;
EXPECT_EQ(44u, II.getInstSizeInBytes(*I));
});
}
|