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