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 {
23 public:
24 struct Result {
Result__anone814850a0111::TestFunctionAnalysis::Result25 Result(int Count) : InstructionCount(Count) {}
26 int InstructionCount;
27 };
28
29 /// \brief Returns an opaque, unique ID for this pass type.
ID()30 static void *ID() { return (void *)&PassID; }
31
32 /// \brief Returns the name of the analysis.
name()33 static StringRef name() { return "TestFunctionAnalysis"; }
34
TestFunctionAnalysis(int & Runs)35 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
36
37 /// \brief Run the analysis pass over the function and return a result.
run(Function & F,FunctionAnalysisManager * AM)38 Result run(Function &F, FunctionAnalysisManager *AM) {
39 ++Runs;
40 int Count = 0;
41 for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI)
42 for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
43 ++II)
44 ++Count;
45 return Result(Count);
46 }
47
48 private:
49 /// \brief Private static data to provide unique ID.
50 static char PassID;
51
52 int &Runs;
53 };
54
55 char TestFunctionAnalysis::PassID;
56
57 class TestModuleAnalysis {
58 public:
59 struct Result {
Result__anone814850a0111::TestModuleAnalysis::Result60 Result(int Count) : FunctionCount(Count) {}
61 int FunctionCount;
62 };
63
ID()64 static void *ID() { return (void *)&PassID; }
65
name()66 static StringRef name() { return "TestModuleAnalysis"; }
67
TestModuleAnalysis(int & Runs)68 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
69
run(Module & M,ModuleAnalysisManager * AM)70 Result run(Module &M, ModuleAnalysisManager *AM) {
71 ++Runs;
72 int Count = 0;
73 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
74 ++Count;
75 return Result(Count);
76 }
77
78 private:
79 static char PassID;
80
81 int &Runs;
82 };
83
84 char TestModuleAnalysis::PassID;
85
86 struct TestModulePass {
TestModulePass__anone814850a0111::TestModulePass87 TestModulePass(int &RunCount) : RunCount(RunCount) {}
88
run__anone814850a0111::TestModulePass89 PreservedAnalyses run(Module &M) {
90 ++RunCount;
91 return PreservedAnalyses::none();
92 }
93
name__anone814850a0111::TestModulePass94 static StringRef name() { return "TestModulePass"; }
95
96 int &RunCount;
97 };
98
99 struct TestPreservingModulePass {
run__anone814850a0111::TestPreservingModulePass100 PreservedAnalyses run(Module &M) { return PreservedAnalyses::all(); }
101
name__anone814850a0111::TestPreservingModulePass102 static StringRef name() { return "TestPreservingModulePass"; }
103 };
104
105 struct TestMinPreservingModulePass {
run__anone814850a0111::TestMinPreservingModulePass106 PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) {
107 PreservedAnalyses PA;
108
109 // Force running an analysis.
110 (void)AM->getResult<TestModuleAnalysis>(M);
111
112 PA.preserve<FunctionAnalysisManagerModuleProxy>();
113 return PA;
114 }
115
name__anone814850a0111::TestMinPreservingModulePass116 static StringRef name() { return "TestMinPreservingModulePass"; }
117 };
118
119 struct TestFunctionPass {
TestFunctionPass__anone814850a0111::TestFunctionPass120 TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
121 int &AnalyzedFunctionCount,
122 bool OnlyUseCachedResults = false)
123 : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
124 AnalyzedFunctionCount(AnalyzedFunctionCount),
125 OnlyUseCachedResults(OnlyUseCachedResults) {}
126
run__anone814850a0111::TestFunctionPass127 PreservedAnalyses run(Function &F, FunctionAnalysisManager *AM) {
128 ++RunCount;
129
130 const ModuleAnalysisManager &MAM =
131 AM->getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
132 if (TestModuleAnalysis::Result *TMA =
133 MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()))
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 }
146
147 return PreservedAnalyses::all();
148 }
149
name__anone814850a0111::TestFunctionPass150 static StringRef name() { return "TestFunctionPass"; }
151
152 int &RunCount;
153 int &AnalyzedInstrCount;
154 int &AnalyzedFunctionCount;
155 bool OnlyUseCachedResults;
156 };
157
158 // A test function pass that invalidates all function analyses for a function
159 // with a specific name.
160 struct TestInvalidationFunctionPass {
TestInvalidationFunctionPass__anone814850a0111::TestInvalidationFunctionPass161 TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
162
run__anone814850a0111::TestInvalidationFunctionPass163 PreservedAnalyses run(Function &F) {
164 return F.getName() == Name ? PreservedAnalyses::none()
165 : PreservedAnalyses::all();
166 }
167
name__anone814850a0111::TestInvalidationFunctionPass168 static StringRef name() { return "TestInvalidationFunctionPass"; }
169
170 StringRef Name;
171 };
172
parseIR(const char * IR)173 std::unique_ptr<Module> parseIR(const char *IR) {
174 LLVMContext &C = getGlobalContext();
175 SMDiagnostic Err;
176 return parseAssemblyString(IR, Err, C);
177 }
178
179 class PassManagerTest : public ::testing::Test {
180 protected:
181 std::unique_ptr<Module> M;
182
183 public:
PassManagerTest()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
TEST_F(PassManagerTest,BasicPreservedAnalyses)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 }
231
TEST_F(PassManagerTest,Basic)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 }
263
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 }
278
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 }
292
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 }
304
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)));
316 }
317
318 MPM.run(*M, &MAM);
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 }
350