blob: d7515ba6b7d938717d7048a67fd243c19a80f0cb [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 Carruthdab4eae2016-11-23 17:53:26 +000044 static AnalysisKey Key;
Chandler Carruthb4faf132016-03-11 10:22:49 +000045
Chandler Carruth851a2aa2013-11-21 02:11:31 +000046 int &Runs;
Chandler Carruth74015a72013-11-13 01:12:08 +000047};
48
Chandler Carruthdab4eae2016-11-23 17:53:26 +000049AnalysisKey TestFunctionAnalysis::Key;
Chandler Carruthb4faf132016-03-11 10:22:49 +000050
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 Carruthdab4eae2016-11-23 17:53:26 +000070 static AnalysisKey Key;
Chandler Carruthb4faf132016-03-11 10:22:49 +000071
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000072 int &Runs;
73};
74
Chandler Carruthdab4eae2016-11-23 17:53:26 +000075AnalysisKey TestModuleAnalysis::Key;
Chandler Carruthb4faf132016-03-11 10:22:49 +000076
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 TestFunctionPass : PassInfoMixin<TestFunctionPass> {
Chandler Carruthde9afd82013-11-23 00:38:42 +000095 TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000096 int &AnalyzedFunctionCount,
Chandler Carruthde9afd82013-11-23 00:38:42 +000097 bool OnlyUseCachedResults = false)
98 : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +000099 AnalyzedFunctionCount(AnalyzedFunctionCount),
Chandler Carruthde9afd82013-11-23 00:38:42 +0000100 OnlyUseCachedResults(OnlyUseCachedResults) {}
Chandler Carruth90a835d2013-11-09 13:09:08 +0000101
Chandler Carruthb47f8012016-03-11 11:05:24 +0000102 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruth90a835d2013-11-09 13:09:08 +0000103 ++RunCount;
Chandler Carruth74015a72013-11-13 01:12:08 +0000104
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000105 const ModuleAnalysisManager &MAM =
Chandler Carruthb47f8012016-03-11 11:05:24 +0000106 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
Chandler Carrutheedf9fc2014-02-05 21:41:42 +0000107 if (TestModuleAnalysis::Result *TMA =
Chandler Carruthd174ce42015-01-05 02:47:05 +0000108 MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()))
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000109 AnalyzedFunctionCount += TMA->FunctionCount;
110
Chandler Carruthde9afd82013-11-23 00:38:42 +0000111 if (OnlyUseCachedResults) {
112 // Hack to force the use of the cached interface.
Chandler Carrutheedf9fc2014-02-05 21:41:42 +0000113 if (TestFunctionAnalysis::Result *AR =
Chandler Carruthb47f8012016-03-11 11:05:24 +0000114 AM.getCachedResult<TestFunctionAnalysis>(F))
Chandler Carruthde9afd82013-11-23 00:38:42 +0000115 AnalyzedInstrCount += AR->InstructionCount;
116 } else {
117 // Typical path just runs the analysis as needed.
Chandler Carruthb47f8012016-03-11 11:05:24 +0000118 TestFunctionAnalysis::Result &AR = AM.getResult<TestFunctionAnalysis>(F);
Chandler Carruthde9afd82013-11-23 00:38:42 +0000119 AnalyzedInstrCount += AR.InstructionCount;
120 }
Chandler Carruth74015a72013-11-13 01:12:08 +0000121
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000122 return PreservedAnalyses::all();
Chandler Carruth90a835d2013-11-09 13:09:08 +0000123 }
124
125 int &RunCount;
Chandler Carruth74015a72013-11-13 01:12:08 +0000126 int &AnalyzedInstrCount;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000127 int &AnalyzedFunctionCount;
Chandler Carruthde9afd82013-11-23 00:38:42 +0000128 bool OnlyUseCachedResults;
Chandler Carruth90a835d2013-11-09 13:09:08 +0000129};
130
Chandler Carruthbceeb222013-11-22 23:38:07 +0000131// A test function pass that invalidates all function analyses for a function
132// with a specific name.
Chandler Carruth30a07302016-03-11 10:33:22 +0000133struct TestInvalidationFunctionPass
134 : PassInfoMixin<TestInvalidationFunctionPass> {
Chandler Carruthbceeb222013-11-22 23:38:07 +0000135 TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
136
Chandler Carruth164a2aa62016-06-17 00:11:01 +0000137 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruthd174ce42015-01-05 02:47:05 +0000138 return F.getName() == Name ? PreservedAnalyses::none()
139 : PreservedAnalyses::all();
Chandler Carruthbceeb222013-11-22 23:38:07 +0000140 }
141
142 StringRef Name;
143};
144
Mehdi Amini03b42e42016-04-14 21:59:01 +0000145std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
Chandler Carruth90a835d2013-11-09 13:09:08 +0000146 SMDiagnostic Err;
Mehdi Amini03b42e42016-04-14 21:59:01 +0000147 return parseAssemblyString(IR, Err, Context);
Chandler Carruth90a835d2013-11-09 13:09:08 +0000148}
149
150class PassManagerTest : public ::testing::Test {
151protected:
Mehdi Amini03b42e42016-04-14 21:59:01 +0000152 LLVMContext Context;
Ahmed Charles56440fd2014-03-06 05:51:42 +0000153 std::unique_ptr<Module> M;
Chandler Carruth90a835d2013-11-09 13:09:08 +0000154
155public:
156 PassManagerTest()
Mehdi Amini03b42e42016-04-14 21:59:01 +0000157 : M(parseIR(Context, "define void @f() {\n"
158 "entry:\n"
159 " call void @g()\n"
160 " call void @h()\n"
161 " ret void\n"
162 "}\n"
163 "define void @g() {\n"
164 " ret void\n"
165 "}\n"
166 "define void @h() {\n"
167 " ret void\n"
168 "}\n")) {}
Chandler Carruth90a835d2013-11-09 13:09:08 +0000169};
170
Chandler Carruth999b92d2014-03-13 10:42:18 +0000171TEST_F(PassManagerTest, BasicPreservedAnalyses) {
172 PreservedAnalyses PA1 = PreservedAnalyses();
173 EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>());
174 EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>());
175 PreservedAnalyses PA2 = PreservedAnalyses::none();
176 EXPECT_FALSE(PA2.preserved<TestFunctionAnalysis>());
177 EXPECT_FALSE(PA2.preserved<TestModuleAnalysis>());
178 PreservedAnalyses PA3 = PreservedAnalyses::all();
179 EXPECT_TRUE(PA3.preserved<TestFunctionAnalysis>());
180 EXPECT_TRUE(PA3.preserved<TestModuleAnalysis>());
181 PreservedAnalyses PA4 = PA1;
182 EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>());
183 EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
184 PA4 = PA3;
185 EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>());
186 EXPECT_TRUE(PA4.preserved<TestModuleAnalysis>());
187 PA4 = std::move(PA2);
188 EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>());
189 EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
190 PA4.preserve<TestFunctionAnalysis>();
191 EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>());
192 EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
193 PA1.preserve<TestModuleAnalysis>();
194 EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>());
195 EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>());
196 PA1.preserve<TestFunctionAnalysis>();
197 EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>());
198 EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>());
199 PA1.intersect(PA4);
200 EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>());
201 EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>());
202}
203
Chandler Carruth90a835d2013-11-09 13:09:08 +0000204TEST_F(PassManagerTest, Basic) {
Chandler Carruth6b981642016-12-10 06:34:44 +0000205 FunctionAnalysisManager FAM(/*DebugLogging*/ true);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000206 int FunctionAnalysisRuns = 0;
Chandler Carruthedf59962016-02-18 09:45:17 +0000207 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
Chandler Carruth74015a72013-11-13 01:12:08 +0000208
Chandler Carruth6b981642016-12-10 06:34:44 +0000209 ModuleAnalysisManager MAM(/*DebugLogging*/ true);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000210 int ModuleAnalysisRuns = 0;
Chandler Carruthedf59962016-02-18 09:45:17 +0000211 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
212 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
213 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000214
Chandler Carruthb3e72192013-11-22 00:43:29 +0000215 ModulePassManager MPM;
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000216
217 // Count the runs over a Function.
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000218 int FunctionPassRunCount1 = 0;
219 int AnalyzedInstrCount1 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000220 int AnalyzedFunctionCount1 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000221 {
Chandler Carruth999b92d2014-03-13 10:42:18 +0000222 // Pointless scoped copy to test move assignment.
Chandler Carruth6b981642016-12-10 06:34:44 +0000223 ModulePassManager NestedMPM(/*DebugLogging*/ true);
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000224 FunctionPassManager FPM;
Chandler Carruth999b92d2014-03-13 10:42:18 +0000225 {
226 // Pointless scope to test move assignment.
Chandler Carruth6b981642016-12-10 06:34:44 +0000227 FunctionPassManager NestedFPM(/*DebugLogging*/ true);
Chandler Carruth74a8a222016-06-17 07:15:29 +0000228 NestedFPM.addPass(TestFunctionPass(
229 FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1));
Chandler Carruth999b92d2014-03-13 10:42:18 +0000230 FPM = std::move(NestedFPM);
231 }
232 NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
233 MPM = std::move(NestedMPM);
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000234 }
Chandler Carruth90a835d2013-11-09 13:09:08 +0000235
236 // Count the runs over a module.
237 int ModulePassRunCount = 0;
238 MPM.addPass(TestModulePass(ModulePassRunCount));
239
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000240 // Count the runs over a Function in a separate manager.
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000241 int FunctionPassRunCount2 = 0;
242 int AnalyzedInstrCount2 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000243 int AnalyzedFunctionCount2 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000244 {
Chandler Carruth6b981642016-12-10 06:34:44 +0000245 FunctionPassManager FPM(/*DebugLogging*/ true);
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000246 FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
247 AnalyzedFunctionCount2));
248 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
249 }
Chandler Carruth90a835d2013-11-09 13:09:08 +0000250
Chandler Carruthbceeb222013-11-22 23:38:07 +0000251 // A third function pass manager but with only preserving intervening passes
252 // and with a function pass that invalidates exactly one analysis.
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000253 MPM.addPass(TestPreservingModulePass());
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000254 int FunctionPassRunCount3 = 0;
255 int AnalyzedInstrCount3 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000256 int AnalyzedFunctionCount3 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000257 {
Chandler Carruth6b981642016-12-10 06:34:44 +0000258 FunctionPassManager FPM(/*DebugLogging*/ true);
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000259 FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
260 AnalyzedFunctionCount3));
261 FPM.addPass(TestInvalidationFunctionPass("f"));
262 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
263 }
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000264
Chandler Carruth6b981642016-12-10 06:34:44 +0000265 // A fourth function pass manager but with only preserving intervening
266 // passes but triggering the module analysis.
267 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000268 int FunctionPassRunCount4 = 0;
269 int AnalyzedInstrCount4 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000270 int AnalyzedFunctionCount4 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000271 {
272 FunctionPassManager FPM;
273 FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
274 AnalyzedFunctionCount4));
275 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
276 }
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000277
Chandler Carruth6b981642016-12-10 06:34:44 +0000278 // A fifth function pass manager which invalidates one function first but
279 // uses only cached results.
Chandler Carruthde9afd82013-11-23 00:38:42 +0000280 int FunctionPassRunCount5 = 0;
281 int AnalyzedInstrCount5 = 0;
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000282 int AnalyzedFunctionCount5 = 0;
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000283 {
Chandler Carruth6b981642016-12-10 06:34:44 +0000284 FunctionPassManager FPM(/*DebugLogging*/ true);
Chandler Carruthc3f3da32014-03-09 11:49:53 +0000285 FPM.addPass(TestInvalidationFunctionPass("f"));
286 FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
287 AnalyzedFunctionCount5,
288 /*OnlyUseCachedResults=*/true));
289 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
290 }
Chandler Carruthde9afd82013-11-23 00:38:42 +0000291
Chandler Carruthb47f8012016-03-11 11:05:24 +0000292 MPM.run(*M, MAM);
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000293
294 // Validate module pass counters.
Chandler Carruth90a835d2013-11-09 13:09:08 +0000295 EXPECT_EQ(1, ModulePassRunCount);
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000296
Chandler Carruthbceeb222013-11-22 23:38:07 +0000297 // Validate all function pass counter sets are the same.
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000298 EXPECT_EQ(3, FunctionPassRunCount1);
299 EXPECT_EQ(5, AnalyzedInstrCount1);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000300 EXPECT_EQ(0, AnalyzedFunctionCount1);
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000301 EXPECT_EQ(3, FunctionPassRunCount2);
302 EXPECT_EQ(5, AnalyzedInstrCount2);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000303 EXPECT_EQ(0, AnalyzedFunctionCount2);
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000304 EXPECT_EQ(3, FunctionPassRunCount3);
305 EXPECT_EQ(5, AnalyzedInstrCount3);
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000306 EXPECT_EQ(0, AnalyzedFunctionCount3);
Chandler Carruth2846e9e2013-11-21 10:53:05 +0000307 EXPECT_EQ(3, FunctionPassRunCount4);
308 EXPECT_EQ(5, AnalyzedInstrCount4);
Chandler Carruth6b981642016-12-10 06:34:44 +0000309 EXPECT_EQ(9, AnalyzedFunctionCount4);
Chandler Carruthde9afd82013-11-23 00:38:42 +0000310 EXPECT_EQ(3, FunctionPassRunCount5);
311 EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
Chandler Carruth6b981642016-12-10 06:34:44 +0000312 EXPECT_EQ(9, AnalyzedFunctionCount5);
Chandler Carruth851a2aa2013-11-21 02:11:31 +0000313
Chandler Carruthbceeb222013-11-22 23:38:07 +0000314 // Validate the analysis counters:
315 // first run over 3 functions, then module pass invalidates
316 // second run over 3 functions, nothing invalidates
317 // third run over 0 functions, but 1 function invalidated
318 // fourth run over 1 function
Chandler Carruth6b981642016-12-10 06:34:44 +0000319 // fifth run invalidates 1 function first, but runs over 0 functions
Chandler Carruthc1ff9ed2013-11-23 01:25:07 +0000320 EXPECT_EQ(7, FunctionAnalysisRuns);
321
322 EXPECT_EQ(1, ModuleAnalysisRuns);
Chandler Carruth90a835d2013-11-09 13:09:08 +0000323}
Chandler Carruth9b35e6d2016-08-19 18:36:06 +0000324
325// A customized pass manager that passes extra arguments through the
326// infrastructure.
327typedef AnalysisManager<Function, int> CustomizedAnalysisManager;
328typedef PassManager<Function, CustomizedAnalysisManager, int, int &>
329 CustomizedPassManager;
330
331class CustomizedAnalysis : public AnalysisInfoMixin<CustomizedAnalysis> {
332public:
333 struct Result {
334 Result(int I) : I(I) {}
335 int I;
336 };
337
338 Result run(Function &F, CustomizedAnalysisManager &AM, int I) {
339 return Result(I);
340 }
341
342private:
343 friend AnalysisInfoMixin<CustomizedAnalysis>;
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000344 static AnalysisKey Key;
Chandler Carruth9b35e6d2016-08-19 18:36:06 +0000345};
346
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000347AnalysisKey CustomizedAnalysis::Key;
Chandler Carruth9b35e6d2016-08-19 18:36:06 +0000348
349struct CustomizedPass : PassInfoMixin<CustomizedPass> {
350 std::function<void(CustomizedAnalysis::Result &, int &)> Callback;
351
352 template <typename CallbackT>
353 CustomizedPass(CallbackT Callback) : Callback(Callback) {}
354
355 PreservedAnalyses run(Function &F, CustomizedAnalysisManager &AM, int I,
356 int &O) {
357 Callback(AM.getResult<CustomizedAnalysis>(F, I), O);
358 return PreservedAnalyses::none();
359 }
360};
361
362TEST_F(PassManagerTest, CustomizedPassManagerArgs) {
363 CustomizedAnalysisManager AM;
364 AM.registerPass([&] { return CustomizedAnalysis(); });
365
366 CustomizedPassManager PM;
367
368 // Add an instance of the customized pass that just accumulates the input
369 // after it is round-tripped through the analysis.
370 int Result = 0;
371 PM.addPass(
372 CustomizedPass([](CustomizedAnalysis::Result &R, int &O) { O += R.I; }));
373
374 // Run this over every function with the input of 42.
375 for (Function &F : *M)
376 PM.run(F, AM, 42, Result);
377
378 // And ensure that we accumulated the correct result.
379 EXPECT_EQ(42 * (int)M->size(), Result);
380}
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000381
382/// A test analysis pass which caches in its result another analysis pass and
383/// uses it to serve queries. This requires the result to invalidate itself
384/// when its dependency is invalidated.
385struct TestIndirectFunctionAnalysis
386 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
387 struct Result {
388 Result(TestFunctionAnalysis::Result &Dep) : Dep(Dep) {}
389 TestFunctionAnalysis::Result &Dep;
390
391 bool invalidate(Function &F, const PreservedAnalyses &PA,
392 FunctionAnalysisManager::Invalidator &Inv) {
393 return !PA.preserved<TestIndirectFunctionAnalysis>() ||
394 Inv.invalidate<TestFunctionAnalysis>(F, PA);
395 }
396 };
397
398 TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
399
400 /// Run the analysis pass over the function and return a result.
401 Result run(Function &F, FunctionAnalysisManager &AM) {
402 ++Runs;
403 return Result(AM.getResult<TestFunctionAnalysis>(F));
404 }
405
406private:
407 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
408 static AnalysisKey Key;
409
410 int &Runs;
411};
412
413AnalysisKey TestIndirectFunctionAnalysis::Key;
414
415struct LambdaPass : public PassInfoMixin<LambdaPass> {
416 using FuncT = std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)>;
417
418 LambdaPass(FuncT Func) : Func(std::move(Func)) {}
419
420 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
421 return Func(F, AM);
422 }
423
424 FuncT Func;
425};
426
427TEST_F(PassManagerTest, IndirectAnalysisInvalidation) {
428 FunctionAnalysisManager FAM(/*DebugLogging*/ true);
429 int AnalysisRuns = 0, IndirectAnalysisRuns = 0;
430 FAM.registerPass([&] { return TestFunctionAnalysis(AnalysisRuns); });
431 FAM.registerPass(
432 [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns); });
433
434 ModuleAnalysisManager MAM(/*DebugLogging*/ true);
435 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
436 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
437
438 int InstrCount = 0;
439 ModulePassManager MPM(/*DebugLogging*/ true);
440 FunctionPassManager FPM(/*DebugLogging*/ true);
441 // First just use the analysis to get the instruction count, and preserve
442 // everything.
443 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
444 InstrCount +=
445 AM.getResult<TestIndirectFunctionAnalysis>(F).Dep.InstructionCount;
446 return PreservedAnalyses::all();
447 }));
448 // Next, invalidate
449 // - both analyses for "f",
450 // - just the underlying (indirect) analysis for "g", and
451 // - just the direct analysis for "h".
452 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
453 InstrCount +=
454 AM.getResult<TestIndirectFunctionAnalysis>(F).Dep.InstructionCount;
455 auto PA = PreservedAnalyses::none();
456 if (F.getName() == "g")
457 PA.preserve<TestFunctionAnalysis>();
458 else if (F.getName() == "h")
459 PA.preserve<TestIndirectFunctionAnalysis>();
460 return PA;
461 }));
462 // Finally, use the analysis again on each function, forcing re-computation
463 // for all of them.
464 FPM.addPass(LambdaPass([&](Function &F, FunctionAnalysisManager &AM) {
465 InstrCount +=
466 AM.getResult<TestIndirectFunctionAnalysis>(F).Dep.InstructionCount;
467 return PreservedAnalyses::all();
468 }));
469 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
470 MPM.run(*M, MAM);
471
472 // There are generally two possible runs for each of the three functions. But
473 // for one function, we only invalidate the indirect analysis so the base one
474 // only gets run five times.
475 EXPECT_EQ(5, AnalysisRuns);
476 // The indirect analysis is invalidated for each function (either directly or
477 // indirectly) and run twice for each.
478 EXPECT_EQ(6, IndirectAnalysisRuns);
479
480 // There are five instructions in the module and we add the count three
481 // times.
482 EXPECT_EQ(5 * 3, InstrCount);
483}
Chandler Carruth90a835d2013-11-09 13:09:08 +0000484}