1b9c05affSMichael Liao //===- MachineInstrBundleIteratorTest.cpp ---------------------------------===// 2b9c05affSMichael Liao // 3b9c05affSMichael Liao // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4b9c05affSMichael Liao // See https://llvm.org/LICENSE.txt for license information. 5b9c05affSMichael Liao // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6b9c05affSMichael Liao // 7b9c05affSMichael Liao //===----------------------------------------------------------------------===// 8b9c05affSMichael Liao 9aba43035SDmitri Gribenko #include "llvm/ADT/STLExtras.h" 10b9c05affSMichael Liao #include "llvm/CodeGen/MIRParser/MIRParser.h" 11b9c05affSMichael Liao #include "llvm/CodeGen/MIRPrinter.h" 12b9c05affSMichael Liao #include "llvm/CodeGen/MachineFunction.h" 13b9c05affSMichael Liao #include "llvm/CodeGen/MachineMemOperand.h" 14b9c05affSMichael Liao #include "llvm/CodeGen/MachineModuleInfo.h" 15b9c05affSMichael Liao #include "llvm/CodeGen/MachineModuleSlotTracker.h" 16b9c05affSMichael Liao #include "llvm/CodeGen/MachineOperand.h" 17b9c05affSMichael Liao #include "llvm/CodeGen/TargetFrameLowering.h" 18b9c05affSMichael Liao #include "llvm/CodeGen/TargetInstrInfo.h" 19b9c05affSMichael Liao #include "llvm/CodeGen/TargetLowering.h" 20b9c05affSMichael Liao #include "llvm/CodeGen/TargetSubtargetInfo.h" 21b9c05affSMichael Liao #include "llvm/FileCheck/FileCheck.h" 22b9c05affSMichael Liao #include "llvm/IR/MDBuilder.h" 234169338eSNikita Popov #include "llvm/IR/Module.h" 24b9c05affSMichael Liao #include "llvm/IR/ModuleSlotTracker.h" 25b9c05affSMichael Liao #include "llvm/MC/MCAsmInfo.h" 2689b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h" 27b9c05affSMichael Liao #include "llvm/Support/SourceMgr.h" 28b9c05affSMichael Liao #include "llvm/Support/TargetSelect.h" 29b9c05affSMichael Liao #include "llvm/Target/TargetMachine.h" 30b9c05affSMichael Liao #include "gtest/gtest.h" 31b9c05affSMichael Liao 32b9c05affSMichael Liao using namespace llvm; 33b9c05affSMichael Liao 34b9c05affSMichael Liao class MachineMetadataTest : public testing::Test { 35b9c05affSMichael Liao public: 36b9c05affSMichael Liao MachineMetadataTest() {} 37b9c05affSMichael Liao 38b9c05affSMichael Liao protected: 39b9c05affSMichael Liao LLVMContext Context; 40b9c05affSMichael Liao std::unique_ptr<Module> M; 41b9c05affSMichael Liao std::unique_ptr<MIRParser> MIR; 42b9c05affSMichael Liao 43b9c05affSMichael Liao static void SetUpTestCase() { 44b9c05affSMichael Liao InitializeAllTargetInfos(); 45b9c05affSMichael Liao InitializeAllTargets(); 46b9c05affSMichael Liao InitializeAllTargetMCs(); 47b9c05affSMichael Liao } 48b9c05affSMichael Liao 49b9c05affSMichael Liao void SetUp() override { M = std::make_unique<Module>("Dummy", Context); } 50b9c05affSMichael Liao 51b9c05affSMichael Liao void addHooks(ModuleSlotTracker &MST, const MachineOperand &MO) { 52b9c05affSMichael Liao // Setup hooks to assign slot numbers for the specified machine metadata. 53b9c05affSMichael Liao MST.setProcessHook([&MO](AbstractSlotTrackerStorage *AST, const Module *M, 54b9c05affSMichael Liao bool ShouldInitializeAllMetadata) { 55b9c05affSMichael Liao if (ShouldInitializeAllMetadata) { 56b9c05affSMichael Liao if (MO.isMetadata()) 57b9c05affSMichael Liao AST->createMetadataSlot(MO.getMetadata()); 58b9c05affSMichael Liao } 59b9c05affSMichael Liao }); 60b9c05affSMichael Liao MST.setProcessHook([&MO](AbstractSlotTrackerStorage *AST, const Function *F, 61b9c05affSMichael Liao bool ShouldInitializeAllMetadata) { 62b9c05affSMichael Liao if (!ShouldInitializeAllMetadata) { 63b9c05affSMichael Liao if (MO.isMetadata()) 64b9c05affSMichael Liao AST->createMetadataSlot(MO.getMetadata()); 65b9c05affSMichael Liao } 66b9c05affSMichael Liao }); 67b9c05affSMichael Liao } 68b9c05affSMichael Liao 69*bb3f5e1fSMatin Raayai std::unique_ptr<TargetMachine> 70b9c05affSMichael Liao createTargetMachine(std::string TT, StringRef CPU, StringRef FS) { 71b9c05affSMichael Liao std::string Error; 72b9c05affSMichael Liao const Target *T = TargetRegistry::lookupTarget(TT, Error); 73b9c05affSMichael Liao if (!T) 74b9c05affSMichael Liao return nullptr; 75b9c05affSMichael Liao TargetOptions Options; 76*bb3f5e1fSMatin Raayai return std::unique_ptr<TargetMachine>(T->createTargetMachine( 77*bb3f5e1fSMatin Raayai TT, CPU, FS, Options, std::nullopt, std::nullopt)); 78b9c05affSMichael Liao } 79b9c05affSMichael Liao 80b9c05affSMichael Liao std::unique_ptr<Module> parseMIR(const TargetMachine &TM, StringRef MIRCode, 8138c3855cSKyungwoo Lee MachineModuleInfo &MMI) { 82b9c05affSMichael Liao SMDiagnostic Diagnostic; 83b9c05affSMichael Liao std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode); 84b9c05affSMichael Liao MIR = createMIRParser(std::move(MBuffer), Context); 85b9c05affSMichael Liao if (!MIR) 86b9c05affSMichael Liao return nullptr; 87b9c05affSMichael Liao 88b9c05affSMichael Liao std::unique_ptr<Module> Mod = MIR->parseIRModule(); 89b9c05affSMichael Liao if (!Mod) 90b9c05affSMichael Liao return nullptr; 91b9c05affSMichael Liao 92b9c05affSMichael Liao Mod->setDataLayout(TM.createDataLayout()); 93b9c05affSMichael Liao 94b9c05affSMichael Liao if (MIR->parseMachineFunctions(*Mod, MMI)) { 95b9c05affSMichael Liao M.reset(); 96b9c05affSMichael Liao return nullptr; 97b9c05affSMichael Liao } 98b9c05affSMichael Liao 99b9c05affSMichael Liao return Mod; 100b9c05affSMichael Liao } 101b9c05affSMichael Liao }; 102b9c05affSMichael Liao 103b9c05affSMichael Liao // Helper to dump the printer output into a string. 104b9c05affSMichael Liao static std::string print(std::function<void(raw_ostream &OS)> PrintFn) { 105b9c05affSMichael Liao std::string Str; 106b9c05affSMichael Liao raw_string_ostream OS(Str); 107b9c05affSMichael Liao PrintFn(OS); 108b9c05affSMichael Liao return Str; 109b9c05affSMichael Liao } 110b9c05affSMichael Liao 111b9c05affSMichael Liao TEST_F(MachineMetadataTest, TrivialHook) { 112b9c05affSMichael Liao // Verify that post-process hook is invoked to assign slot numbers for 113b9c05affSMichael Liao // machine metadata. 114b9c05affSMichael Liao ASSERT_TRUE(M); 115b9c05affSMichael Liao 116b9c05affSMichael Liao // Create a MachineOperand with a metadata and print it. 117b9c05affSMichael Liao Metadata *MDS = MDString::get(Context, "foo"); 118b9c05affSMichael Liao MDNode *Node = MDNode::get(Context, MDS); 119b9c05affSMichael Liao MachineOperand MO = MachineOperand::CreateMetadata(Node); 120b9c05affSMichael Liao 121b9c05affSMichael Liao // Checking some preconditions on the newly created 122b9c05affSMichael Liao // MachineOperand. 123b9c05affSMichael Liao ASSERT_TRUE(MO.isMetadata()); 124b9c05affSMichael Liao ASSERT_EQ(MO.getMetadata(), Node); 125b9c05affSMichael Liao 126b9c05affSMichael Liao ModuleSlotTracker MST(M.get()); 127b9c05affSMichael Liao addHooks(MST, MO); 128b9c05affSMichael Liao 129b9c05affSMichael Liao // Print a MachineOperand containing a metadata node. 130b9c05affSMichael Liao EXPECT_EQ("!0", print([&](raw_ostream &OS) { 131b9c05affSMichael Liao MO.print(OS, MST, LLT{}, /*OpIdx*/ ~0U, /*PrintDef=*/false, 132b9c05affSMichael Liao /*IsStandalone=*/false, 133b9c05affSMichael Liao /*ShouldPrintRegisterTies=*/false, /*TiedOperandIdx=*/0, 134b9c05affSMichael Liao /*TRI=*/nullptr, 135b9c05affSMichael Liao /*IntrinsicInfo=*/nullptr); 136b9c05affSMichael Liao })); 137b9c05affSMichael Liao // Print the definition of that metadata node. 138b9c05affSMichael Liao EXPECT_EQ("!0 = !{!\"foo\"}", 139b9c05affSMichael Liao print([&](raw_ostream &OS) { Node->print(OS, MST); })); 140b9c05affSMichael Liao } 141b9c05affSMichael Liao 142b9c05affSMichael Liao TEST_F(MachineMetadataTest, BasicHook) { 143b9c05affSMichael Liao // Verify that post-process hook is invoked to assign slot numbers for 144b9c05affSMichael Liao // machine metadata. When both LLVM IR and machine IR contain metadata, 145b9c05affSMichael Liao // ensure that machine metadata is always assigned after LLVM IR. 146b9c05affSMichael Liao ASSERT_TRUE(M); 147b9c05affSMichael Liao 148b9c05affSMichael Liao // Create a MachineOperand with a metadata and print it. 149b9c05affSMichael Liao Metadata *MachineMDS = MDString::get(Context, "foo"); 150b9c05affSMichael Liao MDNode *MachineNode = MDNode::get(Context, MachineMDS); 151b9c05affSMichael Liao MachineOperand MO = MachineOperand::CreateMetadata(MachineNode); 152b9c05affSMichael Liao 153b9c05affSMichael Liao // Checking some preconditions on the newly created 154b9c05affSMichael Liao // MachineOperand. 155b9c05affSMichael Liao ASSERT_TRUE(MO.isMetadata()); 156b9c05affSMichael Liao ASSERT_EQ(MO.getMetadata(), MachineNode); 157b9c05affSMichael Liao 158b9c05affSMichael Liao // Create metadata in LLVM IR. 159b9c05affSMichael Liao NamedMDNode *MD = M->getOrInsertNamedMetadata("namedmd"); 160b9c05affSMichael Liao Metadata *MDS = MDString::get(Context, "bar"); 161b9c05affSMichael Liao MDNode *Node = MDNode::get(Context, MDS); 162b9c05affSMichael Liao MD->addOperand(Node); 163b9c05affSMichael Liao 164b9c05affSMichael Liao ModuleSlotTracker MST(M.get()); 165b9c05affSMichael Liao addHooks(MST, MO); 166b9c05affSMichael Liao 167b9c05affSMichael Liao // Print a MachineOperand containing a metadata node. 168b9c05affSMichael Liao EXPECT_EQ("!1", print([&](raw_ostream &OS) { 169b9c05affSMichael Liao MO.print(OS, MST, LLT{}, /*OpIdx*/ ~0U, /*PrintDef=*/false, 170b9c05affSMichael Liao /*IsStandalone=*/false, 171b9c05affSMichael Liao /*ShouldPrintRegisterTies=*/false, /*TiedOperandIdx=*/0, 172b9c05affSMichael Liao /*TRI=*/nullptr, 173b9c05affSMichael Liao /*IntrinsicInfo=*/nullptr); 174b9c05affSMichael Liao })); 175b9c05affSMichael Liao // Print the definition of these unnamed metadata nodes. 176b9c05affSMichael Liao EXPECT_EQ("!0 = !{!\"bar\"}", 177b9c05affSMichael Liao print([&](raw_ostream &OS) { Node->print(OS, MST); })); 178b9c05affSMichael Liao EXPECT_EQ("!1 = !{!\"foo\"}", 179b9c05affSMichael Liao print([&](raw_ostream &OS) { MachineNode->print(OS, MST); })); 180b9c05affSMichael Liao } 181b9c05affSMichael Liao 182b9c05affSMichael Liao static bool checkOutput(std::string CheckString, std::string Output) { 183b9c05affSMichael Liao auto CheckBuffer = MemoryBuffer::getMemBuffer(CheckString, ""); 184b9c05affSMichael Liao auto OutputBuffer = MemoryBuffer::getMemBuffer(Output, "Output", false); 185b9c05affSMichael Liao 186b9c05affSMichael Liao SmallString<4096> CheckFileBuffer; 187b9c05affSMichael Liao FileCheckRequest Req; 188b9c05affSMichael Liao FileCheck FC(Req); 18975bc20ffSKazu Hirata StringRef CheckFileText = FC.CanonicalizeFile(*CheckBuffer, CheckFileBuffer); 190b9c05affSMichael Liao 191b9c05affSMichael Liao SourceMgr SM; 192b9c05affSMichael Liao SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(CheckFileText, "CheckFile"), 193b9c05affSMichael Liao SMLoc()); 194261b4710SNikita Popov if (FC.readCheckFile(SM, CheckFileText)) 195b9c05affSMichael Liao return false; 196b9c05affSMichael Liao 197b9c05affSMichael Liao auto OutBuffer = OutputBuffer->getBuffer(); 198b9c05affSMichael Liao SM.AddNewSourceBuffer(std::move(OutputBuffer), SMLoc()); 199b9c05affSMichael Liao return FC.checkInput(SM, OutBuffer); 200b9c05affSMichael Liao } 201b9c05affSMichael Liao 202b9c05affSMichael Liao TEST_F(MachineMetadataTest, MMSlotTrackerAArch64) { 203b9c05affSMichael Liao auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", ""); 204b9c05affSMichael Liao if (!TM) 205b9c05affSMichael Liao GTEST_SKIP(); 206b9c05affSMichael Liao 207b9c05affSMichael Liao StringRef MIRString = R"MIR( 208b9c05affSMichael Liao --- | 209b9c05affSMichael Liao define i32 @test0(i32* %p) { 210b9c05affSMichael Liao %r = load i32, i32* %p, align 4 211b9c05affSMichael Liao ret i32 %r 212b9c05affSMichael Liao } 213b9c05affSMichael Liao ... 214b9c05affSMichael Liao --- 215b9c05affSMichael Liao name: test0 216b9c05affSMichael Liao liveins: 217b9c05affSMichael Liao - { reg: '$x0', virtual-reg: '%0' } 218b9c05affSMichael Liao body: | 219b9c05affSMichael Liao bb.0 (%ir-block.0): 220b9c05affSMichael Liao liveins: $x0 221b9c05affSMichael Liao 222b9c05affSMichael Liao %0:gpr64common = COPY $x0 223fae05692SMatt Arsenault %1:gpr32 = LDRWui %0, 0 :: (load (s32) from %ir.p) 224b9c05affSMichael Liao ... 225b9c05affSMichael Liao )MIR"; 226b9c05affSMichael Liao 227b9c05affSMichael Liao MachineModuleInfo MMI(TM.get()); 22838c3855cSKyungwoo Lee M = parseMIR(*TM, MIRString, MMI); 229b9c05affSMichael Liao ASSERT_TRUE(M); 230b9c05affSMichael Liao 231b9c05affSMichael Liao auto *MF = MMI.getMachineFunction(*M->getFunction("test0")); 232b9c05affSMichael Liao auto *MBB = MF->getBlockNumbered(0); 233b9c05affSMichael Liao 234b9c05affSMichael Liao auto &MI = MBB->back(); 235b9c05affSMichael Liao ASSERT_TRUE(MI.hasOneMemOperand()); 236b9c05affSMichael Liao 237b9c05affSMichael Liao // Create and attached scoped AA metadata on that instruction with one MMO. 238b9c05affSMichael Liao MDBuilder MDB(Context); 239b9c05affSMichael Liao MDNode *Domain = MDB.createAnonymousAliasScopeDomain("domain"); 240b9c05affSMichael Liao MDNode *Scope0 = MDB.createAnonymousAliasScope(Domain, "scope0"); 241b9c05affSMichael Liao MDNode *Scope1 = MDB.createAnonymousAliasScope(Domain, "scope1"); 242b9c05affSMichael Liao MDNode *Set0 = MDNode::get(Context, {Scope0}); 243b9c05affSMichael Liao MDNode *Set1 = MDNode::get(Context, {Scope1}); 244b9c05affSMichael Liao 245b9c05affSMichael Liao AAMDNodes AAInfo; 246b9c05affSMichael Liao AAInfo.TBAA = AAInfo.TBAAStruct = nullptr; 247b9c05affSMichael Liao AAInfo.Scope = Set0; 248b9c05affSMichael Liao AAInfo.NoAlias = Set1; 249b9c05affSMichael Liao 250b9c05affSMichael Liao auto *OldMMO = MI.memoperands().front(); 251b9c05affSMichael Liao auto *NewMMO = MF->getMachineMemOperand(OldMMO, AAInfo); 252b9c05affSMichael Liao MI.setMemRefs(*MF, NewMMO); 253b9c05affSMichael Liao 2549a258664SMatt Arsenault MachineModuleSlotTracker MST(MMI, MF); 255b9c05affSMichael Liao // Print that MI with new machine metadata, which slot numbers should be 256b9c05affSMichael Liao // assigned. 257fae05692SMatt Arsenault EXPECT_EQ("%1:gpr32 = LDRWui %0, 0 :: (load (s32) from %ir.p, " 258b9c05affSMichael Liao "!alias.scope !0, !noalias !3)", 259b9c05affSMichael Liao print([&](raw_ostream &OS) { 260b9c05affSMichael Liao MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false, 261b9c05affSMichael Liao /*SkipDebugLoc=*/false, /*AddNewLine=*/false); 262b9c05affSMichael Liao })); 263b9c05affSMichael Liao 264b9c05affSMichael Liao std::vector<const MDNode *> Generated{Domain, Scope0, Scope1, Set0, Set1}; 265b9c05affSMichael Liao // Examine machine metadata collected. They should match ones 266b9c05affSMichael Liao // afore-generated. 267b9c05affSMichael Liao std::vector<const MDNode *> Collected; 268b9c05affSMichael Liao MachineModuleSlotTracker::MachineMDNodeListType MDList; 269b9c05affSMichael Liao MST.collectMachineMDNodes(MDList); 270b9c05affSMichael Liao for (auto &MD : MDList) 271b9c05affSMichael Liao Collected.push_back(MD.second); 272b9c05affSMichael Liao 273aba43035SDmitri Gribenko llvm::sort(Generated); 274aba43035SDmitri Gribenko llvm::sort(Collected); 275b9c05affSMichael Liao EXPECT_EQ(Collected, Generated); 276b9c05affSMichael Liao 277b9c05affSMichael Liao // FileCheck the output from MIR printer. 2789a258664SMatt Arsenault std::string Output = print([&](raw_ostream &OS) { printMIR(OS, MMI, *MF); }); 279b9c05affSMichael Liao std::string CheckString = R"( 280b9c05affSMichael Liao CHECK: machineMetadataNodes: 281b9c05affSMichael Liao CHECK-DAG: ![[MMDOMAIN:[0-9]+]] = distinct !{!{{[0-9]+}}, !"domain"} 282b9c05affSMichael Liao CHECK-DAG: ![[MMSCOPE0:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope0"} 283b9c05affSMichael Liao CHECK-DAG: ![[MMSCOPE1:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope1"} 284b9c05affSMichael Liao CHECK-DAG: ![[MMSET0:[0-9]+]] = !{![[MMSCOPE0]]} 285b9c05affSMichael Liao CHECK-DAG: ![[MMSET1:[0-9]+]] = !{![[MMSCOPE1]]} 286b9c05affSMichael Liao CHECK: body: 287fae05692SMatt Arsenault CHECK: %1:gpr32 = LDRWui %0, 0 :: (load (s32) from %ir.p, !alias.scope ![[MMSET0]], !noalias ![[MMSET1]]) 288b9c05affSMichael Liao )"; 289b9c05affSMichael Liao EXPECT_TRUE(checkOutput(CheckString, Output)); 290b9c05affSMichael Liao } 291b9c05affSMichael Liao 292edff0070SShengchen Kan TEST_F(MachineMetadataTest, isMetaInstruction) { 293edff0070SShengchen Kan auto TM = createTargetMachine(Triple::normalize("x86_64--"), "", ""); 294edff0070SShengchen Kan if (!TM) 295edff0070SShengchen Kan GTEST_SKIP(); 296edff0070SShengchen Kan 297edff0070SShengchen Kan StringRef MIRString = R"MIR( 298edff0070SShengchen Kan --- | 299edff0070SShengchen Kan define void @test0(i32 %b) { 300edff0070SShengchen Kan ret void 301edff0070SShengchen Kan } 302edff0070SShengchen Kan !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) 303edff0070SShengchen Kan !1 = !DIFile(filename: "a.c", directory: "/tmp") 304edff0070SShengchen Kan !2 = !{i32 7, !"Dwarf Version", i32 4} 305edff0070SShengchen Kan !3 = !{i32 2, !"Debug Info Version", i32 3} 306edff0070SShengchen Kan !4 = !{i32 1, !"wchar_size", i32 4} 307edff0070SShengchen Kan !5 = !{i32 7, !"uwtable", i32 1} 308edff0070SShengchen Kan !6 = !{i32 7, !"frame-pointer", i32 2} 309edff0070SShengchen Kan !7 = !{!""} 310edff0070SShengchen Kan !8 = distinct !DISubprogram(name: "test0", scope: !1, file: !1, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !12) 311edff0070SShengchen Kan !9 = !DISubroutineType(types: !10) 312edff0070SShengchen Kan !10 = !{null, !11} 313edff0070SShengchen Kan !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) 314edff0070SShengchen Kan !12 = !{} 315edff0070SShengchen Kan !13 = !DILocalVariable(name: "b", arg: 1, scope: !8, file: !1, line: 1, type: !11) 316edff0070SShengchen Kan !14 = !DILocation(line: 1, column: 16, scope: !8) 317edff0070SShengchen Kan ... 318edff0070SShengchen Kan --- 319edff0070SShengchen Kan name: test0 320edff0070SShengchen Kan machineFunctionInfo 321edff0070SShengchen Kan body: | 322edff0070SShengchen Kan bb.0: 323edff0070SShengchen Kan $rdi = IMPLICIT_DEF 324edff0070SShengchen Kan KILL $rsi 325edff0070SShengchen Kan CFI_INSTRUCTION undefined $rax 326edff0070SShengchen Kan EH_LABEL 0 327edff0070SShengchen Kan GC_LABEL 0 328edff0070SShengchen Kan DBG_VALUE $rax, $noreg, !13, !DIExpression(), debug-location !14 329edff0070SShengchen Kan DBG_LABEL 0 330edff0070SShengchen Kan LIFETIME_START 0 331edff0070SShengchen Kan LIFETIME_END 0 332edff0070SShengchen Kan PSEUDO_PROBE 6699318081062747564, 1, 0, 0 333edff0070SShengchen Kan $xmm0 = ARITH_FENCE $xmm0 334eb442269SPhilip Reames MEMBARRIER 335edff0070SShengchen Kan ... 336edff0070SShengchen Kan )MIR"; 337edff0070SShengchen Kan 338edff0070SShengchen Kan MachineModuleInfo MMI(TM.get()); 33938c3855cSKyungwoo Lee M = parseMIR(*TM, MIRString, MMI); 340edff0070SShengchen Kan ASSERT_TRUE(M); 341edff0070SShengchen Kan 342edff0070SShengchen Kan auto *MF = MMI.getMachineFunction(*M->getFunction("test0")); 343edff0070SShengchen Kan auto *MBB = MF->getBlockNumbered(0); 344edff0070SShengchen Kan 345edff0070SShengchen Kan for (auto It = MBB->begin(); It != MBB->end(); ++It) { 346edff0070SShengchen Kan MachineInstr &MI = *It; 347edff0070SShengchen Kan ASSERT_TRUE(MI.isMetaInstruction()); 348edff0070SShengchen Kan } 349edff0070SShengchen Kan } 350edff0070SShengchen Kan 351b9c05affSMichael Liao TEST_F(MachineMetadataTest, MMSlotTrackerX64) { 352b9c05affSMichael Liao auto TM = createTargetMachine(Triple::normalize("x86_64--"), "", ""); 353b9c05affSMichael Liao if (!TM) 354b9c05affSMichael Liao GTEST_SKIP(); 355b9c05affSMichael Liao 356b9c05affSMichael Liao StringRef MIRString = R"MIR( 357b9c05affSMichael Liao --- | 358b9c05affSMichael Liao define i32 @test0(i32* %p) { 359b9c05affSMichael Liao %r = load i32, i32* %p, align 4 360b9c05affSMichael Liao ret i32 %r 361b9c05affSMichael Liao } 362b9c05affSMichael Liao ... 363b9c05affSMichael Liao --- 364b9c05affSMichael Liao name: test0 365b9c05affSMichael Liao liveins: 366b9c05affSMichael Liao - { reg: '$rdi', virtual-reg: '%0' } 367b9c05affSMichael Liao body: | 368b9c05affSMichael Liao bb.0 (%ir-block.0): 369b9c05affSMichael Liao liveins: $rdi 370b9c05affSMichael Liao 371b9c05affSMichael Liao %0:gr64 = COPY $rdi 372fae05692SMatt Arsenault %1:gr32 = MOV32rm %0, 1, $noreg, 0, $noreg :: (load (s32) from %ir.p) 373b9c05affSMichael Liao ... 374b9c05affSMichael Liao )MIR"; 375b9c05affSMichael Liao 376b9c05affSMichael Liao MachineModuleInfo MMI(TM.get()); 37738c3855cSKyungwoo Lee M = parseMIR(*TM, MIRString, MMI); 378b9c05affSMichael Liao ASSERT_TRUE(M); 379b9c05affSMichael Liao 380b9c05affSMichael Liao auto *MF = MMI.getMachineFunction(*M->getFunction("test0")); 381b9c05affSMichael Liao auto *MBB = MF->getBlockNumbered(0); 382b9c05affSMichael Liao 383b9c05affSMichael Liao auto &MI = MBB->back(); 384b9c05affSMichael Liao ASSERT_FALSE(MI.memoperands_empty()); 385b9c05affSMichael Liao ASSERT_TRUE(MI.hasOneMemOperand()); 386b9c05affSMichael Liao 387b9c05affSMichael Liao // Create and attached scoped AA metadata on that instruction with one MMO. 388b9c05affSMichael Liao MDBuilder MDB(Context); 389b9c05affSMichael Liao MDNode *Domain = MDB.createAnonymousAliasScopeDomain("domain"); 390b9c05affSMichael Liao MDNode *Scope0 = MDB.createAnonymousAliasScope(Domain, "scope0"); 391b9c05affSMichael Liao MDNode *Scope1 = MDB.createAnonymousAliasScope(Domain, "scope1"); 392b9c05affSMichael Liao MDNode *Set0 = MDNode::get(Context, {Scope0}); 393b9c05affSMichael Liao MDNode *Set1 = MDNode::get(Context, {Scope1}); 394b9c05affSMichael Liao 395b9c05affSMichael Liao AAMDNodes AAInfo; 396b9c05affSMichael Liao AAInfo.TBAA = AAInfo.TBAAStruct = nullptr; 397b9c05affSMichael Liao AAInfo.Scope = Set0; 398b9c05affSMichael Liao AAInfo.NoAlias = Set1; 399b9c05affSMichael Liao 400b9c05affSMichael Liao auto *OldMMO = MI.memoperands().front(); 401b9c05affSMichael Liao auto *NewMMO = MF->getMachineMemOperand(OldMMO, AAInfo); 402b9c05affSMichael Liao MI.setMemRefs(*MF, NewMMO); 403b9c05affSMichael Liao 4049a258664SMatt Arsenault MachineModuleSlotTracker MST(MMI, MF); 405b9c05affSMichael Liao // Print that MI with new machine metadata, which slot numbers should be 406b9c05affSMichael Liao // assigned. 407fae05692SMatt Arsenault EXPECT_EQ("%1:gr32 = MOV32rm %0, 1, $noreg, 0, $noreg :: (load (s32) from %ir.p, " 408b9c05affSMichael Liao "!alias.scope !0, !noalias !3)", 409b9c05affSMichael Liao print([&](raw_ostream &OS) { 410b9c05affSMichael Liao MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false, 411b9c05affSMichael Liao /*SkipDebugLoc=*/false, /*AddNewLine=*/false); 412b9c05affSMichael Liao })); 413b9c05affSMichael Liao 414b9c05affSMichael Liao std::vector<const MDNode *> Generated{Domain, Scope0, Scope1, Set0, Set1}; 415b9c05affSMichael Liao // Examine machine metadata collected. They should match ones 416b9c05affSMichael Liao // afore-generated. 417b9c05affSMichael Liao std::vector<const MDNode *> Collected; 418b9c05affSMichael Liao MachineModuleSlotTracker::MachineMDNodeListType MDList; 419b9c05affSMichael Liao MST.collectMachineMDNodes(MDList); 420b9c05affSMichael Liao for (auto &MD : MDList) 421b9c05affSMichael Liao Collected.push_back(MD.second); 422b9c05affSMichael Liao 423aba43035SDmitri Gribenko llvm::sort(Generated); 424aba43035SDmitri Gribenko llvm::sort(Collected); 425b9c05affSMichael Liao EXPECT_EQ(Collected, Generated); 426b9c05affSMichael Liao 427b9c05affSMichael Liao // FileCheck the output from MIR printer. 4289a258664SMatt Arsenault std::string Output = print([&](raw_ostream &OS) { printMIR(OS, MMI, *MF); }); 429b9c05affSMichael Liao std::string CheckString = R"( 430b9c05affSMichael Liao CHECK: machineMetadataNodes: 431b9c05affSMichael Liao CHECK-DAG: ![[MMDOMAIN:[0-9]+]] = distinct !{!{{[0-9]+}}, !"domain"} 432b9c05affSMichael Liao CHECK-DAG: ![[MMSCOPE0:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope0"} 433b9c05affSMichael Liao CHECK-DAG: ![[MMSCOPE1:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope1"} 434b9c05affSMichael Liao CHECK-DAG: ![[MMSET0:[0-9]+]] = !{![[MMSCOPE0]]} 435b9c05affSMichael Liao CHECK-DAG: ![[MMSET1:[0-9]+]] = !{![[MMSCOPE1]]} 436b9c05affSMichael Liao CHECK: body: 437fae05692SMatt Arsenault CHECK: %1:gr32 = MOV32rm %0, 1, $noreg, 0, $noreg :: (load (s32) from %ir.p, !alias.scope ![[MMSET0]], !noalias ![[MMSET1]]) 438b9c05affSMichael Liao )"; 439b9c05affSMichael Liao EXPECT_TRUE(checkOutput(CheckString, Output)); 440b9c05affSMichael Liao } 441b9c05affSMichael Liao 442b9c05affSMichael Liao TEST_F(MachineMetadataTest, MMSlotTrackerAMDGPU) { 443b9c05affSMichael Liao auto TM = createTargetMachine(Triple::normalize("amdgcn-amd-amdhsa"), 444b9c05affSMichael Liao "gfx1010", ""); 445b9c05affSMichael Liao if (!TM) 446b9c05affSMichael Liao GTEST_SKIP(); 447b9c05affSMichael Liao 448b9c05affSMichael Liao StringRef MIRString = R"MIR( 449b9c05affSMichael Liao --- | 450b9c05affSMichael Liao define i32 @test0(i32* %p) { 451b9c05affSMichael Liao %r = load i32, i32* %p, align 4 452b9c05affSMichael Liao ret i32 %r 453b9c05affSMichael Liao } 454b9c05affSMichael Liao ... 455b9c05affSMichael Liao --- 456b9c05affSMichael Liao name: test0 457b9c05affSMichael Liao liveins: 458b9c05affSMichael Liao - { reg: '$vgpr0', virtual-reg: '%0' } 459b9c05affSMichael Liao - { reg: '$vgpr1', virtual-reg: '%1' } 460b9c05affSMichael Liao - { reg: '$sgpr30_sgpr31', virtual-reg: '%2' } 461b9c05affSMichael Liao body: | 462b9c05affSMichael Liao bb.0 (%ir-block.0): 463b9c05affSMichael Liao liveins: $vgpr0, $vgpr1, $sgpr30_sgpr31 464b9c05affSMichael Liao 465b9c05affSMichael Liao %2:sreg_64 = COPY $sgpr30_sgpr31 466b9c05affSMichael Liao %1:vgpr_32 = COPY $vgpr1 467b9c05affSMichael Liao %0:vgpr_32 = COPY $vgpr0 468b9c05affSMichael Liao %8:vreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1 469b9c05affSMichael Liao %6:vreg_64 = COPY %8 470fae05692SMatt Arsenault %5:vgpr_32 = FLAT_LOAD_DWORD killed %6, 0, 0, implicit $exec, implicit $flat_scr :: (load (s32) from %ir.p) 471b9c05affSMichael Liao ... 472b9c05affSMichael Liao )MIR"; 473b9c05affSMichael Liao 474b9c05affSMichael Liao MachineModuleInfo MMI(TM.get()); 47538c3855cSKyungwoo Lee M = parseMIR(*TM, MIRString, MMI); 476b9c05affSMichael Liao ASSERT_TRUE(M); 477b9c05affSMichael Liao 478b9c05affSMichael Liao auto *MF = MMI.getMachineFunction(*M->getFunction("test0")); 479b9c05affSMichael Liao auto *MBB = MF->getBlockNumbered(0); 480b9c05affSMichael Liao 481b9c05affSMichael Liao auto &MI = MBB->back(); 482b9c05affSMichael Liao ASSERT_FALSE(MI.memoperands_empty()); 483b9c05affSMichael Liao ASSERT_TRUE(MI.hasOneMemOperand()); 484b9c05affSMichael Liao 485b9c05affSMichael Liao // Create and attached scoped AA metadata on that instruction with one MMO. 486b9c05affSMichael Liao MDBuilder MDB(Context); 487b9c05affSMichael Liao MDNode *Domain = MDB.createAnonymousAliasScopeDomain("domain"); 488b9c05affSMichael Liao MDNode *Scope0 = MDB.createAnonymousAliasScope(Domain, "scope0"); 489b9c05affSMichael Liao MDNode *Scope1 = MDB.createAnonymousAliasScope(Domain, "scope1"); 490b9c05affSMichael Liao MDNode *Set0 = MDNode::get(Context, {Scope0}); 491b9c05affSMichael Liao MDNode *Set1 = MDNode::get(Context, {Scope1}); 492b9c05affSMichael Liao 493b9c05affSMichael Liao AAMDNodes AAInfo; 494b9c05affSMichael Liao AAInfo.TBAA = AAInfo.TBAAStruct = nullptr; 495b9c05affSMichael Liao AAInfo.Scope = Set0; 496b9c05affSMichael Liao AAInfo.NoAlias = Set1; 497b9c05affSMichael Liao 498b9c05affSMichael Liao auto *OldMMO = MI.memoperands().front(); 499b9c05affSMichael Liao auto *NewMMO = MF->getMachineMemOperand(OldMMO, AAInfo); 500b9c05affSMichael Liao MI.setMemRefs(*MF, NewMMO); 501b9c05affSMichael Liao 5029a258664SMatt Arsenault MachineModuleSlotTracker MST(MMI, MF); 503b9c05affSMichael Liao // Print that MI with new machine metadata, which slot numbers should be 504b9c05affSMichael Liao // assigned. 505b9c05affSMichael Liao EXPECT_EQ( 506b9c05affSMichael Liao "%5:vgpr_32 = FLAT_LOAD_DWORD killed %4, 0, 0, implicit $exec, implicit " 507fae05692SMatt Arsenault "$flat_scr :: (load (s32) from %ir.p, !alias.scope !0, !noalias !3)", 508b9c05affSMichael Liao print([&](raw_ostream &OS) { 509b9c05affSMichael Liao MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false, 510b9c05affSMichael Liao /*SkipDebugLoc=*/false, /*AddNewLine=*/false); 511b9c05affSMichael Liao })); 512b9c05affSMichael Liao 513b9c05affSMichael Liao std::vector<const MDNode *> Generated{Domain, Scope0, Scope1, Set0, Set1}; 514b9c05affSMichael Liao // Examine machine metadata collected. They should match ones 515b9c05affSMichael Liao // afore-generated. 516b9c05affSMichael Liao std::vector<const MDNode *> Collected; 517b9c05affSMichael Liao MachineModuleSlotTracker::MachineMDNodeListType MDList; 518b9c05affSMichael Liao MST.collectMachineMDNodes(MDList); 519b9c05affSMichael Liao for (auto &MD : MDList) 520b9c05affSMichael Liao Collected.push_back(MD.second); 521b9c05affSMichael Liao 522aba43035SDmitri Gribenko llvm::sort(Generated); 523aba43035SDmitri Gribenko llvm::sort(Collected); 524b9c05affSMichael Liao EXPECT_EQ(Collected, Generated); 525b9c05affSMichael Liao 526b9c05affSMichael Liao // FileCheck the output from MIR printer. 5279a258664SMatt Arsenault std::string Output = print([&](raw_ostream &OS) { printMIR(OS, MMI, *MF); }); 528b9c05affSMichael Liao std::string CheckString = R"( 529b9c05affSMichael Liao CHECK: machineMetadataNodes: 530b9c05affSMichael Liao CHECK-DAG: ![[MMDOMAIN:[0-9]+]] = distinct !{!{{[0-9]+}}, !"domain"} 531b9c05affSMichael Liao CHECK-DAG: ![[MMSCOPE0:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope0"} 532b9c05affSMichael Liao CHECK-DAG: ![[MMSCOPE1:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope1"} 533b9c05affSMichael Liao CHECK-DAG: ![[MMSET0:[0-9]+]] = !{![[MMSCOPE0]]} 534b9c05affSMichael Liao CHECK-DAG: ![[MMSET1:[0-9]+]] = !{![[MMSCOPE1]]} 535b9c05affSMichael Liao CHECK: body: 536fae05692SMatt Arsenault CHECK: %5:vgpr_32 = FLAT_LOAD_DWORD killed %4, 0, 0, implicit $exec, implicit $flat_scr :: (load (s32) from %ir.p, !alias.scope ![[MMSET0]], !noalias ![[MMSET1]]) 537b9c05affSMichael Liao )"; 538b9c05affSMichael Liao EXPECT_TRUE(checkOutput(CheckString, Output)); 539b9c05affSMichael Liao } 540b206ee69SKai Luo 541b206ee69SKai Luo TEST_F(MachineMetadataTest, TiedOpsRewritten) { 542b206ee69SKai Luo auto TM = createTargetMachine(Triple::normalize("powerpc64--"), "", ""); 543b206ee69SKai Luo if (!TM) 544b206ee69SKai Luo GTEST_SKIP(); 545b206ee69SKai Luo StringRef MIRString = R"MIR( 546b206ee69SKai Luo --- 547b206ee69SKai Luo name: foo 548b206ee69SKai Luo alignment: 16 549b206ee69SKai Luo tracksRegLiveness: true 550b206ee69SKai Luo frameInfo: 551b206ee69SKai Luo maxAlignment: 16 552b206ee69SKai Luo machineFunctionInfo: {} 553b206ee69SKai Luo body: | 554b206ee69SKai Luo bb.0: 555b206ee69SKai Luo liveins: $r3 556b206ee69SKai Luo %0:gprc = COPY $r3 557b206ee69SKai Luo %0 = RLWIMI killed %0, $r3, 1, 0, 30 558b206ee69SKai Luo $r3 = COPY %0 559b206ee69SKai Luo BLR8 implicit $r3, implicit $lr8, implicit $rm 560b206ee69SKai Luo 561b206ee69SKai Luo ... 562b206ee69SKai Luo )MIR"; 563b206ee69SKai Luo MachineModuleInfo MMI(TM.get()); 56438c3855cSKyungwoo Lee M = parseMIR(*TM, MIRString, MMI); 565b206ee69SKai Luo ASSERT_TRUE(M); 566b206ee69SKai Luo auto *MF = MMI.getMachineFunction(*M->getFunction("foo")); 567b206ee69SKai Luo MachineFunctionProperties &Properties = MF->getProperties(); 568b206ee69SKai Luo ASSERT_TRUE(Properties.hasProperty( 569b206ee69SKai Luo MachineFunctionProperties::Property::TiedOpsRewritten)); 570b206ee69SKai Luo } 571b206ee69SKai Luo 572b206ee69SKai Luo TEST_F(MachineMetadataTest, NoTiedOpsRewritten) { 573b206ee69SKai Luo auto TM = createTargetMachine(Triple::normalize("powerpc64--"), "", ""); 574b206ee69SKai Luo if (!TM) 575b206ee69SKai Luo GTEST_SKIP(); 576b206ee69SKai Luo StringRef MIRString = R"MIR( 577b206ee69SKai Luo --- 578b206ee69SKai Luo name: foo 579b206ee69SKai Luo alignment: 16 580b206ee69SKai Luo tracksRegLiveness: true 581b206ee69SKai Luo frameInfo: 582b206ee69SKai Luo maxAlignment: 16 583b206ee69SKai Luo machineFunctionInfo: {} 584b206ee69SKai Luo body: | 585b206ee69SKai Luo bb.0: 586b206ee69SKai Luo liveins: $r3 587b206ee69SKai Luo %0:gprc = COPY $r3 588b206ee69SKai Luo %1:gprc = RLWIMI killed %0, $r3, 1, 0, 30 589b206ee69SKai Luo $r3 = COPY %1 590b206ee69SKai Luo BLR8 implicit $r3, implicit $lr8, implicit $rm 591b206ee69SKai Luo 592b206ee69SKai Luo ... 593b206ee69SKai Luo )MIR"; 594b206ee69SKai Luo MachineModuleInfo MMI(TM.get()); 59538c3855cSKyungwoo Lee M = parseMIR(*TM, MIRString, MMI); 596b206ee69SKai Luo ASSERT_TRUE(M); 597b206ee69SKai Luo auto *MF = MMI.getMachineFunction(*M->getFunction("foo")); 598b206ee69SKai Luo MachineFunctionProperties &Properties = MF->getProperties(); 599b206ee69SKai Luo ASSERT_FALSE(Properties.hasProperty( 600b206ee69SKai Luo MachineFunctionProperties::Property::TiedOpsRewritten)); 601b206ee69SKai Luo } 602