| //===- GISelMITest.h --------------------------------------------*- C++ -*-===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| #ifndef LLVM_UNITTEST_CODEGEN_GLOBALISEL_GISELMI_H |
| #define LLVM_UNITTEST_CODEGEN_GLOBALISEL_GISELMI_H |
| |
| #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" |
| #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" |
| #include "llvm/CodeGen/GlobalISel/LegalizerInfo.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/FileCheck/FileCheck.h" |
| #include "llvm/InitializePasses.h" |
| #include "llvm/MC/TargetRegistry.h" |
| #include "llvm/Support/SourceMgr.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; |
| |
| static inline void initLLVM() { |
| InitializeAllTargets(); |
| InitializeAllTargetMCs(); |
| InitializeAllAsmPrinters(); |
| InitializeAllAsmParsers(); |
| |
| PassRegistry *Registry = PassRegistry::getPassRegistry(); |
| initializeCore(*Registry); |
| initializeCodeGen(*Registry); |
| } |
| |
| // Define a printers to help debugging when things go wrong. |
| namespace llvm { |
| std::ostream & |
| operator<<(std::ostream &OS, const LLT Ty); |
| |
| std::ostream & |
| operator<<(std::ostream &OS, const MachineFunction &MF); |
| } |
| |
| static 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; |
| } |
| static std::pair<std::unique_ptr<Module>, std::unique_ptr<MachineModuleInfo>> |
| createDummyModule(LLVMContext &Context, const LLVMTargetMachine &TM, |
| StringRef MIRString, const char *FuncName) { |
| std::unique_ptr<MIRParser> MIR; |
| auto MMI = std::make_unique<MachineModuleInfo>(&TM); |
| std::unique_ptr<Module> M = |
| parseMIR(Context, MIR, TM, MIRString, FuncName, *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<Register> &Copies, |
| MachineFunction *MF) { |
| for (auto &MBB : *MF) |
| for (MachineInstr &MI : MBB) { |
| if (MI.getOpcode() == TargetOpcode::COPY) |
| Copies.push_back(MI.getOperand(0).getReg()); |
| } |
| } |
| |
| class GISelMITest : public ::testing::Test { |
| protected: |
| GISelMITest() : ::testing::Test() {} |
| |
| /// Prepare a target specific LLVMTargetMachine. |
| virtual std::unique_ptr<LLVMTargetMachine> createTargetMachine() const = 0; |
| |
| /// Get the stub sample MIR test function. |
| virtual void getTargetTestModuleString(SmallString<512> &S, |
| StringRef MIRFunc) const = 0; |
| |
| void setUp(StringRef ExtraAssembly = "") { |
| TM = createTargetMachine(); |
| if (!TM) |
| return; |
| |
| SmallString<512> MIRString; |
| getTargetTestModuleString(MIRString, ExtraAssembly); |
| |
| ModuleMMIPair = createDummyModule(Context, *TM, MIRString, "func"); |
| MF = getMFFromMMI(ModuleMMIPair.first.get(), ModuleMMIPair.second.get()); |
| collectCopies(Copies, MF); |
| EntryMBB = &*MF->begin(); |
| B.setMF(*MF); |
| MRI = &MF->getRegInfo(); |
| B.setInsertPt(*EntryMBB, EntryMBB->end()); |
| } |
| |
| LLVMContext Context; |
| std::unique_ptr<LLVMTargetMachine> TM; |
| MachineFunction *MF; |
| std::pair<std::unique_ptr<Module>, std::unique_ptr<MachineModuleInfo>> |
| ModuleMMIPair; |
| SmallVector<Register, 4> Copies; |
| MachineBasicBlock *EntryMBB; |
| MachineIRBuilder B; |
| MachineRegisterInfo *MRI; |
| }; |
| |
| class AArch64GISelMITest : public GISelMITest { |
| std::unique_ptr<LLVMTargetMachine> createTargetMachine() const override; |
| void getTargetTestModuleString(SmallString<512> &S, |
| StringRef MIRFunc) const override; |
| }; |
| |
| class AMDGPUGISelMITest : public GISelMITest { |
| std::unique_ptr<LLVMTargetMachine> createTargetMachine() const override; |
| void getTargetTestModuleString(SmallString<512> &S, |
| StringRef MIRFunc) const override; |
| }; |
| |
| #define DefineLegalizerInfo(Name, SettingUpActionsBlock) \ |
| class Name##Info : public LegalizerInfo { \ |
| public: \ |
| Name##Info(const TargetSubtargetInfo &ST) { \ |
| using namespace TargetOpcode; \ |
| const LLT s8 = LLT::scalar(8); \ |
| (void)s8; \ |
| const LLT s16 = LLT::scalar(16); \ |
| (void)s16; \ |
| const LLT s32 = LLT::scalar(32); \ |
| (void)s32; \ |
| const LLT s64 = LLT::scalar(64); \ |
| (void)s64; \ |
| const LLT s128 = LLT::scalar(128); \ |
| (void)s128; \ |
| do \ |
| SettingUpActionsBlock while (0); \ |
| getLegacyLegalizerInfo().computeTables(); \ |
| verify(*ST.getInstrInfo()); \ |
| } \ |
| }; |
| |
| static inline bool CheckMachineFunction(const MachineFunction &MF, |
| StringRef CheckStr) { |
| SmallString<512> Msg; |
| raw_svector_ostream OS(Msg); |
| MF.print(OS); |
| auto OutputBuf = MemoryBuffer::getMemBuffer(Msg, "Output", false); |
| auto CheckBuf = MemoryBuffer::getMemBuffer(CheckStr, ""); |
| SmallString<4096> CheckFileBuffer; |
| FileCheckRequest Req; |
| FileCheck FC(Req); |
| StringRef CheckFileText = |
| FC.CanonicalizeFile(*CheckBuf.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 = OutputBuf->getBuffer(); |
| SM.AddNewSourceBuffer(std::move(OutputBuf), SMLoc()); |
| return FC.checkInput(SM, OutBuffer); |
| } |
| #endif |