1 //===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/Function.h"
12 #include "llvm/IR/LLVMContext.h"
13 #include "llvm/IR/Module.h"
14 #include "llvm/IR/PassManager.h"
15 #include "llvm/Support/SourceMgr.h"
16 #include "gtest/gtest.h"
17
18 using namespace llvm;
19
20 namespace {
21
22 class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
23 public:
24 struct Result {
Result__anon5a000c130111::TestFunctionAnalysis::Result25 Result(int Count) : InstructionCount(Count) {}
26 int InstructionCount;
27 };
28
TestFunctionAnalysis(int & Runs)29 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
30
31 /// \brief Run the analysis pass over the function and return a result.
run(Function & F,FunctionAnalysisManager & AM)32 Result run(Function &F, FunctionAnalysisManager &AM) {
33 ++Runs;
34 int Count = 0;
35 for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI)
36 for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
37 ++II)
38 ++Count;
39 return Result(Count);
40 }
41
42 private:
43 friend AnalysisInfoMixin<TestFunctionAnalysis>;
44 static char PassID;
45
46 int &Runs;
47 };
48
49 char TestFunctionAnalysis::PassID;
50
51 class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
52 public:
53 struct Result {
Result__anon5a000c130111::TestModuleAnalysis::Result54 Result(int Count) : FunctionCount(Count) {}
55 int FunctionCount;
56 };
57
TestModuleAnalysis(int & Runs)58 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
59
run(Module & M,ModuleAnalysisManager & AM)60 Result run(Module &M, ModuleAnalysisManager &AM) {
61 ++Runs;
62 int Count = 0;
63 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
64 ++Count;
65 return Result(Count);
66 }
67
68 private:
69 friend AnalysisInfoMixin<TestModuleAnalysis>;
70 static char PassID;
71
72 int &Runs;
73 };
74
75 char TestModuleAnalysis::PassID;
76
77 struct TestModulePass : PassInfoMixin<TestModulePass> {
TestModulePass__anon5a000c130111::TestModulePass78 TestModulePass(int &RunCount) : RunCount(RunCount) {}
79
run__anon5a000c130111::TestModulePass80 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
81 ++RunCount;
82 return PreservedAnalyses::none();
83 }
84
85 int &RunCount;
86 };
87
88 struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> {
run__anon5a000c130111::TestPreservingModulePass89 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
90 return PreservedAnalyses::all();
91 }
92 };
93
94 struct TestMinPreservingModulePass
95 : PassInfoMixin<TestMinPreservingModulePass> {
run__anon5a000c130111::TestMinPreservingModulePass96 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
97 PreservedAnalyses PA;
98
99 // Force running an analysis.
100 (void)AM.getResult<TestModuleAnalysis>(M);
101
102 PA.preserve<FunctionAnalysisManagerModuleProxy>();
103 return PA;
104 }
105 };
106
107 struct TestFunctionPass : PassInfoMixin<TestFunctionPass> {
TestFunctionPass__anon5a000c130111::TestFunctionPass108 TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
109 int &AnalyzedFunctionCount,
110 bool OnlyUseCachedResults = false)
111 : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
112 AnalyzedFunctionCount(AnalyzedFunctionCount),
113 OnlyUseCachedResults(OnlyUseCachedResults) {}
114
run__anon5a000c130111::TestFunctionPass115 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
116 ++RunCount;
117
118 const ModuleAnalysisManager &MAM =
119 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
120 if (TestModuleAnalysis::Result *TMA =
121 MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()))
122 AnalyzedFunctionCount += TMA->FunctionCount;
123
124 if (OnlyUseCachedResults) {
125 // Hack to force the use of the cached interface.
126 if (TestFunctionAnalysis::Result *AR =
127 AM.getCachedResult<TestFunctionAnalysis>(F))
128 AnalyzedInstrCount += AR->InstructionCount;
129 } else {
130 // Typical path just runs the analysis as needed.
131 TestFunctionAnalysis::Result &AR = AM.getResult<TestFunctionAnalysis>(F);
132 AnalyzedInstrCount += AR.InstructionCount;
133 }
134
135 return PreservedAnalyses::all();
136 }
137
138 int &RunCount;
139 int &AnalyzedInstrCount;
140 int &AnalyzedFunctionCount;
141 bool OnlyUseCachedResults;
142 };
143
144 // A test function pass that invalidates all function analyses for a function
145 // with a specific name.
146 struct TestInvalidationFunctionPass
147 : PassInfoMixin<TestInvalidationFunctionPass> {
TestInvalidationFunctionPass__anon5a000c130111::TestInvalidationFunctionPass148 TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
149
run__anon5a000c130111::TestInvalidationFunctionPass150 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
151 return F.getName() == Name ? PreservedAnalyses::none()
152 : PreservedAnalyses::all();
153 }
154
155 StringRef Name;
156 };
157
parseIR(LLVMContext & Context,const char * IR)158 std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
159 SMDiagnostic Err;
160 return parseAssemblyString(IR, Err, Context);
161 }
162
163 class PassManagerTest : public ::testing::Test {
164 protected:
165 LLVMContext Context;
166 std::unique_ptr<Module> M;
167
168 public:
PassManagerTest()169 PassManagerTest()
170 : M(parseIR(Context, "define void @f() {\n"
171 "entry:\n"
172 " call void @g()\n"
173 " call void @h()\n"
174 " ret void\n"
175 "}\n"
176 "define void @g() {\n"
177 " ret void\n"
178 "}\n"
179 "define void @h() {\n"
180 " ret void\n"
181 "}\n")) {}
182 };
183
TEST_F(PassManagerTest,BasicPreservedAnalyses)184 TEST_F(PassManagerTest, BasicPreservedAnalyses) {
185 PreservedAnalyses PA1 = PreservedAnalyses();
186 EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>());
187 EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>());
188 PreservedAnalyses PA2 = PreservedAnalyses::none();
189 EXPECT_FALSE(PA2.preserved<TestFunctionAnalysis>());
190 EXPECT_FALSE(PA2.preserved<TestModuleAnalysis>());
191 PreservedAnalyses PA3 = PreservedAnalyses::all();
192 EXPECT_TRUE(PA3.preserved<TestFunctionAnalysis>());
193 EXPECT_TRUE(PA3.preserved<TestModuleAnalysis>());
194 PreservedAnalyses PA4 = PA1;
195 EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>());
196 EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
197 PA4 = PA3;
198 EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>());
199 EXPECT_TRUE(PA4.preserved<TestModuleAnalysis>());
200 PA4 = std::move(PA2);
201 EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>());
202 EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
203 PA4.preserve<TestFunctionAnalysis>();
204 EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>());
205 EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
206 PA1.preserve<TestModuleAnalysis>();
207 EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>());
208 EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>());
209 PA1.preserve<TestFunctionAnalysis>();
210 EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>());
211 EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>());
212 PA1.intersect(PA4);
213 EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>());
214 EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>());
215 }
216
TEST_F(PassManagerTest,Basic)217 TEST_F(PassManagerTest, Basic) {
218 FunctionAnalysisManager FAM;
219 int FunctionAnalysisRuns = 0;
220 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
221
222 ModuleAnalysisManager MAM;
223 int ModuleAnalysisRuns = 0;
224 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
225 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
226 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
227
228 ModulePassManager MPM;
229
230 // Count the runs over a Function.
231 int FunctionPassRunCount1 = 0;
232 int AnalyzedInstrCount1 = 0;
233 int AnalyzedFunctionCount1 = 0;
234 {
235 // Pointless scoped copy to test move assignment.
236 ModulePassManager NestedMPM;
237 FunctionPassManager FPM;
238 {
239 // Pointless scope to test move assignment.
240 FunctionPassManager NestedFPM;
241 NestedFPM.addPass(TestFunctionPass(
242 FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1));
243 FPM = std::move(NestedFPM);
244 }
245 NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
246 MPM = std::move(NestedMPM);
247 }
248
249 // Count the runs over a module.
250 int ModulePassRunCount = 0;
251 MPM.addPass(TestModulePass(ModulePassRunCount));
252
253 // Count the runs over a Function in a separate manager.
254 int FunctionPassRunCount2 = 0;
255 int AnalyzedInstrCount2 = 0;
256 int AnalyzedFunctionCount2 = 0;
257 {
258 FunctionPassManager FPM;
259 FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
260 AnalyzedFunctionCount2));
261 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
262 }
263
264 // A third function pass manager but with only preserving intervening passes
265 // and with a function pass that invalidates exactly one analysis.
266 MPM.addPass(TestPreservingModulePass());
267 int FunctionPassRunCount3 = 0;
268 int AnalyzedInstrCount3 = 0;
269 int AnalyzedFunctionCount3 = 0;
270 {
271 FunctionPassManager FPM;
272 FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
273 AnalyzedFunctionCount3));
274 FPM.addPass(TestInvalidationFunctionPass("f"));
275 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
276 }
277
278 // A fourth function pass manager but with a minimal intervening passes.
279 MPM.addPass(TestMinPreservingModulePass());
280 int FunctionPassRunCount4 = 0;
281 int AnalyzedInstrCount4 = 0;
282 int AnalyzedFunctionCount4 = 0;
283 {
284 FunctionPassManager FPM;
285 FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
286 AnalyzedFunctionCount4));
287 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
288 }
289
290 // A fifth function pass manager but which uses only cached results.
291 int FunctionPassRunCount5 = 0;
292 int AnalyzedInstrCount5 = 0;
293 int AnalyzedFunctionCount5 = 0;
294 {
295 FunctionPassManager FPM;
296 FPM.addPass(TestInvalidationFunctionPass("f"));
297 FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
298 AnalyzedFunctionCount5,
299 /*OnlyUseCachedResults=*/true));
300 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
301 }
302
303 MPM.run(*M, MAM);
304
305 // Validate module pass counters.
306 EXPECT_EQ(1, ModulePassRunCount);
307
308 // Validate all function pass counter sets are the same.
309 EXPECT_EQ(3, FunctionPassRunCount1);
310 EXPECT_EQ(5, AnalyzedInstrCount1);
311 EXPECT_EQ(0, AnalyzedFunctionCount1);
312 EXPECT_EQ(3, FunctionPassRunCount2);
313 EXPECT_EQ(5, AnalyzedInstrCount2);
314 EXPECT_EQ(0, AnalyzedFunctionCount2);
315 EXPECT_EQ(3, FunctionPassRunCount3);
316 EXPECT_EQ(5, AnalyzedInstrCount3);
317 EXPECT_EQ(0, AnalyzedFunctionCount3);
318 EXPECT_EQ(3, FunctionPassRunCount4);
319 EXPECT_EQ(5, AnalyzedInstrCount4);
320 EXPECT_EQ(0, AnalyzedFunctionCount4);
321 EXPECT_EQ(3, FunctionPassRunCount5);
322 EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
323 EXPECT_EQ(0, AnalyzedFunctionCount5);
324
325 // Validate the analysis counters:
326 // first run over 3 functions, then module pass invalidates
327 // second run over 3 functions, nothing invalidates
328 // third run over 0 functions, but 1 function invalidated
329 // fourth run over 1 function
330 EXPECT_EQ(7, FunctionAnalysisRuns);
331
332 EXPECT_EQ(1, ModuleAnalysisRuns);
333 }
334 }
335