llvm-project/llvm/unittests/MIR/MachineMetadata.cpp
Philip Reames eb44226986 [CodeGen] Introduce a generic MEMBARRIER instruction [mostly-nfc]
This is a follow up to D141317 which extends the common code to include a target independent pseudo instruction. This is an alternative to (subset of) D92842 which tries to be as close to NFC as possible.

A couple things to call out.
* The test change in X86 is because we loose the scheduling information on the instruction. However, I think this was actually a bug in x86 since no instruction was emitted for a MEMBARRIER. Concluding that a meta instruction has latency just seems wrong?
* I intentionally left some parts of D92842 out. Specifically, several of the changes in the X86 code (data independence and outlining) appear functional, and likely worthy of their own review. Additionally, I'm not handling ARM/AArch64 at all. Those targets need the ordering whereas none of the others do. I want to get this in and tested before retrofitting in ordering to support those targets.

Differential Revision: https://reviews.llvm.org/D141408
2023-01-11 07:26:27 -08:00

605 lines
20 KiB
C++

//===- MachineInstrBundleIteratorTest.cpp ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MIRParser/MIRParser.h"
#include "llvm/CodeGen/MIRPrinter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineModuleSlotTracker.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/FileCheck/FileCheck.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "gtest/gtest.h"
using namespace llvm;
class MachineMetadataTest : public testing::Test {
public:
MachineMetadataTest() {}
protected:
LLVMContext Context;
std::unique_ptr<Module> M;
std::unique_ptr<MIRParser> MIR;
static void SetUpTestCase() {
InitializeAllTargetInfos();
InitializeAllTargets();
InitializeAllTargetMCs();
}
void SetUp() override { M = std::make_unique<Module>("Dummy", Context); }
void addHooks(ModuleSlotTracker &MST, const MachineOperand &MO) {
// Setup hooks to assign slot numbers for the specified machine metadata.
MST.setProcessHook([&MO](AbstractSlotTrackerStorage *AST, const Module *M,
bool ShouldInitializeAllMetadata) {
if (ShouldInitializeAllMetadata) {
if (MO.isMetadata())
AST->createMetadataSlot(MO.getMetadata());
}
});
MST.setProcessHook([&MO](AbstractSlotTrackerStorage *AST, const Function *F,
bool ShouldInitializeAllMetadata) {
if (!ShouldInitializeAllMetadata) {
if (MO.isMetadata())
AST->createMetadataSlot(MO.getMetadata());
}
});
}
std::unique_ptr<LLVMTargetMachine>
createTargetMachine(std::string TT, StringRef CPU, StringRef FS) {
std::string Error;
const Target *T = TargetRegistry::lookupTarget(TT, Error);
if (!T)
return nullptr;
TargetOptions Options;
return std::unique_ptr<LLVMTargetMachine>(
static_cast<LLVMTargetMachine *>(T->createTargetMachine(
TT, CPU, FS, Options, std::nullopt, std::nullopt)));
}
std::unique_ptr<Module> parseMIR(const TargetMachine &TM, StringRef MIRCode,
const char *FnName, MachineModuleInfo &MMI) {
SMDiagnostic Diagnostic;
std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode);
MIR = createMIRParser(std::move(MBuffer), Context);
if (!MIR)
return nullptr;
std::unique_ptr<Module> Mod = MIR->parseIRModule();
if (!Mod)
return nullptr;
Mod->setDataLayout(TM.createDataLayout());
if (MIR->parseMachineFunctions(*Mod, MMI)) {
M.reset();
return nullptr;
}
return Mod;
}
};
// Helper to dump the printer output into a string.
static std::string print(std::function<void(raw_ostream &OS)> PrintFn) {
std::string Str;
raw_string_ostream OS(Str);
PrintFn(OS);
OS.flush();
return Str;
}
TEST_F(MachineMetadataTest, TrivialHook) {
// Verify that post-process hook is invoked to assign slot numbers for
// machine metadata.
ASSERT_TRUE(M);
// Create a MachineOperand with a metadata and print it.
Metadata *MDS = MDString::get(Context, "foo");
MDNode *Node = MDNode::get(Context, MDS);
MachineOperand MO = MachineOperand::CreateMetadata(Node);
// Checking some preconditions on the newly created
// MachineOperand.
ASSERT_TRUE(MO.isMetadata());
ASSERT_EQ(MO.getMetadata(), Node);
ModuleSlotTracker MST(M.get());
addHooks(MST, MO);
// Print a MachineOperand containing a metadata node.
EXPECT_EQ("!0", print([&](raw_ostream &OS) {
MO.print(OS, MST, LLT{}, /*OpIdx*/ ~0U, /*PrintDef=*/false,
/*IsStandalone=*/false,
/*ShouldPrintRegisterTies=*/false, /*TiedOperandIdx=*/0,
/*TRI=*/nullptr,
/*IntrinsicInfo=*/nullptr);
}));
// Print the definition of that metadata node.
EXPECT_EQ("!0 = !{!\"foo\"}",
print([&](raw_ostream &OS) { Node->print(OS, MST); }));
}
TEST_F(MachineMetadataTest, BasicHook) {
// Verify that post-process hook is invoked to assign slot numbers for
// machine metadata. When both LLVM IR and machine IR contain metadata,
// ensure that machine metadata is always assigned after LLVM IR.
ASSERT_TRUE(M);
// Create a MachineOperand with a metadata and print it.
Metadata *MachineMDS = MDString::get(Context, "foo");
MDNode *MachineNode = MDNode::get(Context, MachineMDS);
MachineOperand MO = MachineOperand::CreateMetadata(MachineNode);
// Checking some preconditions on the newly created
// MachineOperand.
ASSERT_TRUE(MO.isMetadata());
ASSERT_EQ(MO.getMetadata(), MachineNode);
// Create metadata in LLVM IR.
NamedMDNode *MD = M->getOrInsertNamedMetadata("namedmd");
Metadata *MDS = MDString::get(Context, "bar");
MDNode *Node = MDNode::get(Context, MDS);
MD->addOperand(Node);
ModuleSlotTracker MST(M.get());
addHooks(MST, MO);
// Print a MachineOperand containing a metadata node.
EXPECT_EQ("!1", print([&](raw_ostream &OS) {
MO.print(OS, MST, LLT{}, /*OpIdx*/ ~0U, /*PrintDef=*/false,
/*IsStandalone=*/false,
/*ShouldPrintRegisterTies=*/false, /*TiedOperandIdx=*/0,
/*TRI=*/nullptr,
/*IntrinsicInfo=*/nullptr);
}));
// Print the definition of these unnamed metadata nodes.
EXPECT_EQ("!0 = !{!\"bar\"}",
print([&](raw_ostream &OS) { Node->print(OS, MST); }));
EXPECT_EQ("!1 = !{!\"foo\"}",
print([&](raw_ostream &OS) { MachineNode->print(OS, MST); }));
}
static bool checkOutput(std::string CheckString, std::string Output) {
auto CheckBuffer = MemoryBuffer::getMemBuffer(CheckString, "");
auto OutputBuffer = MemoryBuffer::getMemBuffer(Output, "Output", false);
SmallString<4096> CheckFileBuffer;
FileCheckRequest Req;
FileCheck FC(Req);
StringRef CheckFileText =
FC.CanonicalizeFile(*CheckBuffer.get(), CheckFileBuffer);
SourceMgr SM;
SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(CheckFileText, "CheckFile"),
SMLoc());
Regex PrefixRE = FC.buildCheckPrefixRegex();
if (FC.readCheckFile(SM, CheckFileText, PrefixRE))
return false;
auto OutBuffer = OutputBuffer->getBuffer();
SM.AddNewSourceBuffer(std::move(OutputBuffer), SMLoc());
return FC.checkInput(SM, OutBuffer);
}
TEST_F(MachineMetadataTest, MMSlotTrackerAArch64) {
auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");
if (!TM)
GTEST_SKIP();
StringRef MIRString = R"MIR(
--- |
define i32 @test0(i32* %p) {
%r = load i32, i32* %p, align 4
ret i32 %r
}
...
---
name: test0
liveins:
- { reg: '$x0', virtual-reg: '%0' }
body: |
bb.0 (%ir-block.0):
liveins: $x0
%0:gpr64common = COPY $x0
%1:gpr32 = LDRWui %0, 0 :: (load (s32) from %ir.p)
...
)MIR";
MachineModuleInfo MMI(TM.get());
M = parseMIR(*TM, MIRString, "test0", MMI);
ASSERT_TRUE(M);
auto *MF = MMI.getMachineFunction(*M->getFunction("test0"));
auto *MBB = MF->getBlockNumbered(0);
auto &MI = MBB->back();
ASSERT_TRUE(MI.hasOneMemOperand());
// Create and attached scoped AA metadata on that instruction with one MMO.
MDBuilder MDB(Context);
MDNode *Domain = MDB.createAnonymousAliasScopeDomain("domain");
MDNode *Scope0 = MDB.createAnonymousAliasScope(Domain, "scope0");
MDNode *Scope1 = MDB.createAnonymousAliasScope(Domain, "scope1");
MDNode *Set0 = MDNode::get(Context, {Scope0});
MDNode *Set1 = MDNode::get(Context, {Scope1});
AAMDNodes AAInfo;
AAInfo.TBAA = AAInfo.TBAAStruct = nullptr;
AAInfo.Scope = Set0;
AAInfo.NoAlias = Set1;
auto *OldMMO = MI.memoperands().front();
auto *NewMMO = MF->getMachineMemOperand(OldMMO, AAInfo);
MI.setMemRefs(*MF, NewMMO);
MachineModuleSlotTracker MST(MF);
// Print that MI with new machine metadata, which slot numbers should be
// assigned.
EXPECT_EQ("%1:gpr32 = LDRWui %0, 0 :: (load (s32) from %ir.p, "
"!alias.scope !0, !noalias !3)",
print([&](raw_ostream &OS) {
MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false,
/*SkipDebugLoc=*/false, /*AddNewLine=*/false);
}));
std::vector<const MDNode *> Generated{Domain, Scope0, Scope1, Set0, Set1};
// Examine machine metadata collected. They should match ones
// afore-generated.
std::vector<const MDNode *> Collected;
MachineModuleSlotTracker::MachineMDNodeListType MDList;
MST.collectMachineMDNodes(MDList);
for (auto &MD : MDList)
Collected.push_back(MD.second);
llvm::sort(Generated);
llvm::sort(Collected);
EXPECT_EQ(Collected, Generated);
// FileCheck the output from MIR printer.
std::string Output = print([&](raw_ostream &OS) { printMIR(OS, *MF); });
std::string CheckString = R"(
CHECK: machineMetadataNodes:
CHECK-DAG: ![[MMDOMAIN:[0-9]+]] = distinct !{!{{[0-9]+}}, !"domain"}
CHECK-DAG: ![[MMSCOPE0:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope0"}
CHECK-DAG: ![[MMSCOPE1:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope1"}
CHECK-DAG: ![[MMSET0:[0-9]+]] = !{![[MMSCOPE0]]}
CHECK-DAG: ![[MMSET1:[0-9]+]] = !{![[MMSCOPE1]]}
CHECK: body:
CHECK: %1:gpr32 = LDRWui %0, 0 :: (load (s32) from %ir.p, !alias.scope ![[MMSET0]], !noalias ![[MMSET1]])
)";
EXPECT_TRUE(checkOutput(CheckString, Output));
}
TEST_F(MachineMetadataTest, isMetaInstruction) {
auto TM = createTargetMachine(Triple::normalize("x86_64--"), "", "");
if (!TM)
GTEST_SKIP();
StringRef MIRString = R"MIR(
--- |
define void @test0(i32 %b) {
ret void
}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "a.c", directory: "/tmp")
!2 = !{i32 7, !"Dwarf Version", i32 4}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !{i32 1, !"wchar_size", i32 4}
!5 = !{i32 7, !"uwtable", i32 1}
!6 = !{i32 7, !"frame-pointer", i32 2}
!7 = !{!""}
!8 = distinct !DISubprogram(name: "test0", scope: !1, file: !1, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !12)
!9 = !DISubroutineType(types: !10)
!10 = !{null, !11}
!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!12 = !{}
!13 = !DILocalVariable(name: "b", arg: 1, scope: !8, file: !1, line: 1, type: !11)
!14 = !DILocation(line: 1, column: 16, scope: !8)
...
---
name: test0
machineFunctionInfo
body: |
bb.0:
$rdi = IMPLICIT_DEF
KILL $rsi
CFI_INSTRUCTION undefined $rax
EH_LABEL 0
GC_LABEL 0
DBG_VALUE $rax, $noreg, !13, !DIExpression(), debug-location !14
DBG_LABEL 0
LIFETIME_START 0
LIFETIME_END 0
PSEUDO_PROBE 6699318081062747564, 1, 0, 0
$xmm0 = ARITH_FENCE $xmm0
MEMBARRIER
...
)MIR";
MachineModuleInfo MMI(TM.get());
M = parseMIR(*TM, MIRString, "test0", MMI);
ASSERT_TRUE(M);
auto *MF = MMI.getMachineFunction(*M->getFunction("test0"));
auto *MBB = MF->getBlockNumbered(0);
for (auto It = MBB->begin(); It != MBB->end(); ++It) {
MachineInstr &MI = *It;
ASSERT_TRUE(MI.isMetaInstruction());
}
}
TEST_F(MachineMetadataTest, MMSlotTrackerX64) {
auto TM = createTargetMachine(Triple::normalize("x86_64--"), "", "");
if (!TM)
GTEST_SKIP();
StringRef MIRString = R"MIR(
--- |
define i32 @test0(i32* %p) {
%r = load i32, i32* %p, align 4
ret i32 %r
}
...
---
name: test0
liveins:
- { reg: '$rdi', virtual-reg: '%0' }
body: |
bb.0 (%ir-block.0):
liveins: $rdi
%0:gr64 = COPY $rdi
%1:gr32 = MOV32rm %0, 1, $noreg, 0, $noreg :: (load (s32) from %ir.p)
...
)MIR";
MachineModuleInfo MMI(TM.get());
M = parseMIR(*TM, MIRString, "test0", MMI);
ASSERT_TRUE(M);
auto *MF = MMI.getMachineFunction(*M->getFunction("test0"));
auto *MBB = MF->getBlockNumbered(0);
auto &MI = MBB->back();
ASSERT_FALSE(MI.memoperands_empty());
ASSERT_TRUE(MI.hasOneMemOperand());
// Create and attached scoped AA metadata on that instruction with one MMO.
MDBuilder MDB(Context);
MDNode *Domain = MDB.createAnonymousAliasScopeDomain("domain");
MDNode *Scope0 = MDB.createAnonymousAliasScope(Domain, "scope0");
MDNode *Scope1 = MDB.createAnonymousAliasScope(Domain, "scope1");
MDNode *Set0 = MDNode::get(Context, {Scope0});
MDNode *Set1 = MDNode::get(Context, {Scope1});
AAMDNodes AAInfo;
AAInfo.TBAA = AAInfo.TBAAStruct = nullptr;
AAInfo.Scope = Set0;
AAInfo.NoAlias = Set1;
auto *OldMMO = MI.memoperands().front();
auto *NewMMO = MF->getMachineMemOperand(OldMMO, AAInfo);
MI.setMemRefs(*MF, NewMMO);
MachineModuleSlotTracker MST(MF);
// Print that MI with new machine metadata, which slot numbers should be
// assigned.
EXPECT_EQ("%1:gr32 = MOV32rm %0, 1, $noreg, 0, $noreg :: (load (s32) from %ir.p, "
"!alias.scope !0, !noalias !3)",
print([&](raw_ostream &OS) {
MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false,
/*SkipDebugLoc=*/false, /*AddNewLine=*/false);
}));
std::vector<const MDNode *> Generated{Domain, Scope0, Scope1, Set0, Set1};
// Examine machine metadata collected. They should match ones
// afore-generated.
std::vector<const MDNode *> Collected;
MachineModuleSlotTracker::MachineMDNodeListType MDList;
MST.collectMachineMDNodes(MDList);
for (auto &MD : MDList)
Collected.push_back(MD.second);
llvm::sort(Generated);
llvm::sort(Collected);
EXPECT_EQ(Collected, Generated);
// FileCheck the output from MIR printer.
std::string Output = print([&](raw_ostream &OS) { printMIR(OS, *MF); });
std::string CheckString = R"(
CHECK: machineMetadataNodes:
CHECK-DAG: ![[MMDOMAIN:[0-9]+]] = distinct !{!{{[0-9]+}}, !"domain"}
CHECK-DAG: ![[MMSCOPE0:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope0"}
CHECK-DAG: ![[MMSCOPE1:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope1"}
CHECK-DAG: ![[MMSET0:[0-9]+]] = !{![[MMSCOPE0]]}
CHECK-DAG: ![[MMSET1:[0-9]+]] = !{![[MMSCOPE1]]}
CHECK: body:
CHECK: %1:gr32 = MOV32rm %0, 1, $noreg, 0, $noreg :: (load (s32) from %ir.p, !alias.scope ![[MMSET0]], !noalias ![[MMSET1]])
)";
EXPECT_TRUE(checkOutput(CheckString, Output));
}
TEST_F(MachineMetadataTest, MMSlotTrackerAMDGPU) {
auto TM = createTargetMachine(Triple::normalize("amdgcn-amd-amdhsa"),
"gfx1010", "");
if (!TM)
GTEST_SKIP();
StringRef MIRString = R"MIR(
--- |
define i32 @test0(i32* %p) {
%r = load i32, i32* %p, align 4
ret i32 %r
}
...
---
name: test0
liveins:
- { reg: '$vgpr0', virtual-reg: '%0' }
- { reg: '$vgpr1', virtual-reg: '%1' }
- { reg: '$sgpr30_sgpr31', virtual-reg: '%2' }
body: |
bb.0 (%ir-block.0):
liveins: $vgpr0, $vgpr1, $sgpr30_sgpr31
%2:sreg_64 = COPY $sgpr30_sgpr31
%1:vgpr_32 = COPY $vgpr1
%0:vgpr_32 = COPY $vgpr0
%8:vreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
%6:vreg_64 = COPY %8
%5:vgpr_32 = FLAT_LOAD_DWORD killed %6, 0, 0, implicit $exec, implicit $flat_scr :: (load (s32) from %ir.p)
...
)MIR";
MachineModuleInfo MMI(TM.get());
M = parseMIR(*TM, MIRString, "test0", MMI);
ASSERT_TRUE(M);
auto *MF = MMI.getMachineFunction(*M->getFunction("test0"));
auto *MBB = MF->getBlockNumbered(0);
auto &MI = MBB->back();
ASSERT_FALSE(MI.memoperands_empty());
ASSERT_TRUE(MI.hasOneMemOperand());
// Create and attached scoped AA metadata on that instruction with one MMO.
MDBuilder MDB(Context);
MDNode *Domain = MDB.createAnonymousAliasScopeDomain("domain");
MDNode *Scope0 = MDB.createAnonymousAliasScope(Domain, "scope0");
MDNode *Scope1 = MDB.createAnonymousAliasScope(Domain, "scope1");
MDNode *Set0 = MDNode::get(Context, {Scope0});
MDNode *Set1 = MDNode::get(Context, {Scope1});
AAMDNodes AAInfo;
AAInfo.TBAA = AAInfo.TBAAStruct = nullptr;
AAInfo.Scope = Set0;
AAInfo.NoAlias = Set1;
auto *OldMMO = MI.memoperands().front();
auto *NewMMO = MF->getMachineMemOperand(OldMMO, AAInfo);
MI.setMemRefs(*MF, NewMMO);
MachineModuleSlotTracker MST(MF);
// Print that MI with new machine metadata, which slot numbers should be
// assigned.
EXPECT_EQ(
"%5:vgpr_32 = FLAT_LOAD_DWORD killed %4, 0, 0, implicit $exec, implicit "
"$flat_scr :: (load (s32) from %ir.p, !alias.scope !0, !noalias !3)",
print([&](raw_ostream &OS) {
MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false,
/*SkipDebugLoc=*/false, /*AddNewLine=*/false);
}));
std::vector<const MDNode *> Generated{Domain, Scope0, Scope1, Set0, Set1};
// Examine machine metadata collected. They should match ones
// afore-generated.
std::vector<const MDNode *> Collected;
MachineModuleSlotTracker::MachineMDNodeListType MDList;
MST.collectMachineMDNodes(MDList);
for (auto &MD : MDList)
Collected.push_back(MD.second);
llvm::sort(Generated);
llvm::sort(Collected);
EXPECT_EQ(Collected, Generated);
// FileCheck the output from MIR printer.
std::string Output = print([&](raw_ostream &OS) { printMIR(OS, *MF); });
std::string CheckString = R"(
CHECK: machineMetadataNodes:
CHECK-DAG: ![[MMDOMAIN:[0-9]+]] = distinct !{!{{[0-9]+}}, !"domain"}
CHECK-DAG: ![[MMSCOPE0:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope0"}
CHECK-DAG: ![[MMSCOPE1:[0-9]+]] = distinct !{!{{[0-9]+}}, ![[MMDOMAIN]], !"scope1"}
CHECK-DAG: ![[MMSET0:[0-9]+]] = !{![[MMSCOPE0]]}
CHECK-DAG: ![[MMSET1:[0-9]+]] = !{![[MMSCOPE1]]}
CHECK: body:
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]])
)";
EXPECT_TRUE(checkOutput(CheckString, Output));
}
TEST_F(MachineMetadataTest, TiedOpsRewritten) {
auto TM = createTargetMachine(Triple::normalize("powerpc64--"), "", "");
if (!TM)
GTEST_SKIP();
StringRef MIRString = R"MIR(
---
name: foo
alignment: 16
tracksRegLiveness: true
frameInfo:
maxAlignment: 16
machineFunctionInfo: {}
body: |
bb.0:
liveins: $r3
%0:gprc = COPY $r3
%0 = RLWIMI killed %0, $r3, 1, 0, 30
$r3 = COPY %0
BLR8 implicit $r3, implicit $lr8, implicit $rm
...
)MIR";
MachineModuleInfo MMI(TM.get());
M = parseMIR(*TM, MIRString, "foo", MMI);
ASSERT_TRUE(M);
auto *MF = MMI.getMachineFunction(*M->getFunction("foo"));
MachineFunctionProperties &Properties = MF->getProperties();
ASSERT_TRUE(Properties.hasProperty(
MachineFunctionProperties::Property::TiedOpsRewritten));
}
TEST_F(MachineMetadataTest, NoTiedOpsRewritten) {
auto TM = createTargetMachine(Triple::normalize("powerpc64--"), "", "");
if (!TM)
GTEST_SKIP();
StringRef MIRString = R"MIR(
---
name: foo
alignment: 16
tracksRegLiveness: true
frameInfo:
maxAlignment: 16
machineFunctionInfo: {}
body: |
bb.0:
liveins: $r3
%0:gprc = COPY $r3
%1:gprc = RLWIMI killed %0, $r3, 1, 0, 30
$r3 = COPY %1
BLR8 implicit $r3, implicit $lr8, implicit $rm
...
)MIR";
MachineModuleInfo MMI(TM.get());
M = parseMIR(*TM, MIRString, "foo", MMI);
ASSERT_TRUE(M);
auto *MF = MMI.getMachineFunction(*M->getFunction("foo"));
MachineFunctionProperties &Properties = MF->getProperties();
ASSERT_FALSE(Properties.hasProperty(
MachineFunctionProperties::Property::TiedOpsRewritten));
}