[PM] Rename TestAnalysisPass to TestFunctionAnalysis to clear the way
[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 struct TestModulePass {
55   TestModulePass(int &RunCount) : RunCount(RunCount) {}
56
57   PreservedAnalyses run(Module *M) {
58     ++RunCount;
59     return PreservedAnalyses::none();
60   }
61
62   int &RunCount;
63 };
64
65 struct TestPreservingModulePass {
66   PreservedAnalyses run(Module *M) {
67     return PreservedAnalyses::all();
68   }
69 };
70
71 struct TestMinPreservingModulePass {
72   PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) {
73     PreservedAnalyses PA;
74
75     // Check that we can get cached result objects for modules.
76     const FunctionAnalysisManagerModuleProxy::Result *R =
77         AM->getCachedResult<FunctionAnalysisManagerModuleProxy>(M);
78     (void)R; // FIXME: We should test this better by querying an actual analysis
79              // pass in interesting ways.
80
81     PA.preserve<FunctionAnalysisManagerModuleProxy>();
82     return PA;
83   }
84 };
85
86 struct TestFunctionPass {
87   TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
88                    bool OnlyUseCachedResults = false)
89       : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
90         OnlyUseCachedResults(OnlyUseCachedResults) {}
91
92   PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM) {
93     ++RunCount;
94
95     if (OnlyUseCachedResults) {
96       // Hack to force the use of the cached interface.
97       if (const TestFunctionAnalysis::Result *AR =
98               AM->getCachedResult<TestFunctionAnalysis>(F))
99         AnalyzedInstrCount += AR->InstructionCount;
100     } else {
101       // Typical path just runs the analysis as needed.
102       const TestFunctionAnalysis::Result &AR = AM->getResult<TestFunctionAnalysis>(F);
103       AnalyzedInstrCount += AR.InstructionCount;
104     }
105
106     return PreservedAnalyses::all();
107   }
108
109   int &RunCount;
110   int &AnalyzedInstrCount;
111   bool OnlyUseCachedResults;
112 };
113
114 // A test function pass that invalidates all function analyses for a function
115 // with a specific name.
116 struct TestInvalidationFunctionPass {
117   TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
118
119   PreservedAnalyses run(Function *F) {
120     return F->getName() == Name ? PreservedAnalyses::none()
121                                 : PreservedAnalyses::all();
122   }
123
124   StringRef Name;
125 };
126
127 Module *parseIR(const char *IR) {
128   LLVMContext &C = getGlobalContext();
129   SMDiagnostic Err;
130   return ParseAssemblyString(IR, 0, Err, C);
131 }
132
133 class PassManagerTest : public ::testing::Test {
134 protected:
135   OwningPtr<Module> M;
136
137 public:
138   PassManagerTest()
139       : M(parseIR("define void @f() {\n"
140                   "entry:\n"
141                   "  call void @g()\n"
142                   "  call void @h()\n"
143                   "  ret void\n"
144                   "}\n"
145                   "define void @g() {\n"
146                   "  ret void\n"
147                   "}\n"
148                   "define void @h() {\n"
149                   "  ret void\n"
150                   "}\n")) {}
151 };
152
153 TEST_F(PassManagerTest, Basic) {
154   FunctionAnalysisManager FAM;
155   int AnalysisRuns = 0;
156   FAM.registerPass(TestFunctionAnalysis(AnalysisRuns));
157
158   ModuleAnalysisManager MAM;
159   MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM));
160
161   ModulePassManager MPM;
162
163   // Count the runs over a Function.
164   FunctionPassManager FPM1;
165   int FunctionPassRunCount1 = 0;
166   int AnalyzedInstrCount1 = 0;
167   FPM1.addPass(TestFunctionPass(FunctionPassRunCount1, AnalyzedInstrCount1));
168   MPM.addPass(createModuleToFunctionPassAdaptor(FPM1));
169
170   // Count the runs over a module.
171   int ModulePassRunCount = 0;
172   MPM.addPass(TestModulePass(ModulePassRunCount));
173
174   // Count the runs over a Function in a separate manager.
175   FunctionPassManager FPM2;
176   int FunctionPassRunCount2 = 0;
177   int AnalyzedInstrCount2 = 0;
178   FPM2.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2));
179   MPM.addPass(createModuleToFunctionPassAdaptor(FPM2));
180
181   // A third function pass manager but with only preserving intervening passes
182   // and with a function pass that invalidates exactly one analysis.
183   MPM.addPass(TestPreservingModulePass());
184   FunctionPassManager FPM3;
185   int FunctionPassRunCount3 = 0;
186   int AnalyzedInstrCount3 = 0;
187   FPM3.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3));
188   FPM3.addPass(TestInvalidationFunctionPass("f"));
189   MPM.addPass(createModuleToFunctionPassAdaptor(FPM3));
190
191   // A fourth function pass manager but with a minimal intervening passes.
192   MPM.addPass(TestMinPreservingModulePass());
193   FunctionPassManager FPM4;
194   int FunctionPassRunCount4 = 0;
195   int AnalyzedInstrCount4 = 0;
196   FPM4.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4));
197   MPM.addPass(createModuleToFunctionPassAdaptor(FPM4));
198
199   // A fifth function pass manager but which uses only cached results.
200   FunctionPassManager FPM5;
201   int FunctionPassRunCount5 = 0;
202   int AnalyzedInstrCount5 = 0;
203   FPM5.addPass(TestInvalidationFunctionPass("f"));
204   FPM5.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
205                                 /*OnlyUseCachedResults=*/true));
206   MPM.addPass(createModuleToFunctionPassAdaptor(FPM5));
207
208   MPM.run(M.get(), &MAM);
209
210   // Validate module pass counters.
211   EXPECT_EQ(1, ModulePassRunCount);
212
213   // Validate all function pass counter sets are the same.
214   EXPECT_EQ(3, FunctionPassRunCount1);
215   EXPECT_EQ(5, AnalyzedInstrCount1);
216   EXPECT_EQ(3, FunctionPassRunCount2);
217   EXPECT_EQ(5, AnalyzedInstrCount2);
218   EXPECT_EQ(3, FunctionPassRunCount3);
219   EXPECT_EQ(5, AnalyzedInstrCount3);
220   EXPECT_EQ(3, FunctionPassRunCount4);
221   EXPECT_EQ(5, AnalyzedInstrCount4);
222   EXPECT_EQ(3, FunctionPassRunCount5);
223   EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
224
225   // Validate the analysis counters:
226   //   first run over 3 functions, then module pass invalidates
227   //   second run over 3 functions, nothing invalidates
228   //   third run over 0 functions, but 1 function invalidated
229   //   fourth run over 1 function
230   EXPECT_EQ(7, AnalysisRuns);
231 }
232 }