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