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