xref: /llvm-project/llvm/unittests/CodeGen/PassManagerTest.cpp (revision bb3f5e1fed7c6ba733b7f273e93f5d3930976185)
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