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