1f5b5ccf2SYuanfang Chen //===- llvm/unittest/CodeGen/PassManager.cpp - PassManager tests ----------===// 2f5b5ccf2SYuanfang Chen // 3f5b5ccf2SYuanfang Chen // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4f5b5ccf2SYuanfang Chen // See https://llvm.org/LICENSE.txt for license information. 5f5b5ccf2SYuanfang Chen // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f5b5ccf2SYuanfang Chen // 7f5b5ccf2SYuanfang Chen //===----------------------------------------------------------------------===// 891e9e317SArthur Eubanks // Test that the various MachineFunction pass managers, adaptors, analyses, and 991e9e317SArthur Eubanks // analysis managers work. 1091e9e317SArthur Eubanks //===----------------------------------------------------------------------===// 11f5b5ccf2SYuanfang Chen 1291e9e317SArthur Eubanks #include "llvm/IR/PassManager.h" 13f5b5ccf2SYuanfang Chen #include "llvm/Analysis/CGSCCPassManager.h" 14f5b5ccf2SYuanfang Chen #include "llvm/Analysis/LoopAnalysisManager.h" 15f5b5ccf2SYuanfang Chen #include "llvm/AsmParser/Parser.h" 16989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineFunction.h" 17f5b5ccf2SYuanfang Chen #include "llvm/CodeGen/MachineModuleInfo.h" 18f5b5ccf2SYuanfang Chen #include "llvm/CodeGen/MachinePassManager.h" 1991e9e317SArthur Eubanks #include "llvm/IR/Analysis.h" 20f5b5ccf2SYuanfang Chen #include "llvm/IR/LLVMContext.h" 21f5b5ccf2SYuanfang Chen #include "llvm/IR/Module.h" 2289b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h" 23f5b5ccf2SYuanfang Chen #include "llvm/Passes/PassBuilder.h" 24f5b5ccf2SYuanfang Chen #include "llvm/Support/SourceMgr.h" 25f5b5ccf2SYuanfang Chen #include "llvm/Support/TargetSelect.h" 26f5b5ccf2SYuanfang Chen #include "llvm/Target/TargetMachine.h" 27d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h" 2862c7f035SArchibald Elliott #include "llvm/TargetParser/Triple.h" 29f5b5ccf2SYuanfang Chen #include "gtest/gtest.h" 30f5b5ccf2SYuanfang Chen 31f5b5ccf2SYuanfang Chen using namespace llvm; 32f5b5ccf2SYuanfang Chen 33f5b5ccf2SYuanfang Chen namespace { 34f5b5ccf2SYuanfang Chen 35f5b5ccf2SYuanfang Chen class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> { 36f5b5ccf2SYuanfang Chen public: 37f5b5ccf2SYuanfang Chen struct Result { 38f5b5ccf2SYuanfang Chen Result(int Count) : InstructionCount(Count) {} 39f5b5ccf2SYuanfang Chen int InstructionCount; 40f5b5ccf2SYuanfang Chen }; 41f5b5ccf2SYuanfang Chen 4291e9e317SArthur Eubanks /// The number of instructions in the Function. 43f5b5ccf2SYuanfang Chen Result run(Function &F, FunctionAnalysisManager &AM) { 4491e9e317SArthur Eubanks return Result(F.getInstructionCount()); 45f5b5ccf2SYuanfang Chen } 46f5b5ccf2SYuanfang Chen 47f5b5ccf2SYuanfang Chen private: 48f5b5ccf2SYuanfang Chen friend AnalysisInfoMixin<TestFunctionAnalysis>; 49f5b5ccf2SYuanfang Chen static AnalysisKey Key; 50f5b5ccf2SYuanfang Chen }; 51f5b5ccf2SYuanfang Chen 52f5b5ccf2SYuanfang Chen AnalysisKey TestFunctionAnalysis::Key; 53f5b5ccf2SYuanfang Chen 54f5b5ccf2SYuanfang Chen class TestMachineFunctionAnalysis 55f5b5ccf2SYuanfang Chen : public AnalysisInfoMixin<TestMachineFunctionAnalysis> { 56f5b5ccf2SYuanfang Chen public: 57f5b5ccf2SYuanfang Chen struct Result { 58f5b5ccf2SYuanfang Chen Result(int Count) : InstructionCount(Count) {} 59f5b5ccf2SYuanfang Chen int InstructionCount; 60f5b5ccf2SYuanfang Chen }; 61f5b5ccf2SYuanfang Chen 6291e9e317SArthur Eubanks Result run(MachineFunction &MF, MachineFunctionAnalysisManager &AM) { 6391e9e317SArthur Eubanks FunctionAnalysisManager &FAM = 6491e9e317SArthur Eubanks AM.getResult<FunctionAnalysisManagerMachineFunctionProxy>(MF) 6591e9e317SArthur Eubanks .getManager(); 66f5b5ccf2SYuanfang Chen TestFunctionAnalysis::Result &FAR = 6791e9e317SArthur Eubanks FAM.getResult<TestFunctionAnalysis>(MF.getFunction()); 68f5b5ccf2SYuanfang Chen return FAR.InstructionCount; 69f5b5ccf2SYuanfang Chen } 70f5b5ccf2SYuanfang Chen 71f5b5ccf2SYuanfang Chen private: 72f5b5ccf2SYuanfang Chen friend AnalysisInfoMixin<TestMachineFunctionAnalysis>; 73f5b5ccf2SYuanfang Chen static AnalysisKey Key; 74f5b5ccf2SYuanfang Chen }; 75f5b5ccf2SYuanfang Chen 76f5b5ccf2SYuanfang Chen AnalysisKey TestMachineFunctionAnalysis::Key; 77f5b5ccf2SYuanfang Chen 78f5b5ccf2SYuanfang Chen struct TestMachineFunctionPass : public PassInfoMixin<TestMachineFunctionPass> { 7991e9e317SArthur Eubanks TestMachineFunctionPass(int &Count, std::vector<int> &Counts) 8091e9e317SArthur Eubanks : Count(Count), Counts(Counts) {} 81f5b5ccf2SYuanfang Chen 82f5b5ccf2SYuanfang Chen PreservedAnalyses run(MachineFunction &MF, 83f5b5ccf2SYuanfang Chen MachineFunctionAnalysisManager &MFAM) { 8491e9e317SArthur Eubanks FunctionAnalysisManager &FAM = 8591e9e317SArthur Eubanks MFAM.getResult<FunctionAnalysisManagerMachineFunctionProxy>(MF) 8691e9e317SArthur Eubanks .getManager(); 87f5b5ccf2SYuanfang Chen TestFunctionAnalysis::Result &FAR = 8891e9e317SArthur Eubanks FAM.getResult<TestFunctionAnalysis>(MF.getFunction()); 89f5b5ccf2SYuanfang Chen Count += FAR.InstructionCount; 90f5b5ccf2SYuanfang Chen 91f5b5ccf2SYuanfang Chen TestMachineFunctionAnalysis::Result &MFAR = 92f5b5ccf2SYuanfang Chen MFAM.getResult<TestMachineFunctionAnalysis>(MF); 93f5b5ccf2SYuanfang Chen Count += MFAR.InstructionCount; 94f5b5ccf2SYuanfang Chen 9591e9e317SArthur Eubanks Counts.push_back(Count); 96f5b5ccf2SYuanfang Chen 97f5b5ccf2SYuanfang Chen return PreservedAnalyses::none(); 98f5b5ccf2SYuanfang Chen } 99f5b5ccf2SYuanfang Chen 100f5b5ccf2SYuanfang Chen int &Count; 10191e9e317SArthur Eubanks std::vector<int> &Counts; 102f5b5ccf2SYuanfang Chen }; 103f5b5ccf2SYuanfang Chen 104f5b5ccf2SYuanfang Chen struct TestMachineModulePass : public PassInfoMixin<TestMachineModulePass> { 10591e9e317SArthur Eubanks TestMachineModulePass(int &Count, std::vector<int> &Counts) 10691e9e317SArthur Eubanks : Count(Count), Counts(Counts) {} 107f5b5ccf2SYuanfang Chen 10891e9e317SArthur Eubanks PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM) { 10991e9e317SArthur Eubanks MachineModuleInfo &MMI = MAM.getResult<MachineModuleAnalysis>(M).getMMI(); 11091e9e317SArthur Eubanks FunctionAnalysisManager &FAM = 11191e9e317SArthur Eubanks MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 11291e9e317SArthur Eubanks MachineFunctionAnalysisManager &MFAM = 11391e9e317SArthur Eubanks MAM.getResult<MachineFunctionAnalysisManagerModuleProxy>(M) 11491e9e317SArthur Eubanks .getManager(); 11591e9e317SArthur Eubanks for (Function &F : M) { 11691e9e317SArthur Eubanks MachineFunction &MF = MMI.getOrCreateMachineFunction(F); 11791e9e317SArthur Eubanks Count += FAM.getResult<TestFunctionAnalysis>(F).InstructionCount; 11891e9e317SArthur Eubanks Count += MFAM.getResult<TestMachineFunctionAnalysis>(MF).InstructionCount; 119f5b5ccf2SYuanfang Chen } 12091e9e317SArthur Eubanks Counts.push_back(Count); 12191e9e317SArthur Eubanks return PreservedAnalyses::all(); 122f5b5ccf2SYuanfang Chen } 123f5b5ccf2SYuanfang Chen 124f5b5ccf2SYuanfang Chen int &Count; 12591e9e317SArthur Eubanks std::vector<int> &Counts; 126f5b5ccf2SYuanfang Chen }; 127f5b5ccf2SYuanfang Chen 128f6ca37bfSpaperchalice struct ReportWarningPass : public PassInfoMixin<ReportWarningPass> { 129f6ca37bfSpaperchalice PreservedAnalyses run(MachineFunction &MF, 130f6ca37bfSpaperchalice MachineFunctionAnalysisManager &MFAM) { 131f6ca37bfSpaperchalice auto &Ctx = MF.getContext(); 132f6ca37bfSpaperchalice Ctx.reportWarning(SMLoc(), "Test warning message."); 133f6ca37bfSpaperchalice return PreservedAnalyses::all(); 134f6ca37bfSpaperchalice } 135f6ca37bfSpaperchalice }; 136f6ca37bfSpaperchalice 137f5b5ccf2SYuanfang Chen std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) { 138f5b5ccf2SYuanfang Chen SMDiagnostic Err; 139f5b5ccf2SYuanfang Chen return parseAssemblyString(IR, Err, Context); 140f5b5ccf2SYuanfang Chen } 141f5b5ccf2SYuanfang Chen 142f5b5ccf2SYuanfang Chen class PassManagerTest : public ::testing::Test { 143f5b5ccf2SYuanfang Chen protected: 144f5b5ccf2SYuanfang Chen LLVMContext Context; 145f5b5ccf2SYuanfang Chen std::unique_ptr<Module> M; 146f5b5ccf2SYuanfang Chen std::unique_ptr<TargetMachine> TM; 147f5b5ccf2SYuanfang Chen 148f5b5ccf2SYuanfang Chen public: 149f5b5ccf2SYuanfang Chen PassManagerTest() 150f5b5ccf2SYuanfang Chen : M(parseIR(Context, "define void @f() {\n" 151f5b5ccf2SYuanfang Chen "entry:\n" 152f5b5ccf2SYuanfang Chen " call void @g()\n" 153f5b5ccf2SYuanfang Chen " call void @h()\n" 154f5b5ccf2SYuanfang Chen " ret void\n" 155f5b5ccf2SYuanfang Chen "}\n" 156f5b5ccf2SYuanfang Chen "define void @g() {\n" 157f5b5ccf2SYuanfang Chen " ret void\n" 158f5b5ccf2SYuanfang Chen "}\n" 159f5b5ccf2SYuanfang Chen "define void @h() {\n" 160f5b5ccf2SYuanfang Chen " ret void\n" 161f5b5ccf2SYuanfang Chen "}\n")) { 162f5b5ccf2SYuanfang Chen // MachineModuleAnalysis needs a TargetMachine instance. 163f5b5ccf2SYuanfang Chen llvm::InitializeAllTargets(); 164f5b5ccf2SYuanfang Chen 165f5b5ccf2SYuanfang Chen std::string TripleName = Triple::normalize(sys::getDefaultTargetTriple()); 166f5b5ccf2SYuanfang Chen std::string Error; 167f5b5ccf2SYuanfang Chen const Target *TheTarget = 168f5b5ccf2SYuanfang Chen TargetRegistry::lookupTarget(TripleName, Error); 169f5b5ccf2SYuanfang Chen if (!TheTarget) 170f5b5ccf2SYuanfang Chen return; 171f5b5ccf2SYuanfang Chen 172f5b5ccf2SYuanfang Chen TargetOptions Options; 173b6a01caaSKazu Hirata TM.reset(TheTarget->createTargetMachine(TripleName, "", "", Options, 174b6a01caaSKazu Hirata std::nullopt)); 175f5b5ccf2SYuanfang Chen } 176f5b5ccf2SYuanfang Chen }; 177f5b5ccf2SYuanfang Chen 178f5b5ccf2SYuanfang Chen TEST_F(PassManagerTest, Basic) { 179f5b5ccf2SYuanfang Chen if (!TM) 1805bbf1feaSIgor Kudrin GTEST_SKIP(); 181f5b5ccf2SYuanfang Chen 182f5b5ccf2SYuanfang Chen M->setDataLayout(TM->createDataLayout()); 183f5b5ccf2SYuanfang Chen 184*bb3f5e1fSMatin Raayai MachineModuleInfo MMI(TM.get()); 18591e9e317SArthur Eubanks 186f6ca37bfSpaperchalice MachineFunctionAnalysisManager MFAM; 1876ea0c0a2Spaperchalice LoopAnalysisManager LAM; 1886f713100SArthur Eubanks FunctionAnalysisManager FAM; 1896f713100SArthur Eubanks CGSCCAnalysisManager CGAM; 1906f713100SArthur Eubanks ModuleAnalysisManager MAM; 191f5b5ccf2SYuanfang Chen PassBuilder PB(TM.get()); 192f5b5ccf2SYuanfang Chen PB.registerModuleAnalyses(MAM); 19391e9e317SArthur Eubanks PB.registerCGSCCAnalyses(CGAM); 194f5b5ccf2SYuanfang Chen PB.registerFunctionAnalyses(FAM); 19591e9e317SArthur Eubanks PB.registerLoopAnalyses(LAM); 19691e9e317SArthur Eubanks PB.registerMachineFunctionAnalyses(MFAM); 19791e9e317SArthur Eubanks PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM); 198f5b5ccf2SYuanfang Chen 199f5b5ccf2SYuanfang Chen FAM.registerPass([&] { return TestFunctionAnalysis(); }); 200bb531c9aSArthur Eubanks MAM.registerPass([&] { return MachineModuleAnalysis(MMI); }); 20191e9e317SArthur Eubanks MFAM.registerPass([&] { return TestMachineFunctionAnalysis(); }); 202f5b5ccf2SYuanfang Chen 203f5b5ccf2SYuanfang Chen int Count = 0; 20491e9e317SArthur Eubanks std::vector<int> Counts; 205f5b5ccf2SYuanfang Chen 20691e9e317SArthur Eubanks ModulePassManager MPM; 2076ea0c0a2Spaperchalice FunctionPassManager FPM; 208f5b5ccf2SYuanfang Chen MachineFunctionPassManager MFPM; 20991e9e317SArthur Eubanks MPM.addPass(TestMachineModulePass(Count, Counts)); 2106ea0c0a2Spaperchalice FPM.addPass(createFunctionToMachineFunctionPassAdaptor( 21191e9e317SArthur Eubanks TestMachineFunctionPass(Count, Counts))); 2126ea0c0a2Spaperchalice MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 21391e9e317SArthur Eubanks MPM.addPass(TestMachineModulePass(Count, Counts)); 21491e9e317SArthur Eubanks MFPM.addPass(TestMachineFunctionPass(Count, Counts)); 2156ea0c0a2Spaperchalice FPM = FunctionPassManager(); 2166ea0c0a2Spaperchalice FPM.addPass(createFunctionToMachineFunctionPassAdaptor(std::move(MFPM))); 2176ea0c0a2Spaperchalice MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 218f5b5ccf2SYuanfang Chen 219f6ca37bfSpaperchalice testing::internal::CaptureStderr(); 22091e9e317SArthur Eubanks MPM.run(*M, MAM); 221f6ca37bfSpaperchalice std::string Output = testing::internal::GetCapturedStderr(); 222f5b5ccf2SYuanfang Chen 22391e9e317SArthur Eubanks EXPECT_EQ((std::vector<int>{10, 16, 18, 20, 30, 36, 38, 40}), Counts); 22491e9e317SArthur Eubanks EXPECT_EQ(40, Count); 225f5b5ccf2SYuanfang Chen } 226f5b5ccf2SYuanfang Chen 227f6ca37bfSpaperchalice TEST_F(PassManagerTest, DiagnosticHandler) { 228f6ca37bfSpaperchalice if (!TM) 229f6ca37bfSpaperchalice GTEST_SKIP(); 230f6ca37bfSpaperchalice 231f6ca37bfSpaperchalice M->setDataLayout(TM->createDataLayout()); 232f6ca37bfSpaperchalice 233*bb3f5e1fSMatin Raayai MachineModuleInfo MMI(TM.get()); 234f6ca37bfSpaperchalice 235f6ca37bfSpaperchalice LoopAnalysisManager LAM; 236f6ca37bfSpaperchalice MachineFunctionAnalysisManager MFAM; 237f6ca37bfSpaperchalice FunctionAnalysisManager FAM; 238f6ca37bfSpaperchalice CGSCCAnalysisManager CGAM; 239f6ca37bfSpaperchalice ModuleAnalysisManager MAM; 240f6ca37bfSpaperchalice PassBuilder PB(TM.get()); 241f6ca37bfSpaperchalice PB.registerModuleAnalyses(MAM); 242f6ca37bfSpaperchalice PB.registerCGSCCAnalyses(CGAM); 243f6ca37bfSpaperchalice PB.registerFunctionAnalyses(FAM); 244f6ca37bfSpaperchalice PB.registerLoopAnalyses(LAM); 245f6ca37bfSpaperchalice PB.registerMachineFunctionAnalyses(MFAM); 246f6ca37bfSpaperchalice PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM); 247f6ca37bfSpaperchalice 248f6ca37bfSpaperchalice MAM.registerPass([&] { return MachineModuleAnalysis(MMI); }); 249f6ca37bfSpaperchalice 250f6ca37bfSpaperchalice ModulePassManager MPM; 251f6ca37bfSpaperchalice FunctionPassManager FPM; 252f6ca37bfSpaperchalice MachineFunctionPassManager MFPM; 2536ea0c0a2Spaperchalice MPM.addPass(RequireAnalysisPass<MachineModuleAnalysis, Module>()); 254f6ca37bfSpaperchalice MFPM.addPass(ReportWarningPass()); 2556ea0c0a2Spaperchalice FPM.addPass(createFunctionToMachineFunctionPassAdaptor(std::move(MFPM))); 2566ea0c0a2Spaperchalice MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 257f6ca37bfSpaperchalice testing::internal::CaptureStderr(); 258f6ca37bfSpaperchalice MPM.run(*M, MAM); 259f6ca37bfSpaperchalice std::string Output = testing::internal::GetCapturedStderr(); 260f6ca37bfSpaperchalice 261f6ca37bfSpaperchalice EXPECT_TRUE(Output.find("warning: <unknown>:0: Test warning message.") != 262f6ca37bfSpaperchalice std::string::npos); 263f6ca37bfSpaperchalice } 264f6ca37bfSpaperchalice 265f5b5ccf2SYuanfang Chen } // namespace 266