diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
commit | eb11fae6d08f479c0799db45860a98af528fa6e7 (patch) | |
tree | 44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /unittests/CodeGen | |
parent | b8a2042aa938069e862750553db0e4d82d25822c (diff) |
Notes
Diffstat (limited to 'unittests/CodeGen')
-rw-r--r-- | unittests/CodeGen/CMakeLists.txt | 6 | ||||
-rw-r--r-- | unittests/CodeGen/GlobalISel/CMakeLists.txt | 9 | ||||
-rw-r--r-- | unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp | 167 | ||||
-rw-r--r-- | unittests/CodeGen/GlobalISel/PatternMatchTest.cpp | 493 | ||||
-rw-r--r-- | unittests/CodeGen/MachineInstrTest.cpp | 29 | ||||
-rw-r--r-- | unittests/CodeGen/MachineOperandTest.cpp | 16 | ||||
-rw-r--r-- | unittests/CodeGen/ScalableVectorMVTsTest.cpp | 2 |
7 files changed, 625 insertions, 97 deletions
diff --git a/unittests/CodeGen/CMakeLists.txt b/unittests/CodeGen/CMakeLists.txt index 05b72ce05b7b..3a9112740e0a 100644 --- a/unittests/CodeGen/CMakeLists.txt +++ b/unittests/CodeGen/CMakeLists.txt @@ -8,7 +8,7 @@ set(LLVM_LINK_COMPONENTS Target ) -set(CodeGenSources +add_llvm_unittest(CodeGenTests DIEHashTest.cpp LowLevelTypeTest.cpp MachineInstrBundleIteratorTest.cpp @@ -17,8 +17,4 @@ set(CodeGenSources ScalableVectorMVTsTest.cpp ) -add_llvm_unittest(CodeGenTests - ${CodeGenSources} - ) - add_subdirectory(GlobalISel) diff --git a/unittests/CodeGen/GlobalISel/CMakeLists.txt b/unittests/CodeGen/GlobalISel/CMakeLists.txt index 075bb44bc330..85f5dcd6d040 100644 --- a/unittests/CodeGen/GlobalISel/CMakeLists.txt +++ b/unittests/CodeGen/GlobalISel/CMakeLists.txt @@ -1,8 +1,15 @@ set(LLVM_LINK_COMPONENTS - GlobalISel + ${LLVM_TARGETS_TO_BUILD} CodeGen + Core + GlobalISel + MC + MIRParser + Support + Target ) add_llvm_unittest(GlobalISelTests LegalizerInfoTest.cpp + PatternMatchTest.cpp ) diff --git a/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp b/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp index ca7b47e87eda..42371e63da9d 100644 --- a/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp +++ b/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp @@ -12,22 +12,24 @@ #include "gtest/gtest.h" using namespace llvm; +using namespace LegalizeActions; // Define a couple of pretty printers to help debugging when things go wrong. namespace llvm { std::ostream & -operator<<(std::ostream &OS, const llvm::LegalizerInfo::LegalizeAction Act) { +operator<<(std::ostream &OS, const LegalizeAction Act) { switch (Act) { - case LegalizerInfo::Lower: OS << "Lower"; break; - case LegalizerInfo::Legal: OS << "Legal"; break; - case LegalizerInfo::NarrowScalar: OS << "NarrowScalar"; break; - case LegalizerInfo::WidenScalar: OS << "WidenScalar"; break; - case LegalizerInfo::FewerElements: OS << "FewerElements"; break; - case LegalizerInfo::MoreElements: OS << "MoreElements"; break; - case LegalizerInfo::Libcall: OS << "Libcall"; break; - case LegalizerInfo::Custom: OS << "Custom"; break; - case LegalizerInfo::Unsupported: OS << "Unsupported"; break; - case LegalizerInfo::NotFound: OS << "NotFound"; + case Lower: OS << "Lower"; break; + case Legal: OS << "Legal"; break; + case NarrowScalar: OS << "NarrowScalar"; break; + case WidenScalar: OS << "WidenScalar"; break; + case FewerElements: OS << "FewerElements"; break; + case MoreElements: OS << "MoreElements"; break; + case Libcall: OS << "Libcall"; break; + case Custom: OS << "Custom"; break; + case Unsupported: OS << "Unsupported"; break; + case NotFound: OS << "NotFound"; break; + case UseLegacyRules: OS << "UseLegacyRules"; break; } return OS; } @@ -51,7 +53,7 @@ TEST(LegalizerInfoTest, ScalarRISC) { // Typical RISCy set of operations based on AArch64. for (unsigned Op : {G_ADD, G_SUB}) { for (unsigned Size : {32, 64}) - L.setAction({Op, 0, LLT::scalar(Size)}, LegalizerInfo::Legal); + L.setAction({Op, 0, LLT::scalar(Size)}, Legal); L.setLegalizeScalarToDifferentSizeStrategy( Op, 0, LegalizerInfo::widenToLargerTypesAndNarrowToLargest); } @@ -60,29 +62,29 @@ TEST(LegalizerInfoTest, ScalarRISC) { for (unsigned opcode : {G_ADD, G_SUB}) { // Check we infer the correct types and actually do what we're told. - ASSERT_EQ(L.getAction({opcode, LLT::scalar(8)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32))); - ASSERT_EQ(L.getAction({opcode, LLT::scalar(16)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32))); - ASSERT_EQ(L.getAction({opcode, LLT::scalar(32)}), - std::make_pair(LegalizerInfo::Legal, LLT::scalar(32))); - ASSERT_EQ(L.getAction({opcode, LLT::scalar(64)}), - std::make_pair(LegalizerInfo::Legal, LLT::scalar(64))); + ASSERT_EQ(L.getAction({opcode, {LLT::scalar(8)}}), + LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); + ASSERT_EQ(L.getAction({opcode, {LLT::scalar(16)}}), + LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); + ASSERT_EQ(L.getAction({opcode, {LLT::scalar(32)}}), + LegalizeActionStep(Legal, 0, LLT{})); + ASSERT_EQ(L.getAction({opcode, {LLT::scalar(64)}}), + LegalizeActionStep(Legal, 0, LLT{})); // Make sure the default for over-sized types applies. - ASSERT_EQ(L.getAction({opcode, LLT::scalar(128)}), - std::make_pair(LegalizerInfo::NarrowScalar, LLT::scalar(64))); + ASSERT_EQ(L.getAction({opcode, {LLT::scalar(128)}}), + LegalizeActionStep(NarrowScalar, 0, LLT::scalar(64))); // Make sure we also handle unusual sizes - ASSERT_EQ(L.getAction({opcode, LLT::scalar(1)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32))); - ASSERT_EQ(L.getAction({opcode, LLT::scalar(31)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32))); - ASSERT_EQ(L.getAction({opcode, LLT::scalar(33)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(64))); - ASSERT_EQ(L.getAction({opcode, LLT::scalar(63)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(64))); - ASSERT_EQ(L.getAction({opcode, LLT::scalar(65)}), - std::make_pair(LegalizerInfo::NarrowScalar, LLT::scalar(64))); + ASSERT_EQ(L.getAction({opcode, {LLT::scalar(1)}}), + LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); + ASSERT_EQ(L.getAction({opcode, {LLT::scalar(31)}}), + LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); + ASSERT_EQ(L.getAction({opcode, {LLT::scalar(33)}}), + LegalizeActionStep(WidenScalar, 0, LLT::scalar(64))); + ASSERT_EQ(L.getAction({opcode, {LLT::scalar(63)}}), + LegalizeActionStep(WidenScalar, 0, LLT::scalar(64))); + ASSERT_EQ(L.getAction({opcode, {LLT::scalar(65)}}), + LegalizeActionStep(NarrowScalar, 0, LLT::scalar(64))); } } @@ -90,35 +92,35 @@ TEST(LegalizerInfoTest, VectorRISC) { using namespace TargetOpcode; LegalizerInfo L; // Typical RISCy set of operations based on ARM. - L.setAction({G_ADD, LLT::vector(8, 8)}, LegalizerInfo::Legal); - L.setAction({G_ADD, LLT::vector(16, 8)}, LegalizerInfo::Legal); - L.setAction({G_ADD, LLT::vector(4, 16)}, LegalizerInfo::Legal); - L.setAction({G_ADD, LLT::vector(8, 16)}, LegalizerInfo::Legal); - L.setAction({G_ADD, LLT::vector(2, 32)}, LegalizerInfo::Legal); - L.setAction({G_ADD, LLT::vector(4, 32)}, LegalizerInfo::Legal); + L.setAction({G_ADD, LLT::vector(8, 8)}, Legal); + L.setAction({G_ADD, LLT::vector(16, 8)}, Legal); + L.setAction({G_ADD, LLT::vector(4, 16)}, Legal); + L.setAction({G_ADD, LLT::vector(8, 16)}, Legal); + L.setAction({G_ADD, LLT::vector(2, 32)}, Legal); + L.setAction({G_ADD, LLT::vector(4, 32)}, Legal); L.setLegalizeVectorElementToDifferentSizeStrategy( G_ADD, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise); - L.setAction({G_ADD, 0, LLT::scalar(32)}, LegalizerInfo::Legal); + L.setAction({G_ADD, 0, LLT::scalar(32)}, Legal); L.computeTables(); // Check we infer the correct types and actually do what we're told for some // simple cases. - ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 8)}), - std::make_pair(LegalizerInfo::Legal, LLT::vector(8, 8))); - ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 7)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::vector(8, 8))); - ASSERT_EQ(L.getAction({G_ADD, LLT::vector(2, 8)}), - std::make_pair(LegalizerInfo::MoreElements, LLT::vector(8, 8))); - ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 32)}), - std::make_pair(LegalizerInfo::FewerElements, LLT::vector(4, 32))); + ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 8)}}), + LegalizeActionStep(Legal, 0, LLT{})); + ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 7)}}), + LegalizeActionStep(WidenScalar, 0, LLT::vector(8, 8))); + ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(2, 8)}}), + LegalizeActionStep(MoreElements, 0, LLT::vector(8, 8))); + ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 32)}}), + LegalizeActionStep(FewerElements, 0, LLT::vector(4, 32))); // Check a few non-power-of-2 sizes: - ASSERT_EQ(L.getAction({G_ADD, LLT::vector(3, 3)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::vector(3, 8))); - ASSERT_EQ(L.getAction({G_ADD, LLT::vector(3, 8)}), - std::make_pair(LegalizerInfo::MoreElements, LLT::vector(8, 8))); + ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(3, 3)}}), + LegalizeActionStep(WidenScalar, 0, LLT::vector(3, 8))); + ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(3, 8)}}), + LegalizeActionStep(MoreElements, 0, LLT::vector(8, 8))); } TEST(LegalizerInfoTest, MultipleTypes) { @@ -128,8 +130,8 @@ TEST(LegalizerInfoTest, MultipleTypes) { LLT s64 = LLT::scalar(64); // Typical RISCy set of operations based on AArch64. - L.setAction({G_PTRTOINT, 0, s64}, LegalizerInfo::Legal); - L.setAction({G_PTRTOINT, 1, p0}, LegalizerInfo::Legal); + L.setAction({G_PTRTOINT, 0, s64}, Legal); + L.setAction({G_PTRTOINT, 1, p0}, Legal); L.setLegalizeScalarToDifferentSizeStrategy( G_PTRTOINT, 0, LegalizerInfo::widenToLargerTypesAndNarrowToLargest); @@ -137,15 +139,16 @@ TEST(LegalizerInfoTest, MultipleTypes) { L.computeTables(); // Check we infer the correct types and actually do what we're told. - ASSERT_EQ(L.getAction({G_PTRTOINT, 0, s64}), - std::make_pair(LegalizerInfo::Legal, s64)); - ASSERT_EQ(L.getAction({G_PTRTOINT, 1, p0}), - std::make_pair(LegalizerInfo::Legal, p0)); + ASSERT_EQ(L.getAction({G_PTRTOINT, {s64, p0}}), + LegalizeActionStep(Legal, 0, LLT{})); + // Make sure we also handle unusual sizes - ASSERT_EQ(L.getAction({G_PTRTOINT, 0, LLT::scalar(65)}), - std::make_pair(LegalizerInfo::NarrowScalar, s64)); - ASSERT_EQ(L.getAction({G_PTRTOINT, 1, LLT::pointer(0, 32)}), - std::make_pair(LegalizerInfo::Unsupported, LLT::pointer(0, 32))); + ASSERT_EQ( + L.getAction({G_PTRTOINT, {LLT::scalar(65), s64}}), + LegalizeActionStep(NarrowScalar, 0, s64)); + ASSERT_EQ( + L.getAction({G_PTRTOINT, {s64, LLT::pointer(0, 32)}}), + LegalizeActionStep(Unsupported, 1, LLT::pointer(0, 32))); } TEST(LegalizerInfoTest, MultipleSteps) { @@ -156,22 +159,22 @@ TEST(LegalizerInfoTest, MultipleSteps) { L.setLegalizeScalarToDifferentSizeStrategy( G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise); - L.setAction({G_UREM, 0, s32}, LegalizerInfo::Lower); - L.setAction({G_UREM, 0, s64}, LegalizerInfo::Lower); + L.setAction({G_UREM, 0, s32}, Lower); + L.setAction({G_UREM, 0, s64}, Lower); L.computeTables(); - ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(16)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32))); - ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(32)}), - std::make_pair(LegalizerInfo::Lower, LLT::scalar(32))); + ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(16)}}), + LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); + ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(32)}}), + LegalizeActionStep(Lower, 0, LLT::scalar(32))); } TEST(LegalizerInfoTest, SizeChangeStrategy) { using namespace TargetOpcode; LegalizerInfo L; for (unsigned Size : {1, 8, 16, 32}) - L.setAction({G_UREM, 0, LLT::scalar(Size)}, LegalizerInfo::Legal); + L.setAction({G_UREM, 0, LLT::scalar(Size)}, Legal); L.setLegalizeScalarToDifferentSizeStrategy( G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise); @@ -179,20 +182,20 @@ TEST(LegalizerInfoTest, SizeChangeStrategy) { // Check we infer the correct types and actually do what we're told. for (unsigned Size : {1, 8, 16, 32}) { - ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(Size)}), - std::make_pair(LegalizerInfo::Legal, LLT::scalar(Size))); + ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(Size)}}), + LegalizeActionStep(Legal, 0, LLT{})); } - ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(2)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(8))); - ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(7)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(8))); - ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(9)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(16))); - ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(17)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32))); - ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(31)}), - std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32))); - ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(33)}), - std::make_pair(LegalizerInfo::Unsupported, LLT::scalar(33))); + ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(2)}}), + LegalizeActionStep(WidenScalar, 0, LLT::scalar(8))); + ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(7)}}), + LegalizeActionStep(WidenScalar, 0, LLT::scalar(8))); + ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(9)}}), + LegalizeActionStep(WidenScalar, 0, LLT::scalar(16))); + ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(17)}}), + LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); + ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(31)}}), + LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); + ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(33)}}), + LegalizeActionStep(Unsupported, 0, LLT::scalar(33))); } } diff --git a/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp b/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp new file mode 100644 index 000000000000..8f17b1991df5 --- /dev/null +++ b/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp @@ -0,0 +1,493 @@ +//===- PatternMatchTest.cpp -----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" +#include "llvm/CodeGen/MIRParser/MIRParser.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/TargetFrameLowering.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace MIPatternMatch; + +namespace { + +void initLLVM() { + InitializeAllTargets(); + InitializeAllTargetMCs(); + InitializeAllAsmPrinters(); + InitializeAllAsmParsers(); + + PassRegistry *Registry = PassRegistry::getPassRegistry(); + initializeCore(*Registry); + initializeCodeGen(*Registry); +} + +/// Create a TargetMachine. As we lack a dedicated always available target for +/// unittests, we go for "AArch64". +std::unique_ptr<TargetMachine> createTargetMachine() { + Triple TargetTriple("aarch64--"); + std::string Error; + const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error); + if (!T) + return nullptr; + + TargetOptions Options; + return std::unique_ptr<TargetMachine>(T->createTargetMachine( + "AArch64", "", "", Options, None, None, CodeGenOpt::Aggressive)); +} + +std::unique_ptr<Module> parseMIR(LLVMContext &Context, + std::unique_ptr<MIRParser> &MIR, + const TargetMachine &TM, StringRef MIRCode, + const char *FuncName, 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> M = MIR->parseIRModule(); + if (!M) + return nullptr; + + M->setDataLayout(TM.createDataLayout()); + + if (MIR->parseMachineFunctions(*M, MMI)) + return nullptr; + + return M; +} + +std::pair<std::unique_ptr<Module>, std::unique_ptr<MachineModuleInfo>> +createDummyModule(LLVMContext &Context, const TargetMachine &TM, + StringRef MIRFunc) { + SmallString<512> S; + StringRef MIRString = (Twine(R"MIR( +--- +... +name: func +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } + - { id: 3, class: _ } +body: | + bb.1: + %0(s64) = COPY $x0 + %1(s64) = COPY $x1 + %2(s64) = COPY $x2 +)MIR") + Twine(MIRFunc) + Twine("...\n")) + .toNullTerminatedStringRef(S); + std::unique_ptr<MIRParser> MIR; + auto MMI = make_unique<MachineModuleInfo>(&TM); + std::unique_ptr<Module> M = + parseMIR(Context, MIR, TM, MIRString, "func", *MMI); + return make_pair(std::move(M), std::move(MMI)); +} + +static MachineFunction *getMFFromMMI(const Module *M, + const MachineModuleInfo *MMI) { + Function *F = M->getFunction("func"); + auto *MF = MMI->getMachineFunction(*F); + return MF; +} + +static void collectCopies(SmallVectorImpl<unsigned> &Copies, + MachineFunction *MF) { + for (auto &MBB : *MF) + for (MachineInstr &MI : MBB) { + if (MI.getOpcode() == TargetOpcode::COPY) + Copies.push_back(MI.getOperand(0).getReg()); + } +} + +TEST(PatternMatchInstr, MatchIntConstant) { + LLVMContext Context; + std::unique_ptr<TargetMachine> TM = createTargetMachine(); + if (!TM) + return; + auto ModuleMMIPair = createDummyModule(Context, *TM, ""); + MachineFunction *MF = + getMFFromMMI(ModuleMMIPair.first.get(), ModuleMMIPair.second.get()); + SmallVector<unsigned, 4> Copies; + collectCopies(Copies, MF); + MachineBasicBlock *EntryMBB = &*MF->begin(); + MachineIRBuilder B(*MF); + MachineRegisterInfo &MRI = MF->getRegInfo(); + B.setInsertPt(*EntryMBB, EntryMBB->end()); + auto MIBCst = B.buildConstant(LLT::scalar(64), 42); + int64_t Cst; + bool match = mi_match(MIBCst->getOperand(0).getReg(), MRI, m_ICst(Cst)); + ASSERT_TRUE(match); + ASSERT_EQ(Cst, 42); +} + +TEST(PatternMatchInstr, MatchBinaryOp) { + LLVMContext Context; + std::unique_ptr<TargetMachine> TM = createTargetMachine(); + if (!TM) + return; + auto ModuleMMIPair = createDummyModule(Context, *TM, ""); + MachineFunction *MF = + getMFFromMMI(ModuleMMIPair.first.get(), ModuleMMIPair.second.get()); + SmallVector<unsigned, 4> Copies; + collectCopies(Copies, MF); + MachineBasicBlock *EntryMBB = &*MF->begin(); + MachineIRBuilder B(*MF); + MachineRegisterInfo &MRI = MF->getRegInfo(); + B.setInsertPt(*EntryMBB, EntryMBB->end()); + LLT s64 = LLT::scalar(64); + auto MIBAdd = B.buildAdd(s64, Copies[0], Copies[1]); + // Test case for no bind. + bool match = + mi_match(MIBAdd->getOperand(0).getReg(), MRI, m_GAdd(m_Reg(), m_Reg())); + ASSERT_TRUE(match); + unsigned Src0, Src1, Src2; + match = mi_match(MIBAdd->getOperand(0).getReg(), MRI, + m_GAdd(m_Reg(Src0), m_Reg(Src1))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, Copies[0]); + ASSERT_EQ(Src1, Copies[1]); + + // Build MUL(ADD %0, %1), %2 + auto MIBMul = B.buildMul(s64, MIBAdd, Copies[2]); + + // Try to match MUL. + match = mi_match(MIBMul->getOperand(0).getReg(), MRI, + m_GMul(m_Reg(Src0), m_Reg(Src1))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, MIBAdd->getOperand(0).getReg()); + ASSERT_EQ(Src1, Copies[2]); + + // Try to match MUL(ADD) + match = mi_match(MIBMul->getOperand(0).getReg(), MRI, + m_GMul(m_GAdd(m_Reg(Src0), m_Reg(Src1)), m_Reg(Src2))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, Copies[0]); + ASSERT_EQ(Src1, Copies[1]); + ASSERT_EQ(Src2, Copies[2]); + + // Test Commutativity. + auto MIBMul2 = B.buildMul(s64, Copies[0], B.buildConstant(s64, 42)); + // Try to match MUL(Cst, Reg) on src of MUL(Reg, Cst) to validate + // commutativity. + int64_t Cst; + match = mi_match(MIBMul2->getOperand(0).getReg(), MRI, + m_GMul(m_ICst(Cst), m_Reg(Src0))); + ASSERT_TRUE(match); + ASSERT_EQ(Cst, 42); + ASSERT_EQ(Src0, Copies[0]); + + // Make sure commutative doesn't work with something like SUB. + auto MIBSub = B.buildSub(s64, Copies[0], B.buildConstant(s64, 42)); + match = mi_match(MIBSub->getOperand(0).getReg(), MRI, + m_GSub(m_ICst(Cst), m_Reg(Src0))); + ASSERT_FALSE(match); + + auto MIBFMul = B.buildInstr(TargetOpcode::G_FMUL, s64, Copies[0], + B.buildConstant(s64, 42)); + // Match and test commutativity for FMUL. + match = mi_match(MIBFMul->getOperand(0).getReg(), MRI, + m_GFMul(m_ICst(Cst), m_Reg(Src0))); + ASSERT_TRUE(match); + ASSERT_EQ(Cst, 42); + ASSERT_EQ(Src0, Copies[0]); + + // FSUB + auto MIBFSub = B.buildInstr(TargetOpcode::G_FSUB, s64, Copies[0], + B.buildConstant(s64, 42)); + match = mi_match(MIBFSub->getOperand(0).getReg(), MRI, + m_GFSub(m_Reg(Src0), m_Reg())); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, Copies[0]); + + // Build AND %0, %1 + auto MIBAnd = B.buildAnd(s64, Copies[0], Copies[1]); + // Try to match AND. + match = mi_match(MIBAnd->getOperand(0).getReg(), MRI, + m_GAnd(m_Reg(Src0), m_Reg(Src1))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, Copies[0]); + ASSERT_EQ(Src1, Copies[1]); + + // Build OR %0, %1 + auto MIBOr = B.buildOr(s64, Copies[0], Copies[1]); + // Try to match OR. + match = mi_match(MIBOr->getOperand(0).getReg(), MRI, + m_GOr(m_Reg(Src0), m_Reg(Src1))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, Copies[0]); + ASSERT_EQ(Src1, Copies[1]); + + // Try to use the FoldableInstructionsBuilder to build binary ops. + ConstantFoldingMIRBuilder CFB(B.getState()); + LLT s32 = LLT::scalar(32); + auto MIBCAdd = + CFB.buildAdd(s32, CFB.buildConstant(s32, 0), CFB.buildConstant(s32, 1)); + // This should be a constant now. + match = mi_match(MIBCAdd->getOperand(0).getReg(), MRI, m_ICst(Cst)); + ASSERT_TRUE(match); + ASSERT_EQ(Cst, 1); + auto MIBCAdd1 = + CFB.buildInstr(TargetOpcode::G_ADD, s32, CFB.buildConstant(s32, 0), + CFB.buildConstant(s32, 1)); + // This should be a constant now. + match = mi_match(MIBCAdd1->getOperand(0).getReg(), MRI, m_ICst(Cst)); + ASSERT_TRUE(match); + ASSERT_EQ(Cst, 1); + + // Try one of the other constructors of MachineIRBuilder to make sure it's + // compatible. + ConstantFoldingMIRBuilder CFB1(*MF); + CFB1.setInsertPt(*EntryMBB, EntryMBB->end()); + auto MIBCSub = + CFB1.buildInstr(TargetOpcode::G_SUB, s32, CFB1.buildConstant(s32, 1), + CFB1.buildConstant(s32, 1)); + // This should be a constant now. + match = mi_match(MIBCSub->getOperand(0).getReg(), MRI, m_ICst(Cst)); + ASSERT_TRUE(match); + ASSERT_EQ(Cst, 0); +} + +TEST(PatternMatchInstr, MatchFPUnaryOp) { + LLVMContext Context; + std::unique_ptr<TargetMachine> TM = createTargetMachine(); + if (!TM) + return; + auto ModuleMMIPair = createDummyModule(Context, *TM, ""); + MachineFunction *MF = + getMFFromMMI(ModuleMMIPair.first.get(), ModuleMMIPair.second.get()); + SmallVector<unsigned, 4> Copies; + collectCopies(Copies, MF); + MachineBasicBlock *EntryMBB = &*MF->begin(); + MachineIRBuilder B(*MF); + MachineRegisterInfo &MRI = MF->getRegInfo(); + B.setInsertPt(*EntryMBB, EntryMBB->end()); + + // Truncate s64 to s32. + LLT s32 = LLT::scalar(32); + auto Copy0s32 = B.buildFPTrunc(s32, Copies[0]); + + // Match G_FABS. + auto MIBFabs = B.buildInstr(TargetOpcode::G_FABS, s32, Copy0s32); + bool match = mi_match(MIBFabs->getOperand(0).getReg(), MRI, m_GFabs(m_Reg())); + ASSERT_TRUE(match); + + unsigned Src; + auto MIBFNeg = B.buildInstr(TargetOpcode::G_FNEG, s32, Copy0s32); + match = mi_match(MIBFNeg->getOperand(0).getReg(), MRI, m_GFNeg(m_Reg(Src))); + ASSERT_TRUE(match); + ASSERT_EQ(Src, Copy0s32->getOperand(0).getReg()); + + match = mi_match(MIBFabs->getOperand(0).getReg(), MRI, m_GFabs(m_Reg(Src))); + ASSERT_TRUE(match); + ASSERT_EQ(Src, Copy0s32->getOperand(0).getReg()); + + // Build and match FConstant. + auto MIBFCst = B.buildFConstant(s32, .5); + const ConstantFP *TmpFP{}; + match = mi_match(MIBFCst->getOperand(0).getReg(), MRI, m_GFCst(TmpFP)); + ASSERT_TRUE(match); + ASSERT_TRUE(TmpFP); + APFloat APF((float).5); + auto *CFP = ConstantFP::get(Context, APF); + ASSERT_EQ(CFP, TmpFP); + + // Build double float. + LLT s64 = LLT::scalar(64); + auto MIBFCst64 = B.buildFConstant(s64, .5); + const ConstantFP *TmpFP64{}; + match = mi_match(MIBFCst64->getOperand(0).getReg(), MRI, m_GFCst(TmpFP64)); + ASSERT_TRUE(match); + ASSERT_TRUE(TmpFP64); + APFloat APF64(.5); + auto CFP64 = ConstantFP::get(Context, APF64); + ASSERT_EQ(CFP64, TmpFP64); + ASSERT_NE(TmpFP64, TmpFP); + + // Build half float. + LLT s16 = LLT::scalar(16); + auto MIBFCst16 = B.buildFConstant(s16, .5); + const ConstantFP *TmpFP16{}; + match = mi_match(MIBFCst16->getOperand(0).getReg(), MRI, m_GFCst(TmpFP16)); + ASSERT_TRUE(match); + ASSERT_TRUE(TmpFP16); + bool Ignored; + APFloat APF16(.5); + APF16.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored); + auto CFP16 = ConstantFP::get(Context, APF16); + ASSERT_EQ(TmpFP16, CFP16); + ASSERT_NE(TmpFP16, TmpFP); +} + +TEST(PatternMatchInstr, MatchExtendsTrunc) { + LLVMContext Context; + std::unique_ptr<TargetMachine> TM = createTargetMachine(); + if (!TM) + return; + auto ModuleMMIPair = createDummyModule(Context, *TM, ""); + MachineFunction *MF = + getMFFromMMI(ModuleMMIPair.first.get(), ModuleMMIPair.second.get()); + SmallVector<unsigned, 4> Copies; + collectCopies(Copies, MF); + MachineBasicBlock *EntryMBB = &*MF->begin(); + MachineIRBuilder B(*MF); + MachineRegisterInfo &MRI = MF->getRegInfo(); + B.setInsertPt(*EntryMBB, EntryMBB->end()); + LLT s64 = LLT::scalar(64); + LLT s32 = LLT::scalar(32); + + auto MIBTrunc = B.buildTrunc(s32, Copies[0]); + auto MIBAExt = B.buildAnyExt(s64, MIBTrunc); + auto MIBZExt = B.buildZExt(s64, MIBTrunc); + auto MIBSExt = B.buildSExt(s64, MIBTrunc); + unsigned Src0; + bool match = + mi_match(MIBTrunc->getOperand(0).getReg(), MRI, m_GTrunc(m_Reg(Src0))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, Copies[0]); + match = + mi_match(MIBAExt->getOperand(0).getReg(), MRI, m_GAnyExt(m_Reg(Src0))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, MIBTrunc->getOperand(0).getReg()); + + match = mi_match(MIBSExt->getOperand(0).getReg(), MRI, m_GSExt(m_Reg(Src0))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, MIBTrunc->getOperand(0).getReg()); + + match = mi_match(MIBZExt->getOperand(0).getReg(), MRI, m_GZExt(m_Reg(Src0))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, MIBTrunc->getOperand(0).getReg()); + + // Match ext(trunc src) + match = mi_match(MIBAExt->getOperand(0).getReg(), MRI, + m_GAnyExt(m_GTrunc(m_Reg(Src0)))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, Copies[0]); + + match = mi_match(MIBSExt->getOperand(0).getReg(), MRI, + m_GSExt(m_GTrunc(m_Reg(Src0)))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, Copies[0]); + + match = mi_match(MIBZExt->getOperand(0).getReg(), MRI, + m_GZExt(m_GTrunc(m_Reg(Src0)))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, Copies[0]); +} + +TEST(PatternMatchInstr, MatchSpecificType) { + LLVMContext Context; + std::unique_ptr<TargetMachine> TM = createTargetMachine(); + if (!TM) + return; + auto ModuleMMIPair = createDummyModule(Context, *TM, ""); + MachineFunction *MF = + getMFFromMMI(ModuleMMIPair.first.get(), ModuleMMIPair.second.get()); + SmallVector<unsigned, 4> Copies; + collectCopies(Copies, MF); + MachineBasicBlock *EntryMBB = &*MF->begin(); + MachineIRBuilder B(*MF); + MachineRegisterInfo &MRI = MF->getRegInfo(); + B.setInsertPt(*EntryMBB, EntryMBB->end()); + + // Try to match a 64bit add. + LLT s64 = LLT::scalar(64); + LLT s32 = LLT::scalar(32); + auto MIBAdd = B.buildAdd(s64, Copies[0], Copies[1]); + ASSERT_FALSE(mi_match(MIBAdd->getOperand(0).getReg(), MRI, + m_GAdd(m_SpecificType(s32), m_Reg()))); + ASSERT_TRUE(mi_match(MIBAdd->getOperand(0).getReg(), MRI, + m_GAdd(m_SpecificType(s64), m_Reg()))); + + // Try to match the destination type of a bitcast. + LLT v2s32 = LLT::vector(2, 32); + auto MIBCast = B.buildCast(v2s32, Copies[0]); + ASSERT_TRUE( + mi_match(MIBCast->getOperand(0).getReg(), MRI, m_GBitcast(m_Reg()))); + ASSERT_TRUE( + mi_match(MIBCast->getOperand(0).getReg(), MRI, m_SpecificType(v2s32))); + ASSERT_TRUE( + mi_match(MIBCast->getOperand(1).getReg(), MRI, m_SpecificType(s64))); + + // Build a PTRToInt and INTTOPTR and match and test them. + LLT PtrTy = LLT::pointer(0, 64); + auto MIBIntToPtr = B.buildCast(PtrTy, Copies[0]); + auto MIBPtrToInt = B.buildCast(s64, MIBIntToPtr); + unsigned Src0; + + // match the ptrtoint(inttoptr reg) + bool match = mi_match(MIBPtrToInt->getOperand(0).getReg(), MRI, + m_GPtrToInt(m_GIntToPtr(m_Reg(Src0)))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, Copies[0]); +} + +TEST(PatternMatchInstr, MatchCombinators) { + LLVMContext Context; + std::unique_ptr<TargetMachine> TM = createTargetMachine(); + if (!TM) + return; + auto ModuleMMIPair = createDummyModule(Context, *TM, ""); + MachineFunction *MF = + getMFFromMMI(ModuleMMIPair.first.get(), ModuleMMIPair.second.get()); + SmallVector<unsigned, 4> Copies; + collectCopies(Copies, MF); + MachineBasicBlock *EntryMBB = &*MF->begin(); + MachineIRBuilder B(*MF); + MachineRegisterInfo &MRI = MF->getRegInfo(); + B.setInsertPt(*EntryMBB, EntryMBB->end()); + LLT s64 = LLT::scalar(64); + LLT s32 = LLT::scalar(32); + auto MIBAdd = B.buildAdd(s64, Copies[0], Copies[1]); + unsigned Src0, Src1; + bool match = + mi_match(MIBAdd->getOperand(0).getReg(), MRI, + m_all_of(m_SpecificType(s64), m_GAdd(m_Reg(Src0), m_Reg(Src1)))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, Copies[0]); + ASSERT_EQ(Src1, Copies[1]); + // Check for s32 (which should fail). + match = + mi_match(MIBAdd->getOperand(0).getReg(), MRI, + m_all_of(m_SpecificType(s32), m_GAdd(m_Reg(Src0), m_Reg(Src1)))); + ASSERT_FALSE(match); + match = + mi_match(MIBAdd->getOperand(0).getReg(), MRI, + m_any_of(m_SpecificType(s32), m_GAdd(m_Reg(Src0), m_Reg(Src1)))); + ASSERT_TRUE(match); + ASSERT_EQ(Src0, Copies[0]); + ASSERT_EQ(Src1, Copies[1]); + + // Match a case where none of the predicates hold true. + match = mi_match( + MIBAdd->getOperand(0).getReg(), MRI, + m_any_of(m_SpecificType(LLT::scalar(16)), m_GSub(m_Reg(), m_Reg()))); + ASSERT_FALSE(match); +} +} // namespace + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + initLLVM(); + return RUN_ALL_TESTS(); +} diff --git a/unittests/CodeGen/MachineInstrTest.cpp b/unittests/CodeGen/MachineInstrTest.cpp index aca640ebcf35..6883d3ed63e9 100644 --- a/unittests/CodeGen/MachineInstrTest.cpp +++ b/unittests/CodeGen/MachineInstrTest.cpp @@ -14,6 +14,8 @@ #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/ModuleSlotTracker.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Target/TargetMachine.h" @@ -244,4 +246,31 @@ TEST(MachineInstrExpressionTraitTest, IsEqualAgreesWithGetHashValue) { checkHashAndIsEqualMatch(VD2PU, VD2PD); } + +TEST(MachineInstrPrintingTest, DebugLocPrinting) { + auto MF = createMachineFunction(); + + MCOperandInfo OpInfo{0, 0, MCOI::OPERAND_REGISTER, 0}; + MCInstrDesc MCID = {0, 1, 1, 0, 0, 0, + 0, nullptr, nullptr, &OpInfo, 0, nullptr}; + + LLVMContext Ctx; + DIFile *DIF = DIFile::getDistinct(Ctx, "filename", ""); + DISubprogram *DIS = DISubprogram::getDistinct( + Ctx, nullptr, "", "", DIF, 0, nullptr, false, false, 0, nullptr, 0, 0, 0, + DINode::FlagZero, false, nullptr); + DILocation *DIL = DILocation::get(Ctx, 1, 5, DIS); + DebugLoc DL(DIL); + MachineInstr *MI = MF->CreateMachineInstr(MCID, DL); + MI->addOperand(*MF, MachineOperand::CreateReg(0, /*isDef*/ true)); + + std::string str; + raw_string_ostream OS(str); + MI->print(OS); + ASSERT_TRUE( + StringRef(OS.str()).startswith("$noreg = UNKNOWN debug-location ")); + ASSERT_TRUE( + StringRef(OS.str()).endswith("filename:1:5")); +} + } // end namespace diff --git a/unittests/CodeGen/MachineOperandTest.cpp b/unittests/CodeGen/MachineOperandTest.cpp index 78a20b836486..53ec5aed8189 100644 --- a/unittests/CodeGen/MachineOperandTest.cpp +++ b/unittests/CodeGen/MachineOperandTest.cpp @@ -80,7 +80,7 @@ TEST(MachineOperandTest, PrintSubReg) { std::string str; raw_string_ostream OS(str); MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); - ASSERT_TRUE(OS.str() == "%physreg1.subreg5"); + ASSERT_TRUE(OS.str() == "$physreg1.subreg5"); } TEST(MachineOperandTest, PrintCImm) { @@ -118,8 +118,7 @@ TEST(MachineOperandTest, PrintSubRegIndex) { // TRI and IntrinsicInfo we can print the operand as a subreg index. std::string str; raw_string_ostream OS(str); - ModuleSlotTracker DummyMST(nullptr); - MachineOperand::printSubregIdx(OS, MO.getImm(), nullptr); + MachineOperand::printSubRegIdx(OS, MO.getImm(), nullptr); ASSERT_TRUE(OS.str() == "%subreg.3"); } @@ -215,7 +214,7 @@ TEST(MachineOperandTest, PrintExternalSymbol) { { raw_string_ostream OS(str); MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); - ASSERT_TRUE(OS.str() == "$foo"); + ASSERT_TRUE(OS.str() == "&foo"); } str.clear(); @@ -225,7 +224,7 @@ TEST(MachineOperandTest, PrintExternalSymbol) { { raw_string_ostream OS(str); MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); - ASSERT_TRUE(OS.str() == "$foo + 12"); + ASSERT_TRUE(OS.str() == "&foo + 12"); } str.clear(); @@ -235,7 +234,7 @@ TEST(MachineOperandTest, PrintExternalSymbol) { { raw_string_ostream OS(str); MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); - ASSERT_TRUE(OS.str() == "$foo - 12"); + ASSERT_TRUE(OS.str() == "&foo - 12"); } } @@ -296,7 +295,7 @@ TEST(MachineOperandTest, PrintMetadata) { LLVMContext Ctx; Module M("MachineOperandMDNodeTest", Ctx); NamedMDNode *MD = M.getOrInsertNamedMetadata("namedmd"); - ModuleSlotTracker DummyMST(&M); + ModuleSlotTracker MST(&M); Metadata *MDS = MDString::get(Ctx, "foo"); MDNode *Node = MDNode::get(Ctx, MDS); MD->addOperand(Node); @@ -312,7 +311,8 @@ TEST(MachineOperandTest, PrintMetadata) { std::string str; // Print a MachineOperand containing a metadata node. raw_string_ostream OS(str); - MO.print(OS, DummyMST, LLT{}, false, false, 0, /*TRI=*/nullptr, + MO.print(OS, MST, LLT{}, /*PrintDef=*/false, /*IsStandalone=*/false, + /*ShouldPrintRegisterTies=*/false, 0, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); ASSERT_TRUE(OS.str() == "!0"); } diff --git a/unittests/CodeGen/ScalableVectorMVTsTest.cpp b/unittests/CodeGen/ScalableVectorMVTsTest.cpp index 0071823f2cc9..20b3fb1b9f48 100644 --- a/unittests/CodeGen/ScalableVectorMVTsTest.cpp +++ b/unittests/CodeGen/ScalableVectorMVTsTest.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/Support/MachineValueType.h" #include "gtest/gtest.h" using namespace llvm; |