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