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