16d34074dSXiaodong Liu #include "LoongArchSubtarget.h" 26d34074dSXiaodong Liu #include "LoongArchTargetMachine.h" 36d34074dSXiaodong Liu #include "llvm/CodeGen/MIRParser/MIRParser.h" 46d34074dSXiaodong Liu #include "llvm/CodeGen/MachineModuleInfo.h" 54169338eSNikita Popov #include "llvm/IR/Module.h" 66d34074dSXiaodong Liu #include "llvm/MC/TargetRegistry.h" 76d34074dSXiaodong Liu #include "llvm/Support/MemoryBuffer.h" 86d34074dSXiaodong Liu #include "llvm/Support/TargetSelect.h" 9fda79685SKazu Hirata #include <optional> 106d34074dSXiaodong Liu 116d34074dSXiaodong Liu #include "gtest/gtest.h" 126d34074dSXiaodong Liu 136d34074dSXiaodong Liu using namespace llvm; 146d34074dSXiaodong Liu 156d34074dSXiaodong Liu namespace { 16*bb3f5e1fSMatin Raayai std::unique_ptr<TargetMachine> createTargetMachine() { 176d34074dSXiaodong Liu auto TT(Triple::normalize("loongarch64--")); 186d34074dSXiaodong Liu std::string CPU("generic-la64"); 196d34074dSXiaodong Liu std::string FS("+64bit"); 206d34074dSXiaodong Liu 216d34074dSXiaodong Liu LLVMInitializeLoongArchTargetInfo(); 226d34074dSXiaodong Liu LLVMInitializeLoongArchTarget(); 236d34074dSXiaodong Liu LLVMInitializeLoongArchTargetMC(); 246d34074dSXiaodong Liu 256d34074dSXiaodong Liu std::string Error; 266d34074dSXiaodong Liu const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); 276d34074dSXiaodong Liu 28*bb3f5e1fSMatin Raayai return std::unique_ptr<TargetMachine>( 29fda79685SKazu Hirata TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), std::nullopt, 30*bb3f5e1fSMatin Raayai std::nullopt, CodeGenOptLevel::Default)); 316d34074dSXiaodong Liu } 326d34074dSXiaodong Liu 336d34074dSXiaodong Liu std::unique_ptr<LoongArchInstrInfo> createInstrInfo(TargetMachine *TM) { 346d34074dSXiaodong Liu LoongArchSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()), 356d34074dSXiaodong Liu std::string(TM->getTargetCPU()), 366d34074dSXiaodong Liu std::string(TM->getTargetFeatureString()), "lp64d", 376d34074dSXiaodong Liu *TM); 386d34074dSXiaodong Liu return std::make_unique<LoongArchInstrInfo>(ST); 396d34074dSXiaodong Liu } 406d34074dSXiaodong Liu 416d34074dSXiaodong Liu /// The \p InputIRSnippet is only needed for things that can't be expressed in 426d34074dSXiaodong Liu /// the \p InputMIRSnippet (global variables etc) 436d34074dSXiaodong Liu /// Inspired by AArch64 446d34074dSXiaodong Liu void runChecks( 45*bb3f5e1fSMatin Raayai TargetMachine *TM, LoongArchInstrInfo *II, const StringRef InputIRSnippet, 46*bb3f5e1fSMatin Raayai const StringRef InputMIRSnippet, 476d34074dSXiaodong Liu std::function<void(LoongArchInstrInfo &, MachineFunction &)> Checks) { 486d34074dSXiaodong Liu LLVMContext Context; 496d34074dSXiaodong Liu 506d34074dSXiaodong Liu auto MIRString = "--- |\n" 516d34074dSXiaodong Liu " declare void @sizes()\n" + 526d34074dSXiaodong Liu InputIRSnippet.str() + 536d34074dSXiaodong Liu "...\n" 546d34074dSXiaodong Liu "---\n" 556d34074dSXiaodong Liu "name: sizes\n" 566d34074dSXiaodong Liu "jumpTable:\n" 576d34074dSXiaodong Liu " kind: block-address\n" 586d34074dSXiaodong Liu " entries:\n" 596d34074dSXiaodong Liu " - id: 0\n" 606d34074dSXiaodong Liu " blocks: [ '%bb.0' ]\n" 616d34074dSXiaodong Liu "body: |\n" 626d34074dSXiaodong Liu " bb.0:\n" + 636d34074dSXiaodong Liu InputMIRSnippet.str(); 646d34074dSXiaodong Liu 656d34074dSXiaodong Liu std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRString); 666d34074dSXiaodong Liu std::unique_ptr<MIRParser> MParser = 676d34074dSXiaodong Liu createMIRParser(std::move(MBuffer), Context); 686d34074dSXiaodong Liu ASSERT_TRUE(MParser); 696d34074dSXiaodong Liu 706d34074dSXiaodong Liu std::unique_ptr<Module> M = MParser->parseIRModule(); 716d34074dSXiaodong Liu ASSERT_TRUE(M); 726d34074dSXiaodong Liu 736d34074dSXiaodong Liu M->setTargetTriple(TM->getTargetTriple().getTriple()); 746d34074dSXiaodong Liu M->setDataLayout(TM->createDataLayout()); 756d34074dSXiaodong Liu 766d34074dSXiaodong Liu MachineModuleInfo MMI(TM); 776d34074dSXiaodong Liu bool Res = MParser->parseMachineFunctions(*M, MMI); 786d34074dSXiaodong Liu ASSERT_FALSE(Res); 796d34074dSXiaodong Liu 806d34074dSXiaodong Liu auto F = M->getFunction("sizes"); 816d34074dSXiaodong Liu ASSERT_TRUE(F != nullptr); 826d34074dSXiaodong Liu auto &MF = MMI.getOrCreateMachineFunction(*F); 836d34074dSXiaodong Liu 846d34074dSXiaodong Liu Checks(*II, MF); 856d34074dSXiaodong Liu } 866d34074dSXiaodong Liu 876d34074dSXiaodong Liu } // anonymous namespace 886d34074dSXiaodong Liu 896d34074dSXiaodong Liu TEST(InstSizes, INLINEASM_BR) { 90*bb3f5e1fSMatin Raayai std::unique_ptr<TargetMachine> TM = createTargetMachine(); 916d34074dSXiaodong Liu std::unique_ptr<LoongArchInstrInfo> II = createInstrInfo(TM.get()); 926d34074dSXiaodong Liu 936d34074dSXiaodong Liu runChecks(TM.get(), II.get(), "", 946d34074dSXiaodong Liu // clang-format off 956d34074dSXiaodong Liu " INLINEASM_BR &nop, 1 /* sideeffect attdialect */, 13 /* imm */, %jump-table.0\n", 966d34074dSXiaodong Liu // clang-format on 976d34074dSXiaodong Liu [](LoongArchInstrInfo &II, MachineFunction &MF) { 986d34074dSXiaodong Liu auto I = MF.begin()->begin(); 996d34074dSXiaodong Liu EXPECT_EQ(4u, II.getInstSizeInBytes(*I)); 1006d34074dSXiaodong Liu }); 1016d34074dSXiaodong Liu } 1026d34074dSXiaodong Liu 1036d34074dSXiaodong Liu TEST(InstSizes, SPACE) { 104*bb3f5e1fSMatin Raayai std::unique_ptr<TargetMachine> TM = createTargetMachine(); 1056d34074dSXiaodong Liu std::unique_ptr<LoongArchInstrInfo> II = createInstrInfo(TM.get()); 1066d34074dSXiaodong Liu 1076d34074dSXiaodong Liu runChecks(TM.get(), II.get(), "", " INLINEASM &\".space 1024\", 1\n", 1086d34074dSXiaodong Liu [](LoongArchInstrInfo &II, MachineFunction &MF) { 1096d34074dSXiaodong Liu auto I = MF.begin()->begin(); 1106d34074dSXiaodong Liu EXPECT_EQ(1024u, II.getInstSizeInBytes(*I)); 1116d34074dSXiaodong Liu }); 1126d34074dSXiaodong Liu } 1136d34074dSXiaodong Liu 1146d34074dSXiaodong Liu TEST(InstSizes, AtomicPseudo) { 115*bb3f5e1fSMatin Raayai std::unique_ptr<TargetMachine> TM = createTargetMachine(); 1166d34074dSXiaodong Liu std::unique_ptr<LoongArchInstrInfo> II = createInstrInfo(TM.get()); 1176d34074dSXiaodong Liu 1186d34074dSXiaodong Liu runChecks( 1196d34074dSXiaodong Liu TM.get(), II.get(), "", 1206d34074dSXiaodong Liu // clang-format off 1216d34074dSXiaodong Liu " dead early-clobber renamable $r10, dead early-clobber renamable $r11 = PseudoMaskedAtomicLoadAdd32 renamable $r7, renamable $r6, renamable $r8, 4\n" 1226d34074dSXiaodong Liu " dead early-clobber renamable $r10, dead early-clobber renamable $r11 = PseudoAtomicLoadAdd32 renamable $r7, renamable $r6, renamable $r8\n" 1236d34074dSXiaodong Liu " dead early-clobber renamable $r5, dead early-clobber renamable $r9, dead early-clobber renamable $r10 = PseudoMaskedAtomicLoadUMax32 renamable $r7, renamable $r6, renamable $r8, 4\n" 1246d34074dSXiaodong Liu " 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" 125203ba238Shev " dead early-clobber renamable $r5, dead early-clobber renamable $r9 = PseudoCmpXchg32 renamable $r7, renamable $r4, renamable $r6, 4\n" 1266d34074dSXiaodong Liu " 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", 1276d34074dSXiaodong Liu // clang-format on 1286d34074dSXiaodong Liu [](LoongArchInstrInfo &II, MachineFunction &MF) { 1296d34074dSXiaodong Liu auto I = MF.begin()->begin(); 1306d34074dSXiaodong Liu EXPECT_EQ(36u, II.getInstSizeInBytes(*I)); 1316d34074dSXiaodong Liu ++I; 1326d34074dSXiaodong Liu EXPECT_EQ(24u, II.getInstSizeInBytes(*I)); 1336d34074dSXiaodong Liu ++I; 1346d34074dSXiaodong Liu EXPECT_EQ(48u, II.getInstSizeInBytes(*I)); 1356d34074dSXiaodong Liu ++I; 1366d34074dSXiaodong Liu EXPECT_EQ(56u, II.getInstSizeInBytes(*I)); 1376d34074dSXiaodong Liu ++I; 1386d34074dSXiaodong Liu EXPECT_EQ(36u, II.getInstSizeInBytes(*I)); 1396d34074dSXiaodong Liu ++I; 1406d34074dSXiaodong Liu EXPECT_EQ(44u, II.getInstSizeInBytes(*I)); 1416d34074dSXiaodong Liu }); 1426d34074dSXiaodong Liu } 143ffcebcdbSLu Weining 144ffcebcdbSLu Weining TEST(InstSizes, StatePoint) { 145*bb3f5e1fSMatin Raayai std::unique_ptr<TargetMachine> TM = createTargetMachine(); 146ffcebcdbSLu Weining std::unique_ptr<LoongArchInstrInfo> II = createInstrInfo(TM.get()); 147ffcebcdbSLu Weining 148ffcebcdbSLu Weining runChecks( 149ffcebcdbSLu Weining TM.get(), II.get(), " declare zeroext i1 @return_i1()\n", 150ffcebcdbSLu Weining // clang-format off 151ffcebcdbSLu Weining " STATEPOINT 0, 0, 0, target-flags(loongarch-call-plt) @return_i1, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, implicit-def $r3, implicit-def $r4\n", 152ffcebcdbSLu Weining // clang-format on 153ffcebcdbSLu Weining [](LoongArchInstrInfo &II, MachineFunction &MF) { 154ffcebcdbSLu Weining auto I = MF.begin()->begin(); 155ffcebcdbSLu Weining EXPECT_EQ(4u, II.getInstSizeInBytes(*I)); 156ffcebcdbSLu Weining }); 157ffcebcdbSLu Weining } 158