1//===- llvm/unittest/CodeGen/PassManager.cpp - PassManager tests ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// Test that the various MachineFunction pass managers, adaptors, analyses, and
9// analysis managers work.
10//===----------------------------------------------------------------------===//
11
12#include "llvm/IR/PassManager.h"
13#include "llvm/Analysis/CGSCCPassManager.h"
14#include "llvm/Analysis/LoopAnalysisManager.h"
15#include "llvm/AsmParser/Parser.h"
16#include "llvm/CodeGen/MachineFunction.h"
17#include "llvm/CodeGen/MachineModuleInfo.h"
18#include "llvm/CodeGen/MachinePassManager.h"
19#include "llvm/IR/Analysis.h"
20#include "llvm/IR/LLVMContext.h"
21#include "llvm/IR/Module.h"
22#include "llvm/MC/TargetRegistry.h"
23#include "llvm/Passes/PassBuilder.h"
24#include "llvm/Support/SourceMgr.h"
25#include "llvm/Support/TargetSelect.h"
26#include "llvm/Target/TargetMachine.h"
27#include "llvm/TargetParser/Host.h"
28#include "llvm/TargetParser/Triple.h"
29#include "gtest/gtest.h"
30
31using namespace llvm;
32
33namespace {
34
35class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
36public:
37 struct Result {
38 Result(int Count) : InstructionCount(Count) {}
39 int InstructionCount;
40 };
41
42 /// The number of instructions in the Function.
43 Result run(Function &F, FunctionAnalysisManager &AM) {
44 return Result(F.getInstructionCount());
45 }
46
47private:
48 friend AnalysisInfoMixin<TestFunctionAnalysis>;
49 static AnalysisKey Key;
50};
51
52AnalysisKey TestFunctionAnalysis::Key;
53
54class TestMachineFunctionAnalysis
55 : public AnalysisInfoMixin<TestMachineFunctionAnalysis> {
56public:
57 struct Result {
58 Result(int Count) : InstructionCount(Count) {}
59 int InstructionCount;
60 };
61
62 Result run(MachineFunction &MF, MachineFunctionAnalysisManager &AM) {
63 FunctionAnalysisManager &FAM =
64 AM.getResult<FunctionAnalysisManagerMachineFunctionProxy>(IR&: MF)
65 .getManager();
66 TestFunctionAnalysis::Result &FAR =
67 FAM.getResult<TestFunctionAnalysis>(IR&: MF.getFunction());
68 return FAR.InstructionCount;
69 }
70
71private:
72 friend AnalysisInfoMixin<TestMachineFunctionAnalysis>;
73 static AnalysisKey Key;
74};
75
76AnalysisKey TestMachineFunctionAnalysis::Key;
77
78struct TestMachineFunctionPass : public PassInfoMixin<TestMachineFunctionPass> {
79 TestMachineFunctionPass(int &Count, std::vector<int> &Counts)
80 : Count(Count), Counts(Counts) {}
81
82 PreservedAnalyses run(MachineFunction &MF,
83 MachineFunctionAnalysisManager &MFAM) {
84 FunctionAnalysisManager &FAM =
85 MFAM.getResult<FunctionAnalysisManagerMachineFunctionProxy>(IR&: MF)
86 .getManager();
87 TestFunctionAnalysis::Result &FAR =
88 FAM.getResult<TestFunctionAnalysis>(IR&: MF.getFunction());
89 Count += FAR.InstructionCount;
90
91 TestMachineFunctionAnalysis::Result &MFAR =
92 MFAM.getResult<TestMachineFunctionAnalysis>(IR&: MF);
93 Count += MFAR.InstructionCount;
94
95 Counts.push_back(x: Count);
96
97 return PreservedAnalyses::none();
98 }
99
100 int &Count;
101 std::vector<int> &Counts;
102};
103
104struct TestMachineModulePass : public PassInfoMixin<TestMachineModulePass> {
105 TestMachineModulePass(int &Count, std::vector<int> &Counts)
106 : Count(Count), Counts(Counts) {}
107
108 PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM) {
109 MachineModuleInfo &MMI = MAM.getResult<MachineModuleAnalysis>(IR&: M).getMMI();
110 FunctionAnalysisManager &FAM =
111 MAM.getResult<FunctionAnalysisManagerModuleProxy>(IR&: M).getManager();
112 MachineFunctionAnalysisManager &MFAM =
113 MAM.getResult<MachineFunctionAnalysisManagerModuleProxy>(IR&: M)
114 .getManager();
115 for (Function &F : M) {
116 MachineFunction &MF = MMI.getOrCreateMachineFunction(F);
117 Count += FAM.getResult<TestFunctionAnalysis>(IR&: F).InstructionCount;
118 Count += MFAM.getResult<TestMachineFunctionAnalysis>(IR&: MF).InstructionCount;
119 }
120 Counts.push_back(x: Count);
121 return PreservedAnalyses::all();
122 }
123
124 int &Count;
125 std::vector<int> &Counts;
126};
127
128struct ReportWarningPass : public PassInfoMixin<ReportWarningPass> {
129 PreservedAnalyses run(MachineFunction &MF,
130 MachineFunctionAnalysisManager &MFAM) {
131 auto &Ctx = MF.getContext();
132 Ctx.reportWarning(L: SMLoc(), Msg: "Test warning message.");
133 return PreservedAnalyses::all();
134 }
135};
136
137std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
138 SMDiagnostic Err;
139 return parseAssemblyString(AsmString: IR, Err, Context);
140}
141
142class PassManagerTest : public ::testing::Test {
143protected:
144 LLVMContext Context;
145 std::unique_ptr<Module> M;
146 std::unique_ptr<TargetMachine> TM;
147
148public:
149 PassManagerTest()
150 : M(parseIR(Context, IR: "define void @f() {\n"
151 "entry:\n"
152 " call void @g()\n"
153 " call void @h()\n"
154 " ret void\n"
155 "}\n"
156 "define void @g() {\n"
157 " ret void\n"
158 "}\n"
159 "define void @h() {\n"
160 " ret void\n"
161 "}\n")) {
162 // MachineModuleAnalysis needs a TargetMachine instance.
163 llvm::InitializeAllTargets();
164
165 std::string TripleName = Triple::normalize(Str: sys::getDefaultTargetTriple());
166 std::string Error;
167 const Target *TheTarget =
168 TargetRegistry::lookupTarget(Triple: TripleName, Error);
169 if (!TheTarget)
170 return;
171
172 TargetOptions Options;
173 TM.reset(p: TheTarget->createTargetMachine(TT: TripleName, CPU: "", Features: "", Options,
174 RM: std::nullopt));
175 }
176};
177
178TEST_F(PassManagerTest, Basic) {
179 if (!TM)
180 GTEST_SKIP();
181
182 LLVMTargetMachine *LLVMTM = static_cast<LLVMTargetMachine *>(TM.get());
183 M->setDataLayout(TM->createDataLayout());
184
185 MachineModuleInfo MMI(LLVMTM);
186
187 LoopAnalysisManager LAM;
188 MachineFunctionAnalysisManager MFAM;
189 FunctionAnalysisManager FAM;
190 CGSCCAnalysisManager CGAM;
191 ModuleAnalysisManager MAM;
192 PassBuilder PB(TM.get());
193 PB.registerModuleAnalyses(MAM);
194 PB.registerCGSCCAnalyses(CGAM);
195 PB.registerFunctionAnalyses(FAM);
196 PB.registerLoopAnalyses(LAM);
197 PB.registerMachineFunctionAnalyses(MFAM);
198 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, MFAM: &MFAM);
199
200 FAM.registerPass(PassBuilder: [&] { return TestFunctionAnalysis(); });
201 MAM.registerPass(PassBuilder: [&] { return MachineModuleAnalysis(MMI); });
202 MFAM.registerPass(PassBuilder: [&] { return TestMachineFunctionAnalysis(); });
203
204 int Count = 0;
205 std::vector<int> Counts;
206
207 ModulePassManager MPM;
208 MachineFunctionPassManager MFPM;
209 MPM.addPass(Pass: TestMachineModulePass(Count, Counts));
210 MPM.addPass(Pass: createModuleToMachineFunctionPassAdaptor(
211 Pass: TestMachineFunctionPass(Count, Counts)));
212 MPM.addPass(Pass: TestMachineModulePass(Count, Counts));
213 MFPM.addPass(Pass: TestMachineFunctionPass(Count, Counts));
214 MPM.addPass(Pass: createModuleToMachineFunctionPassAdaptor(Pass: std::move(MFPM)));
215
216 testing::internal::CaptureStderr();
217 MPM.run(IR&: *M, AM&: MAM);
218 std::string Output = testing::internal::GetCapturedStderr();
219
220 EXPECT_EQ((std::vector<int>{10, 16, 18, 20, 30, 36, 38, 40}), Counts);
221 EXPECT_EQ(40, Count);
222}
223
224TEST_F(PassManagerTest, DiagnosticHandler) {
225 if (!TM)
226 GTEST_SKIP();
227
228 LLVMTargetMachine *LLVMTM = static_cast<LLVMTargetMachine *>(TM.get());
229 M->setDataLayout(TM->createDataLayout());
230
231 MachineModuleInfo MMI(LLVMTM);
232
233 LoopAnalysisManager LAM;
234 MachineFunctionAnalysisManager MFAM;
235 FunctionAnalysisManager FAM;
236 CGSCCAnalysisManager CGAM;
237 ModuleAnalysisManager MAM;
238 PassBuilder PB(TM.get());
239 PB.registerModuleAnalyses(MAM);
240 PB.registerCGSCCAnalyses(CGAM);
241 PB.registerFunctionAnalyses(FAM);
242 PB.registerLoopAnalyses(LAM);
243 PB.registerMachineFunctionAnalyses(MFAM);
244 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, MFAM: &MFAM);
245
246 MAM.registerPass(PassBuilder: [&] { return MachineModuleAnalysis(MMI); });
247
248 ModulePassManager MPM;
249 FunctionPassManager FPM;
250 MachineFunctionPassManager MFPM;
251 MFPM.addPass(Pass: ReportWarningPass());
252 MPM.addPass(Pass: createModuleToMachineFunctionPassAdaptor(Pass: std::move(MFPM)));
253 testing::internal::CaptureStderr();
254 MPM.run(IR&: *M, AM&: MAM);
255 std::string Output = testing::internal::GetCapturedStderr();
256
257 EXPECT_TRUE(Output.find("warning: <unknown>:0: Test warning message.") !=
258 std::string::npos);
259}
260
261} // namespace
262

source code of llvm/unittests/CodeGen/PassManagerTest.cpp