xref: /llvm-project/llvm/unittests/MIR/MachineMetadata.cpp (revision 9a258664024d12a06ba8eb9344e270a9bb5f5d87)
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