blob: 47fb8b70f1bd775cce285d770a2899952a049665 [file] [log] [blame]
Chandler Carruth90a835d2013-11-09 13:09:08 +00001//===- 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
Chandler Carruth9aca9182014-01-07 12:34:26 +000010#include "llvm/AsmParser/Parser.h"
Chandler Carruth90a835d2013-11-09 13:09:08 +000011#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
18using namespace llvm;
19
20namespace {
21
Chandler Carruth30a07302016-03-11 10:33:22 +000022class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
Chandler Carruth74015a72013-11-13 01:12:08 +000023public:
Chandler Carruth74015a72013-11-13 01:12:08 +000024 struct Result {
25 Result(int Count) : InstructionCount(Count) {}
Chandler Carruth74015a72013-11-13 01:12:08 +000026 int InstructionCount;
27 };
28
Chandler Carruth2ad18582013-11-23 01:25:02 +000029 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
Chandler Carruth851a2aa2013-11-21 02:11:31 +000030
Chandler Carruth74015a72013-11-13 01:12:08 +000031 /// \brief Run the analysis pass over the function and return a result.
Chandler Carruthb47f8012016-03-11 11:05:24 +000032 Result run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruth851a2aa2013-11-21 02:11:31 +000033 ++Runs;
Chandler Carruth74015a72013-11-13 01:12:08 +000034 int Count = 0;
Chandler Carruthd174ce42015-01-05 02:47:05 +000035 for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI)
Chandler Carruth74015a72013-11-13 01:12:08 +000036 for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
37 ++II)
38 ++Count;
39 return Result(Count);
40 }
41
42private:
Chandler Carruth30a07302016-03-11 10:33:22 +000043 friend AnalysisInfoMixin<TestFunctionAnalysis>;
Chandler Carruthb4faf132016-03-11 10:22:49 +000044 static char PassID;
45
Chandler Carruth851a2aa2013-11-21 02:11:31 +000046 int &Runs;
Chandler Carruth74015a72013-11-13 01:12:08 +000047};
48
Chandler Carruthb4faf132016-03-11 10:22:49 +000049char TestFunctionAnalysis::PassID;
50
Chandler Carruth30a07302016-03-11 10:33:22 +000051class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000052public:
53 struct Result {
54 Result(int Count) : FunctionCount(Count) {}
55 int FunctionCount;
56 };
57
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000058 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
59
Chandler Carruthb47f8012016-03-11 11:05:24 +000060 Result run(Module &M, ModuleAnalysisManager &AM) {
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000061 ++Runs;
62 int Count = 0;
Chandler Carruthd174ce42015-01-05 02:47:05 +000063 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000064 ++Count;
65 return Result(Count);
66 }
67
68private:
Chandler Carruth30a07302016-03-11 10:33:22 +000069 friend AnalysisInfoMixin<TestModuleAnalysis>;
Chandler Carruthb4faf132016-03-11 10:22:49 +000070 static char PassID;
71
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000072 int &Runs;
73};
74
Chandler Carruthb4faf132016-03-11 10:22:49 +000075char TestModuleAnalysis::PassID;
76
Chandler Carruth30a07302016-03-11 10:33:22 +000077struct TestModulePass : PassInfoMixin<TestModulePass> {
Chandler Carruth90a835d2013-11-09 13:09:08 +000078 TestModulePass(int &RunCount) : RunCount(RunCount) {}
79
Chandler Carruth164a2aa62016-06-17 00:11:01 +000080 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
Chandler Carruth90a835d2013-11-09 13:09:08 +000081 ++RunCount;
Chandler Carruthc0bfa8c2013-11-20 11:31:50 +000082 return PreservedAnalyses::none();
Chandler Carruth90a835d2013-11-09 13:09:08 +000083 }
84
85 int &RunCount;
86};
87
Chandler Carruth30a07302016-03-11 10:33:22 +000088struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> {
Chandler Carruth164a2aa62016-06-17 00:11:01 +000089 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
90 return PreservedAnalyses::all();
91 }
Chandler Carruth2846e9e2013-11-21 10:53:05 +000092};
93
Chandler Carruth30a07302016-03-11 10:33:22 +000094struct TestMinPreservingModulePass
95 : PassInfoMixin<TestMinPreservingModulePass> {
Chandler Carruthb47f8012016-03-11 11:05:24 +000096 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
Chandler Carruth2846e9e2013-11-21 10:53:05 +000097 PreservedAnalyses PA;
Chandler Carruthde9afd82013-11-23 00:38:42 +000098
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000099 // Force running an analysis.
Chandler Carruthb47f8012016-03-11 11:05:24 +0000100 (void)AM.getResult<TestModuleAnalysis>(M);
Chandler Carruthde9afd82013-11-23 00:38:42 +0000101
Chandler Carruthb3e72192013-11-22 00:43:29 +0000102 PA.preserve<FunctionAnalysisManagerModuleProxy>();
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000103 return PA;
104 }
105};
106
Chandler Carruth30a07302016-03-11 10:33:22 +0000107struct TestFunctionPass : PassInfoMixin<TestFunctionPass> {
Chandler Carruthde9afd82013-11-23 00:38:42 +0000108 TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000109 int &AnalyzedFunctionCount,
Chandler Carruthde9afd82013-11-23 00:38:42 +0000110 bool OnlyUseCachedResults = false)
111 : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000112 AnalyzedFunctionCount(AnalyzedFunctionCount),
Chandler Carruthde9afd82013-11-23 00:38:42 +0000113 OnlyUseCachedResults(OnlyUseCachedResults) {}
Chandler Carruth90a835d2013-11-09 13:09:08 +0000114
Chandler Carruthb47f8012016-03-11 11:05:24 +0000115 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruth90a835d2013-11-09 13:09:08 +0000116 ++RunCount;
Chandler Carruth74015a72013-11-13 01:12:08 +0000117
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000118 const ModuleAnalysisManager &MAM =
Chandler Carruthb47f8012016-03-11 11:05:24 +0000119 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
Chandler Carrutheedf9fc2014-02-05 21:41:42 +0000120 if (TestModuleAnalysis::Result *TMA =
Chandler Carruthd174ce42015-01-05 02:47:05 +0000121 MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()))
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000122 AnalyzedFunctionCount += TMA->FunctionCount;
123
Chandler Carruthde9afd82013-11-23 00:38:42 +0000124 if (OnlyUseCachedResults) {
125 // Hack to force the use of the cached interface.
Chandler Carrutheedf9fc2014-02-05 21:41:42 +0000126 if (TestFunctionAnalysis::Result *AR =
Chandler Carruthb47f8012016-03-11 11:05:24 +0000127 AM.getCachedResult<TestFunctionAnalysis>(F))
Chandler Carruthde9afd82013-11-23 00:38:42 +0000128 AnalyzedInstrCount += AR->InstructionCount;
129 } else {
130 // Typical path just runs the analysis as needed.
Chandler Carruthb47f8012016-03-11 11:05:24 +0000131 TestFunctionAnalysis::Result &AR = AM.getResult<TestFunctionAnalysis>(F);
Chandler Carruthde9afd82013-11-23 00:38:42 +0000132 AnalyzedInstrCount += AR.InstructionCount;
133 }
Chandler Carruth74015a72013-11-13 01:12:08 +0000134
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000135 return PreservedAnalyses::all();
Chandler Carruth90a835d2013-11-09 13:09:08 +0000136 }
137
138 int &RunCount;
Chandler Carruth74015a72013-11-13 01:12:08 +0000139 int &AnalyzedInstrCount;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000140 int &AnalyzedFunctionCount;
Chandler Carruthde9afd82013-11-23 00:38:42 +0000141 bool OnlyUseCachedResults;
Chandler Carruth90a835d2013-11-09 13:09:08 +0000142};
143
Chandler Carruthbceeb222013-11-22 23:38:07 +0000144// A test function pass that invalidates all function analyses for a function
145// with a specific name.
Chandler Carruth30a07302016-03-11 10:33:22 +0000146struct TestInvalidationFunctionPass
147 : PassInfoMixin<TestInvalidationFunctionPass> {
Chandler Carruthbceeb222013-11-22 23:38:07 +0000148 TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
149
Chandler Carruth164a2aa62016-06-17 00:11:01 +0000150 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruthd174ce42015-01-05 02:47:05 +0000151 return F.getName() == Name ? PreservedAnalyses::none()
152 : PreservedAnalyses::all();
Chandler Carruthbceeb222013-11-22 23:38:07 +0000153 }
154
155 StringRef Name;
156};
157
Mehdi Amini03b42e42016-04-14 21:59:01 +0000158std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
Chandler Carruth90a835d2013-11-09 13:09:08 +0000159 SMDiagnostic Err;
Mehdi Amini03b42e42016-04-14 21:59:01 +0000160 return parseAssemblyString(IR, Err, Context);
Chandler Carruth90a835d2013-11-09 13:09:08 +0000161}
162
163class PassManagerTest : public ::testing::Test {
164protected:
Mehdi Amini03b42e42016-04-14 21:59:01 +0000165 LLVMContext Context;
Ahmed Charles56440fd2014-03-06 05:51:42 +0000166 std::unique_ptr<Module> M;
Chandler Carruth90a835d2013-11-09 13:09:08 +0000167
168public:
169 PassManagerTest()
Mehdi Amini03b42e42016-04-14 21:59:01 +0000170 : 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")) {}
Chandler Carruth90a835d2013-11-09 13:09:08 +0000182};
183
Chandler Carruth999b92d2014-03-13 10:42:18 +0000184TEST_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
Chandler Carruth90a835d2013-11-09 13:09:08 +0000217TEST_F(PassManagerTest, Basic) {
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000218 FunctionAnalysisManager FAM;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000219 int FunctionAnalysisRuns = 0;
Chandler Carruthedf59962016-02-18 09:45:17 +0000220 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
Chandler Carruth74015a72013-11-13 01:12:08 +0000221
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000222 ModuleAnalysisManager MAM;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000223 int ModuleAnalysisRuns = 0;
Chandler Carruthedf59962016-02-18 09:45:17 +0000224 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
225 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
226 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000227
Chandler Carruthb3e72192013-11-22 00:43:29 +0000228 ModulePassManager MPM;
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000229
230 // Count the runs over a Function.
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000231 int FunctionPassRunCount1 = 0;
232 int AnalyzedInstrCount1 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000233 int AnalyzedFunctionCount1 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000234 {
Chandler Carruth999b92d2014-03-13 10:42:18 +0000235 // Pointless scoped copy to test move assignment.
236 ModulePassManager NestedMPM;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000237 FunctionPassManager FPM;
Chandler Carruth999b92d2014-03-13 10:42:18 +0000238 {
239 // Pointless scope to test move assignment.
240 FunctionPassManager NestedFPM;
Chandler Carruth74a8a222016-06-17 07:15:29 +0000241 NestedFPM.addPass(TestFunctionPass(
242 FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1));
Chandler Carruth999b92d2014-03-13 10:42:18 +0000243 FPM = std::move(NestedFPM);
244 }
245 NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
246 MPM = std::move(NestedMPM);
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000247 }
Chandler Carruth90a835d2013-11-09 13:09:08 +0000248
249 // Count the runs over a module.
250 int ModulePassRunCount = 0;
251 MPM.addPass(TestModulePass(ModulePassRunCount));
252
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000253 // Count the runs over a Function in a separate manager.
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000254 int FunctionPassRunCount2 = 0;
255 int AnalyzedInstrCount2 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000256 int AnalyzedFunctionCount2 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000257 {
258 FunctionPassManager FPM;
259 FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
260 AnalyzedFunctionCount2));
261 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
262 }
Chandler Carruth90a835d2013-11-09 13:09:08 +0000263
Chandler Carruthbceeb222013-11-22 23:38:07 +0000264 // A third function pass manager but with only preserving intervening passes
265 // and with a function pass that invalidates exactly one analysis.
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000266 MPM.addPass(TestPreservingModulePass());
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000267 int FunctionPassRunCount3 = 0;
268 int AnalyzedInstrCount3 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000269 int AnalyzedFunctionCount3 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000270 {
271 FunctionPassManager FPM;
272 FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
273 AnalyzedFunctionCount3));
274 FPM.addPass(TestInvalidationFunctionPass("f"));
275 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
276 }
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000277
278 // A fourth function pass manager but with a minimal intervening passes.
279 MPM.addPass(TestMinPreservingModulePass());
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000280 int FunctionPassRunCount4 = 0;
281 int AnalyzedInstrCount4 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000282 int AnalyzedFunctionCount4 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000283 {
284 FunctionPassManager FPM;
285 FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
286 AnalyzedFunctionCount4));
287 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
288 }
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000289
Chandler Carruthde9afd82013-11-23 00:38:42 +0000290 // A fifth function pass manager but which uses only cached results.
Chandler Carruthde9afd82013-11-23 00:38:42 +0000291 int FunctionPassRunCount5 = 0;
292 int AnalyzedInstrCount5 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000293 int AnalyzedFunctionCount5 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000294 {
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 }
Chandler Carruthde9afd82013-11-23 00:38:42 +0000302
Chandler Carruthb47f8012016-03-11 11:05:24 +0000303 MPM.run(*M, MAM);
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000304
305 // Validate module pass counters.
Chandler Carruth90a835d2013-11-09 13:09:08 +0000306 EXPECT_EQ(1, ModulePassRunCount);
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000307
Chandler Carruthbceeb222013-11-22 23:38:07 +0000308 // Validate all function pass counter sets are the same.
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000309 EXPECT_EQ(3, FunctionPassRunCount1);
310 EXPECT_EQ(5, AnalyzedInstrCount1);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000311 EXPECT_EQ(0, AnalyzedFunctionCount1);
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000312 EXPECT_EQ(3, FunctionPassRunCount2);
313 EXPECT_EQ(5, AnalyzedInstrCount2);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000314 EXPECT_EQ(0, AnalyzedFunctionCount2);
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000315 EXPECT_EQ(3, FunctionPassRunCount3);
316 EXPECT_EQ(5, AnalyzedInstrCount3);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000317 EXPECT_EQ(0, AnalyzedFunctionCount3);
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000318 EXPECT_EQ(3, FunctionPassRunCount4);
319 EXPECT_EQ(5, AnalyzedInstrCount4);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000320 EXPECT_EQ(0, AnalyzedFunctionCount4);
Chandler Carruthde9afd82013-11-23 00:38:42 +0000321 EXPECT_EQ(3, FunctionPassRunCount5);
322 EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000323 EXPECT_EQ(0, AnalyzedFunctionCount5);
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000324
Chandler Carruthbceeb222013-11-22 23:38:07 +0000325 // 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
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000330 EXPECT_EQ(7, FunctionAnalysisRuns);
331
332 EXPECT_EQ(1, ModuleAnalysisRuns);
Chandler Carruth90a835d2013-11-09 13:09:08 +0000333}
Chandler Carruth9b35e6d2016-08-19 18:36:06 +0000334
335// A customized pass manager that passes extra arguments through the
336// infrastructure.
337typedef AnalysisManager<Function, int> CustomizedAnalysisManager;
338typedef PassManager<Function, CustomizedAnalysisManager, int, int &>
339 CustomizedPassManager;
340
341class CustomizedAnalysis : public AnalysisInfoMixin<CustomizedAnalysis> {
342public:
343 struct Result {
344 Result(int I) : I(I) {}
345 int I;
346 };
347
348 Result run(Function &F, CustomizedAnalysisManager &AM, int I) {
349 return Result(I);
350 }
351
352private:
353 friend AnalysisInfoMixin<CustomizedAnalysis>;
354 static char PassID;
355};
356
357char CustomizedAnalysis::PassID;
358
359struct CustomizedPass : PassInfoMixin<CustomizedPass> {
360 std::function<void(CustomizedAnalysis::Result &, int &)> Callback;
361
362 template <typename CallbackT>
363 CustomizedPass(CallbackT Callback) : Callback(Callback) {}
364
365 PreservedAnalyses run(Function &F, CustomizedAnalysisManager &AM, int I,
366 int &O) {
367 Callback(AM.getResult<CustomizedAnalysis>(F, I), O);
368 return PreservedAnalyses::none();
369 }
370};
371
372TEST_F(PassManagerTest, CustomizedPassManagerArgs) {
373 CustomizedAnalysisManager AM;
374 AM.registerPass([&] { return CustomizedAnalysis(); });
375
376 CustomizedPassManager PM;
377
378 // Add an instance of the customized pass that just accumulates the input
379 // after it is round-tripped through the analysis.
380 int Result = 0;
381 PM.addPass(
382 CustomizedPass([](CustomizedAnalysis::Result &R, int &O) { O += R.I; }));
383
384 // Run this over every function with the input of 42.
385 for (Function &F : *M)
386 PM.run(F, AM, 42, Result);
387
388 // And ensure that we accumulated the correct result.
389 EXPECT_EQ(42 * (int)M->size(), Result);
390}
Chandler Carruth90a835d2013-11-09 13:09:08 +0000391}