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