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