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