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/ModuleSlotTracker.h"
24#include "llvm/MC/MCAsmInfo.h"
25#include "llvm/MC/TargetRegistry.h"
26#include "llvm/Support/SourceMgr.h"
27#include "llvm/Support/TargetSelect.h"
28#include "llvm/Target/TargetMachine.h"
29#include "gtest/gtest.h"
30
31using namespace llvm;
32
33class MachineMetadataTest : public testing::Test {
34public:
35 MachineMetadataTest() {}
36
37protected:
38 LLVMContext Context;
39 std::unique_ptr<Module> M;
40 std::unique_ptr<MIRParser> MIR;
41
42 static void SetUpTestCase() {
43 InitializeAllTargetInfos();
44 InitializeAllTargets();
45 InitializeAllTargetMCs();
46 }
47
48 void SetUp() override { M = std::make_unique<Module>(args: "Dummy", args&: Context); }
49
50 void addHooks(ModuleSlotTracker &MST, const MachineOperand &MO) {
51 // Setup hooks to assign slot numbers for the specified machine metadata.
52 MST.setProcessHook([&MO](AbstractSlotTrackerStorage *AST, const Module *M,
53 bool ShouldInitializeAllMetadata) {
54 if (ShouldInitializeAllMetadata) {
55 if (MO.isMetadata())
56 AST->createMetadataSlot(MO.getMetadata());
57 }
58 });
59 MST.setProcessHook([&MO](AbstractSlotTrackerStorage *AST, const Function *F,
60 bool ShouldInitializeAllMetadata) {
61 if (!ShouldInitializeAllMetadata) {
62 if (MO.isMetadata())
63 AST->createMetadataSlot(MO.getMetadata());
64 }
65 });
66 }
67
68 std::unique_ptr<LLVMTargetMachine>
69 createTargetMachine(std::string TT, StringRef CPU, StringRef FS) {
70 std::string Error;
71 const Target *T = TargetRegistry::lookupTarget(Triple: TT, Error);
72 if (!T)
73 return nullptr;
74 TargetOptions Options;
75 return std::unique_ptr<LLVMTargetMachine>(
76 static_cast<LLVMTargetMachine *>(T->createTargetMachine(
77 TT, CPU, Features: FS, Options, RM: std::nullopt, CM: std::nullopt)));
78 }
79
80 std::unique_ptr<Module> parseMIR(const TargetMachine &TM, StringRef MIRCode,
81 const char *FnName, MachineModuleInfo &MMI) {
82 SMDiagnostic Diagnostic;
83 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(InputData: MIRCode);
84 MIR = createMIRParser(Contents: 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(M&: *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.
104static std::string print(std::function<void(raw_ostream &OS)> PrintFn) {
105 std::string Str;
106 raw_string_ostream OS(Str);
107 PrintFn(OS);
108 OS.flush();
109 return Str;
110}
111
112TEST_F(MachineMetadataTest, TrivialHook) {
113 // Verify that post-process hook is invoked to assign slot numbers for
114 // machine metadata.
115 ASSERT_TRUE(M);
116
117 // Create a MachineOperand with a metadata and print it.
118 Metadata *MDS = MDString::get(Context, Str: "foo");
119 MDNode *Node = MDNode::get(Context, MDs: MDS);
120 MachineOperand MO = MachineOperand::CreateMetadata(Meta: Node);
121
122 // Checking some preconditions on the newly created
123 // MachineOperand.
124 ASSERT_TRUE(MO.isMetadata());
125 ASSERT_EQ(MO.getMetadata(), Node);
126
127 ModuleSlotTracker MST(M.get());
128 addHooks(MST, MO);
129
130 // Print a MachineOperand containing a metadata node.
131 EXPECT_EQ("!0", print([&](raw_ostream &OS) {
132 MO.print(OS, MST, LLT{}, /*OpIdx*/ ~0U, /*PrintDef=*/false,
133 /*IsStandalone=*/false,
134 /*ShouldPrintRegisterTies=*/false, /*TiedOperandIdx=*/0,
135 /*TRI=*/nullptr,
136 /*IntrinsicInfo=*/nullptr);
137 }));
138 // Print the definition of that metadata node.
139 EXPECT_EQ("!0 = !{!\"foo\"}",
140 print([&](raw_ostream &OS) { Node->print(OS, MST); }));
141}
142
143TEST_F(MachineMetadataTest, BasicHook) {
144 // Verify that post-process hook is invoked to assign slot numbers for
145 // machine metadata. When both LLVM IR and machine IR contain metadata,
146 // ensure that machine metadata is always assigned after LLVM IR.
147 ASSERT_TRUE(M);
148
149 // Create a MachineOperand with a metadata and print it.
150 Metadata *MachineMDS = MDString::get(Context, Str: "foo");
151 MDNode *MachineNode = MDNode::get(Context, MDs: MachineMDS);
152 MachineOperand MO = MachineOperand::CreateMetadata(Meta: MachineNode);
153
154 // Checking some preconditions on the newly created
155 // MachineOperand.
156 ASSERT_TRUE(MO.isMetadata());
157 ASSERT_EQ(MO.getMetadata(), MachineNode);
158
159 // Create metadata in LLVM IR.
160 NamedMDNode *MD = M->getOrInsertNamedMetadata(Name: "namedmd");
161 Metadata *MDS = MDString::get(Context, Str: "bar");
162 MDNode *Node = MDNode::get(Context, MDs: MDS);
163 MD->addOperand(M: Node);
164
165 ModuleSlotTracker MST(M.get());
166 addHooks(MST, MO);
167
168 // Print a MachineOperand containing a metadata node.
169 EXPECT_EQ("!1", print([&](raw_ostream &OS) {
170 MO.print(OS, MST, LLT{}, /*OpIdx*/ ~0U, /*PrintDef=*/false,
171 /*IsStandalone=*/false,
172 /*ShouldPrintRegisterTies=*/false, /*TiedOperandIdx=*/0,
173 /*TRI=*/nullptr,
174 /*IntrinsicInfo=*/nullptr);
175 }));
176 // Print the definition of these unnamed metadata nodes.
177 EXPECT_EQ("!0 = !{!\"bar\"}",
178 print([&](raw_ostream &OS) { Node->print(OS, MST); }));
179 EXPECT_EQ("!1 = !{!\"foo\"}",
180 print([&](raw_ostream &OS) { MachineNode->print(OS, MST); }));
181}
182
183static bool checkOutput(std::string CheckString, std::string Output) {
184 auto CheckBuffer = MemoryBuffer::getMemBuffer(InputData: CheckString, BufferName: "");
185 auto OutputBuffer = MemoryBuffer::getMemBuffer(InputData: Output, BufferName: "Output", RequiresNullTerminator: false);
186
187 SmallString<4096> CheckFileBuffer;
188 FileCheckRequest Req;
189 FileCheck FC(Req);
190 StringRef CheckFileText =
191 FC.CanonicalizeFile(MB&: *CheckBuffer.get(), OutputBuffer&: CheckFileBuffer);
192
193 SourceMgr SM;
194 SM.AddNewSourceBuffer(F: MemoryBuffer::getMemBuffer(InputData: CheckFileText, BufferName: "CheckFile"),
195 IncludeLoc: SMLoc());
196 if (FC.readCheckFile(SM, Buffer: CheckFileText))
197 return false;
198
199 auto OutBuffer = OutputBuffer->getBuffer();
200 SM.AddNewSourceBuffer(F: std::move(OutputBuffer), IncludeLoc: SMLoc());
201 return FC.checkInput(SM, Buffer: OutBuffer);
202}
203
204TEST_F(MachineMetadataTest, MMSlotTrackerAArch64) {
205 auto TM = createTargetMachine(TT: Triple::normalize(Str: "aarch64--"), CPU: "", FS: "");
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---
217name: test0
218liveins:
219 - { reg: '$x0', virtual-reg: '%0' }
220body: |
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: *TM, MIRCode: MIRString, FnName: "test0", MMI);
231 ASSERT_TRUE(M);
232
233 auto *MF = MMI.getMachineFunction(F: *M->getFunction(Name: "test0"));
234 auto *MBB = MF->getBlockNumbered(N: 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(Name: "domain");
242 MDNode *Scope0 = MDB.createAnonymousAliasScope(Domain, Name: "scope0");
243 MDNode *Scope1 = MDB.createAnonymousAliasScope(Domain, Name: "scope1");
244 MDNode *Set0 = MDNode::get(Context, MDs: {Scope0});
245 MDNode *Set1 = MDNode::get(Context, MDs: {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(MMO: OldMMO, AAInfo);
254 MI.setMemRefs(MF&: *MF, MemRefs: NewMMO);
255
256 MachineModuleSlotTracker MST(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(L&: MDList);
272 for (auto &MD : MDList)
273 Collected.push_back(x: MD.second);
274
275 llvm::sort(C&: Generated);
276 llvm::sort(C&: Collected);
277 EXPECT_EQ(Collected, Generated);
278
279 // FileCheck the output from MIR printer.
280 std::string Output = print(PrintFn: [&](raw_ostream &OS) { printMIR(OS, MF: *MF); });
281 std::string CheckString = R"(
282CHECK: machineMetadataNodes:
283CHECK-DAG: ![[MMDOMAIN:[0-9]+]] = distinct !{!{{[0-9]+}}, !"domain"}
284CHECK-DAG: ![[MMSCOPE0:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope0"}
285CHECK-DAG: ![[MMSCOPE1:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope1"}
286CHECK-DAG: ![[MMSET0:[0-9]+]] = !{![[MMSCOPE0]]}
287CHECK-DAG: ![[MMSET1:[0-9]+]] = !{![[MMSCOPE1]]}
288CHECK: body:
289CHECK: %1:gpr32 = LDRWui %0, 0 :: (load (s32) from %ir.p, !alias.scope ![[MMSET0]], !noalias ![[MMSET1]])
290)";
291 EXPECT_TRUE(checkOutput(CheckString, Output));
292}
293
294TEST_F(MachineMetadataTest, isMetaInstruction) {
295 auto TM = createTargetMachine(TT: Triple::normalize(Str: "x86_64--"), CPU: "", FS: "");
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---
321name: test0
322machineFunctionInfo
323body: |
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: *TM, MIRCode: MIRString, FnName: "test0", MMI);
342 ASSERT_TRUE(M);
343
344 auto *MF = MMI.getMachineFunction(F: *M->getFunction(Name: "test0"));
345 auto *MBB = MF->getBlockNumbered(N: 0);
346
347 for (auto It = MBB->begin(); It != MBB->end(); ++It) {
348 MachineInstr &MI = *It;
349 ASSERT_TRUE(MI.isMetaInstruction());
350 }
351}
352
353TEST_F(MachineMetadataTest, MMSlotTrackerX64) {
354 auto TM = createTargetMachine(TT: Triple::normalize(Str: "x86_64--"), CPU: "", FS: "");
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---
366name: test0
367liveins:
368 - { reg: '$rdi', virtual-reg: '%0' }
369body: |
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: *TM, MIRCode: MIRString, FnName: "test0", MMI);
380 ASSERT_TRUE(M);
381
382 auto *MF = MMI.getMachineFunction(F: *M->getFunction(Name: "test0"));
383 auto *MBB = MF->getBlockNumbered(N: 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(Name: "domain");
392 MDNode *Scope0 = MDB.createAnonymousAliasScope(Domain, Name: "scope0");
393 MDNode *Scope1 = MDB.createAnonymousAliasScope(Domain, Name: "scope1");
394 MDNode *Set0 = MDNode::get(Context, MDs: {Scope0});
395 MDNode *Set1 = MDNode::get(Context, MDs: {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(MMO: OldMMO, AAInfo);
404 MI.setMemRefs(MF&: *MF, MemRefs: NewMMO);
405
406 MachineModuleSlotTracker MST(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(L&: MDList);
422 for (auto &MD : MDList)
423 Collected.push_back(x: MD.second);
424
425 llvm::sort(C&: Generated);
426 llvm::sort(C&: Collected);
427 EXPECT_EQ(Collected, Generated);
428
429 // FileCheck the output from MIR printer.
430 std::string Output = print(PrintFn: [&](raw_ostream &OS) { printMIR(OS, MF: *MF); });
431 std::string CheckString = R"(
432CHECK: machineMetadataNodes:
433CHECK-DAG: ![[MMDOMAIN:[0-9]+]] = distinct !{!{{[0-9]+}}, !"domain"}
434CHECK-DAG: ![[MMSCOPE0:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope0"}
435CHECK-DAG: ![[MMSCOPE1:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope1"}
436CHECK-DAG: ![[MMSET0:[0-9]+]] = !{![[MMSCOPE0]]}
437CHECK-DAG: ![[MMSET1:[0-9]+]] = !{![[MMSCOPE1]]}
438CHECK: body:
439CHECK: %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
444TEST_F(MachineMetadataTest, MMSlotTrackerAMDGPU) {
445 auto TM = createTargetMachine(TT: Triple::normalize(Str: "amdgcn-amd-amdhsa"),
446 CPU: "gfx1010", FS: "");
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---
458name: test0
459liveins:
460 - { reg: '$vgpr0', virtual-reg: '%0' }
461 - { reg: '$vgpr1', virtual-reg: '%1' }
462 - { reg: '$sgpr30_sgpr31', virtual-reg: '%2' }
463body: |
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: *TM, MIRCode: MIRString, FnName: "test0", MMI);
478 ASSERT_TRUE(M);
479
480 auto *MF = MMI.getMachineFunction(F: *M->getFunction(Name: "test0"));
481 auto *MBB = MF->getBlockNumbered(N: 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(Name: "domain");
490 MDNode *Scope0 = MDB.createAnonymousAliasScope(Domain, Name: "scope0");
491 MDNode *Scope1 = MDB.createAnonymousAliasScope(Domain, Name: "scope1");
492 MDNode *Set0 = MDNode::get(Context, MDs: {Scope0});
493 MDNode *Set1 = MDNode::get(Context, MDs: {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(MMO: OldMMO, AAInfo);
502 MI.setMemRefs(MF&: *MF, MemRefs: NewMMO);
503
504 MachineModuleSlotTracker MST(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(L&: MDList);
521 for (auto &MD : MDList)
522 Collected.push_back(x: MD.second);
523
524 llvm::sort(C&: Generated);
525 llvm::sort(C&: Collected);
526 EXPECT_EQ(Collected, Generated);
527
528 // FileCheck the output from MIR printer.
529 std::string Output = print(PrintFn: [&](raw_ostream &OS) { printMIR(OS, MF: *MF); });
530 std::string CheckString = R"(
531CHECK: machineMetadataNodes:
532CHECK-DAG: ![[MMDOMAIN:[0-9]+]] = distinct !{!{{[0-9]+}}, !"domain"}
533CHECK-DAG: ![[MMSCOPE0:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope0"}
534CHECK-DAG: ![[MMSCOPE1:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope1"}
535CHECK-DAG: ![[MMSET0:[0-9]+]] = !{![[MMSCOPE0]]}
536CHECK-DAG: ![[MMSET1:[0-9]+]] = !{![[MMSCOPE1]]}
537CHECK: body:
538CHECK: %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
543TEST_F(MachineMetadataTest, TiedOpsRewritten) {
544 auto TM = createTargetMachine(TT: Triple::normalize(Str: "powerpc64--"), CPU: "", FS: "");
545 if (!TM)
546 GTEST_SKIP();
547 StringRef MIRString = R"MIR(
548---
549name: foo
550alignment: 16
551tracksRegLiveness: true
552frameInfo:
553 maxAlignment: 16
554machineFunctionInfo: {}
555body: |
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: *TM, MIRCode: MIRString, FnName: "foo", MMI);
567 ASSERT_TRUE(M);
568 auto *MF = MMI.getMachineFunction(F: *M->getFunction(Name: "foo"));
569 MachineFunctionProperties &Properties = MF->getProperties();
570 ASSERT_TRUE(Properties.hasProperty(
571 MachineFunctionProperties::Property::TiedOpsRewritten));
572}
573
574TEST_F(MachineMetadataTest, NoTiedOpsRewritten) {
575 auto TM = createTargetMachine(TT: Triple::normalize(Str: "powerpc64--"), CPU: "", FS: "");
576 if (!TM)
577 GTEST_SKIP();
578 StringRef MIRString = R"MIR(
579---
580name: foo
581alignment: 16
582tracksRegLiveness: true
583frameInfo:
584 maxAlignment: 16
585machineFunctionInfo: {}
586body: |
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: *TM, MIRCode: MIRString, FnName: "foo", MMI);
598 ASSERT_TRUE(M);
599 auto *MF = MMI.getMachineFunction(F: *M->getFunction(Name: "foo"));
600 MachineFunctionProperties &Properties = MF->getProperties();
601 ASSERT_FALSE(Properties.hasProperty(
602 MachineFunctionProperties::Property::TiedOpsRewritten));
603}
604

source code of llvm/unittests/MIR/MachineMetadata.cpp