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