1 //===- MachineInstrBundleIteratorTest.cpp ---------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
34 class MachineMetadataTest
: public testing::Test
{
36 MachineMetadataTest() {}
40 std::unique_ptr
<Module
> M
;
41 std::unique_ptr
<MIRParser
> MIR
;
43 static void SetUpTestCase() {
44 InitializeAllTargetInfos();
45 InitializeAllTargets();
46 InitializeAllTargetMCs();
49 void SetUp() override
{ M
= std::make_unique
<Module
>("Dummy", Context
); }
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
) {
57 AST
->createMetadataSlot(MO
.getMetadata());
60 MST
.setProcessHook([&MO
](AbstractSlotTrackerStorage
*AST
, const Function
*F
,
61 bool ShouldInitializeAllMetadata
) {
62 if (!ShouldInitializeAllMetadata
) {
64 AST
->createMetadataSlot(MO
.getMetadata());
69 std::unique_ptr
<LLVMTargetMachine
>
70 createTargetMachine(std::string TT
, StringRef CPU
, StringRef FS
) {
72 const Target
*T
= TargetRegistry::lookupTarget(TT
, Error
);
75 TargetOptions Options
;
76 return std::unique_ptr
<LLVMTargetMachine
>(
77 static_cast<LLVMTargetMachine
*>(T
->createTargetMachine(
78 TT
, CPU
, FS
, Options
, std::nullopt
, std::nullopt
)));
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
);
89 std::unique_ptr
<Module
> Mod
= MIR
->parseIRModule();
93 Mod
->setDataLayout(TM
.createDataLayout());
95 if (MIR
->parseMachineFunctions(*Mod
, MMI
)) {
104 // Helper to dump the printer output into a string.
105 static std::string
print(std::function
<void(raw_ostream
&OS
)> PrintFn
) {
107 raw_string_ostream
OS(Str
);
113 TEST_F(MachineMetadataTest
, TrivialHook
) {
114 // Verify that post-process hook is invoked to assign slot numbers for
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
);
123 // Checking some preconditions on the newly created
125 ASSERT_TRUE(MO
.isMetadata());
126 ASSERT_EQ(MO
.getMetadata(), Node
);
128 ModuleSlotTracker
MST(M
.get());
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,
137 /*IntrinsicInfo=*/nullptr);
139 // Print the definition of that metadata node.
140 EXPECT_EQ("!0 = !{!\"foo\"}",
141 print([&](raw_ostream
&OS
) { Node
->print(OS
, MST
); }));
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.
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
);
155 // Checking some preconditions on the newly created
157 ASSERT_TRUE(MO
.isMetadata());
158 ASSERT_EQ(MO
.getMetadata(), MachineNode
);
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
);
166 ModuleSlotTracker
MST(M
.get());
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,
175 /*IntrinsicInfo=*/nullptr);
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
); }));
184 static bool checkOutput(std::string CheckString
, std::string Output
) {
185 auto CheckBuffer
= MemoryBuffer::getMemBuffer(CheckString
, "");
186 auto OutputBuffer
= MemoryBuffer::getMemBuffer(Output
, "Output", false);
188 SmallString
<4096> CheckFileBuffer
;
189 FileCheckRequest Req
;
191 StringRef CheckFileText
= FC
.CanonicalizeFile(*CheckBuffer
, CheckFileBuffer
);
194 SM
.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(CheckFileText
, "CheckFile"),
196 if (FC
.readCheckFile(SM
, CheckFileText
))
199 auto OutBuffer
= OutputBuffer
->getBuffer();
200 SM
.AddNewSourceBuffer(std::move(OutputBuffer
), SMLoc());
201 return FC
.checkInput(SM
, OutBuffer
);
204 TEST_F(MachineMetadataTest
, MMSlotTrackerAArch64
) {
205 auto TM
= createTargetMachine(Triple::normalize("aarch64--"), "", "");
209 StringRef MIRString
= R
"MIR(
211 define i32 @test0(i32* %p) {
212 %r = load i32, i32* %p, align 4
219 - { reg: '$x0', virtual-reg: '%0' }
224 %0:gpr64common = COPY $x0
225 %1:gpr32 = LDRWui %0, 0 :: (load (s32) from %ir.p)
229 MachineModuleInfo
MMI(TM
.get());
230 M
= parseMIR(*TM
, MIRString
, "test0", MMI
);
233 auto *MF
= MMI
.getMachineFunction(*M
->getFunction("test0"));
234 auto *MBB
= MF
->getBlockNumbered(0);
236 auto &MI
= MBB
->back();
237 ASSERT_TRUE(MI
.hasOneMemOperand());
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
});
248 AAInfo
.TBAA
= AAInfo
.TBAAStruct
= nullptr;
250 AAInfo
.NoAlias
= Set1
;
252 auto *OldMMO
= MI
.memoperands().front();
253 auto *NewMMO
= MF
->getMachineMemOperand(OldMMO
, AAInfo
);
254 MI
.setMemRefs(*MF
, NewMMO
);
256 MachineModuleSlotTracker
MST(MF
);
257 // Print that MI with new machine metadata, which slot numbers should be
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);
266 std::vector
<const MDNode
*> Generated
{Domain
, Scope0
, Scope1
, Set0
, Set1
};
267 // Examine machine metadata collected. They should match ones
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
);
275 llvm::sort(Generated
);
276 llvm::sort(Collected
);
277 EXPECT_EQ(Collected
, Generated
);
279 // FileCheck the output from MIR printer.
280 std::string Output
= print([&](raw_ostream
&OS
) { printMIR(OS
, *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]]}
289 CHECK: %1:gpr32 = LDRWui %0, 0 :: (load (s32) from %ir.p, !alias.scope ![[MMSET0]], !noalias ![[MMSET1]])
291 EXPECT_TRUE(checkOutput(CheckString
, Output
));
294 TEST_F(MachineMetadataTest
, isMetaInstruction
) {
295 auto TM
= createTargetMachine(Triple::normalize("x86_64--"), "", "");
299 StringRef MIRString
= R
"MIR(
301 define void @test0(i32 %b) {
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}
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)
315 !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
317 !13 = !DILocalVariable(name: "b
", arg: 1, scope: !8, file: !1, line: 1, type: !11)
318 !14 = !DILocation(line: 1, column: 16, scope: !8)
327 CFI_INSTRUCTION undefined $rax
330 DBG_VALUE $rax, $noreg, !13, !DIExpression(), debug-location !14
334 PSEUDO_PROBE 6699318081062747564, 1, 0, 0
335 $xmm0 = ARITH_FENCE $xmm0
340 MachineModuleInfo
MMI(TM
.get());
341 M
= parseMIR(*TM
, MIRString
, "test0", MMI
);
344 auto *MF
= MMI
.getMachineFunction(*M
->getFunction("test0"));
345 auto *MBB
= MF
->getBlockNumbered(0);
347 for (auto It
= MBB
->begin(); It
!= MBB
->end(); ++It
) {
348 MachineInstr
&MI
= *It
;
349 ASSERT_TRUE(MI
.isMetaInstruction());
353 TEST_F(MachineMetadataTest
, MMSlotTrackerX64
) {
354 auto TM
= createTargetMachine(Triple::normalize("x86_64--"), "", "");
358 StringRef MIRString
= R
"MIR(
360 define i32 @test0(i32* %p) {
361 %r = load i32, i32* %p, align 4
368 - { reg: '$rdi', virtual-reg: '%0' }
374 %1:gr32 = MOV32rm %0, 1, $noreg, 0, $noreg :: (load (s32) from %ir.p)
378 MachineModuleInfo
MMI(TM
.get());
379 M
= parseMIR(*TM
, MIRString
, "test0", MMI
);
382 auto *MF
= MMI
.getMachineFunction(*M
->getFunction("test0"));
383 auto *MBB
= MF
->getBlockNumbered(0);
385 auto &MI
= MBB
->back();
386 ASSERT_FALSE(MI
.memoperands_empty());
387 ASSERT_TRUE(MI
.hasOneMemOperand());
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
});
398 AAInfo
.TBAA
= AAInfo
.TBAAStruct
= nullptr;
400 AAInfo
.NoAlias
= Set1
;
402 auto *OldMMO
= MI
.memoperands().front();
403 auto *NewMMO
= MF
->getMachineMemOperand(OldMMO
, AAInfo
);
404 MI
.setMemRefs(*MF
, NewMMO
);
406 MachineModuleSlotTracker
MST(MF
);
407 // Print that MI with new machine metadata, which slot numbers should be
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);
416 std::vector
<const MDNode
*> Generated
{Domain
, Scope0
, Scope1
, Set0
, Set1
};
417 // Examine machine metadata collected. They should match ones
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
);
425 llvm::sort(Generated
);
426 llvm::sort(Collected
);
427 EXPECT_EQ(Collected
, Generated
);
429 // FileCheck the output from MIR printer.
430 std::string Output
= print([&](raw_ostream
&OS
) { printMIR(OS
, *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]]}
439 CHECK: %1:gr32 = MOV32rm %0, 1, $noreg, 0, $noreg :: (load (s32) from %ir.p, !alias.scope ![[MMSET0]], !noalias ![[MMSET1]])
441 EXPECT_TRUE(checkOutput(CheckString
, Output
));
444 TEST_F(MachineMetadataTest
, MMSlotTrackerAMDGPU
) {
445 auto TM
= createTargetMachine(Triple::normalize("amdgcn-amd-amdhsa"),
450 StringRef MIRString
= R
"MIR(
452 define i32 @test0(i32* %p) {
453 %r = load i32, i32* %p, align 4
460 - { reg: '$vgpr0', virtual-reg: '%0' }
461 - { reg: '$vgpr1', virtual-reg: '%1' }
462 - { reg: '$sgpr30_sgpr31', virtual-reg: '%2' }
465 liveins: $vgpr0, $vgpr1, $sgpr30_sgpr31
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
472 %5:vgpr_32 = FLAT_LOAD_DWORD killed %6, 0, 0, implicit $exec, implicit $flat_scr :: (load (s32) from %ir.p)
476 MachineModuleInfo
MMI(TM
.get());
477 M
= parseMIR(*TM
, MIRString
, "test0", MMI
);
480 auto *MF
= MMI
.getMachineFunction(*M
->getFunction("test0"));
481 auto *MBB
= MF
->getBlockNumbered(0);
483 auto &MI
= MBB
->back();
484 ASSERT_FALSE(MI
.memoperands_empty());
485 ASSERT_TRUE(MI
.hasOneMemOperand());
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
});
496 AAInfo
.TBAA
= AAInfo
.TBAAStruct
= nullptr;
498 AAInfo
.NoAlias
= Set1
;
500 auto *OldMMO
= MI
.memoperands().front();
501 auto *NewMMO
= MF
->getMachineMemOperand(OldMMO
, AAInfo
);
502 MI
.setMemRefs(*MF
, NewMMO
);
504 MachineModuleSlotTracker
MST(MF
);
505 // Print that MI with new machine metadata, which slot numbers should be
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);
515 std::vector
<const MDNode
*> Generated
{Domain
, Scope0
, Scope1
, Set0
, Set1
};
516 // Examine machine metadata collected. They should match ones
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
);
524 llvm::sort(Generated
);
525 llvm::sort(Collected
);
526 EXPECT_EQ(Collected
, Generated
);
528 // FileCheck the output from MIR printer.
529 std::string Output
= print([&](raw_ostream
&OS
) { printMIR(OS
, *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]]}
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]])
540 EXPECT_TRUE(checkOutput(CheckString
, Output
));
543 TEST_F(MachineMetadataTest
, TiedOpsRewritten
) {
544 auto TM
= createTargetMachine(Triple::normalize("powerpc64--"), "", "");
547 StringRef MIRString
= R
"MIR(
551 tracksRegLiveness: true
554 machineFunctionInfo: {}
559 %0 = RLWIMI killed %0, $r3, 1, 0, 30
561 BLR8 implicit $r3, implicit $lr8, implicit $rm
565 MachineModuleInfo
MMI(TM
.get());
566 M
= parseMIR(*TM
, MIRString
, "foo", MMI
);
568 auto *MF
= MMI
.getMachineFunction(*M
->getFunction("foo"));
569 MachineFunctionProperties
&Properties
= MF
->getProperties();
570 ASSERT_TRUE(Properties
.hasProperty(
571 MachineFunctionProperties::Property::TiedOpsRewritten
));
574 TEST_F(MachineMetadataTest
, NoTiedOpsRewritten
) {
575 auto TM
= createTargetMachine(Triple::normalize("powerpc64--"), "", "");
578 StringRef MIRString
= R
"MIR(
582 tracksRegLiveness: true
585 machineFunctionInfo: {}
590 %1:gprc = RLWIMI killed %0, $r3, 1, 0, 30
592 BLR8 implicit $r3, implicit $lr8, implicit $rm
596 MachineModuleInfo
MMI(TM
.get());
597 M
= parseMIR(*TM
, MIRString
, "foo", MMI
);
599 auto *MF
= MMI
.getMachineFunction(*M
->getFunction("foo"));
600 MachineFunctionProperties
&Properties
= MF
->getProperties();
601 ASSERT_FALSE(Properties
.hasProperty(
602 MachineFunctionProperties::Property::TiedOpsRewritten
));