• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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