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