blob: ab5d1862c23e7c7e0e91fde71527bb32cd0d6ffe [file] [log] [blame]
Chandler Carruth74319922016-02-23 10:02:02 +00001//===- CGSCCPassManagerTest.cpp -------------------------------------------===//
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/Analysis/CGSCCPassManager.h"
11#include "llvm/Analysis/LazyCallGraph.h"
12#include "llvm/AsmParser/Parser.h"
13#include "llvm/IR/Function.h"
14#include "llvm/IR/InstIterator.h"
15#include "llvm/IR/LLVMContext.h"
16#include "llvm/IR/Module.h"
17#include "llvm/IR/PassManager.h"
18#include "llvm/Support/SourceMgr.h"
19#include "gtest/gtest.h"
20
21using namespace llvm;
22
23namespace {
24
Chandler Carruthdab4eae2016-11-23 17:53:26 +000025class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
Chandler Carruth74319922016-02-23 10:02:02 +000026public:
27 struct Result {
28 Result(int Count) : FunctionCount(Count) {}
29 int FunctionCount;
30 };
31
Chandler Carruth74319922016-02-23 10:02:02 +000032 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
33
Chandler Carruthb47f8012016-03-11 11:05:24 +000034 Result run(Module &M, ModuleAnalysisManager &AM) {
Chandler Carruth74319922016-02-23 10:02:02 +000035 ++Runs;
36 return Result(M.size());
37 }
38
39private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +000040 friend AnalysisInfoMixin<TestModuleAnalysis>;
41 static AnalysisKey Key;
Chandler Carruth74319922016-02-23 10:02:02 +000042
43 int &Runs;
44};
45
Chandler Carruthdab4eae2016-11-23 17:53:26 +000046AnalysisKey TestModuleAnalysis::Key;
Chandler Carruth74319922016-02-23 10:02:02 +000047
Chandler Carruthdab4eae2016-11-23 17:53:26 +000048class TestSCCAnalysis : public AnalysisInfoMixin<TestSCCAnalysis> {
Chandler Carruth74319922016-02-23 10:02:02 +000049public:
50 struct Result {
51 Result(int Count) : FunctionCount(Count) {}
52 int FunctionCount;
53 };
54
Chandler Carruth74319922016-02-23 10:02:02 +000055 TestSCCAnalysis(int &Runs) : Runs(Runs) {}
56
Chandler Carruth88823462016-08-24 09:37:14 +000057 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &) {
Chandler Carruth74319922016-02-23 10:02:02 +000058 ++Runs;
59 return Result(C.size());
60 }
61
62private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +000063 friend AnalysisInfoMixin<TestSCCAnalysis>;
64 static AnalysisKey Key;
Chandler Carruth74319922016-02-23 10:02:02 +000065
66 int &Runs;
67};
68
Chandler Carruthdab4eae2016-11-23 17:53:26 +000069AnalysisKey TestSCCAnalysis::Key;
Chandler Carruth74319922016-02-23 10:02:02 +000070
Chandler Carruthdab4eae2016-11-23 17:53:26 +000071class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
Chandler Carruth74319922016-02-23 10:02:02 +000072public:
73 struct Result {
74 Result(int Count) : InstructionCount(Count) {}
75 int InstructionCount;
76 };
77
Chandler Carruth74319922016-02-23 10:02:02 +000078 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
79
Chandler Carruthb47f8012016-03-11 11:05:24 +000080 Result run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruth74319922016-02-23 10:02:02 +000081 ++Runs;
82 int Count = 0;
83 for (Instruction &I : instructions(F)) {
84 (void)I;
85 ++Count;
86 }
87 return Result(Count);
88 }
89
90private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +000091 friend AnalysisInfoMixin<TestFunctionAnalysis>;
92 static AnalysisKey Key;
Chandler Carruth74319922016-02-23 10:02:02 +000093
94 int &Runs;
95};
96
Chandler Carruthdab4eae2016-11-23 17:53:26 +000097AnalysisKey TestFunctionAnalysis::Key;
Chandler Carruth74319922016-02-23 10:02:02 +000098
Chandler Carruthdab4eae2016-11-23 17:53:26 +000099class TestImmutableFunctionAnalysis
100 : public AnalysisInfoMixin<TestImmutableFunctionAnalysis> {
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000101public:
102 struct Result {
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000103 bool invalidate(Function &, const PreservedAnalyses &,
104 FunctionAnalysisManager::Invalidator &) {
105 return false;
106 }
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000107 };
108
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000109 TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {}
110
Chandler Carruthb47f8012016-03-11 11:05:24 +0000111 Result run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000112 ++Runs;
113 return Result();
114 }
115
116private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000117 friend AnalysisInfoMixin<TestImmutableFunctionAnalysis>;
118 static AnalysisKey Key;
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000119
120 int &Runs;
121};
122
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000123AnalysisKey TestImmutableFunctionAnalysis::Key;
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000124
Chandler Carruth6b981642016-12-10 06:34:44 +0000125struct LambdaModulePass : public PassInfoMixin<LambdaModulePass> {
126 template <typename T>
127 LambdaModulePass(T &&Arg) : Func(std::forward<T>(Arg)) {}
128
129 PreservedAnalyses run(Module &F, ModuleAnalysisManager &AM) {
130 return Func(F, AM);
131 }
132
133 std::function<PreservedAnalyses(Module &, ModuleAnalysisManager &)> Func;
134};
135
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000136struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> {
137 template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
Chandler Carruth74319922016-02-23 10:02:02 +0000138
Chandler Carruth88823462016-08-24 09:37:14 +0000139 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
140 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000141 return Func(C, AM, CG, UR);
Chandler Carruth74319922016-02-23 10:02:02 +0000142 }
143
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000144 std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
145 LazyCallGraph &, CGSCCUpdateResult &)>
146 Func;
Chandler Carruth74319922016-02-23 10:02:02 +0000147};
148
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000149struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> {
Chandler Carruth6b981642016-12-10 06:34:44 +0000150 template <typename T>
151 LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
Chandler Carruth74319922016-02-23 10:02:02 +0000152
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000153 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
154 return Func(F, AM);
Chandler Carruth74319922016-02-23 10:02:02 +0000155 }
156
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000157 std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func;
Chandler Carruth74319922016-02-23 10:02:02 +0000158};
159
Chandler Carruth6c138ce2016-06-28 00:38:42 +0000160std::unique_ptr<Module> parseIR(const char *IR) {
161 // We just use a static context here. This is never called from multiple
162 // threads so it is harmless no matter how it is implemented. We just need
163 // the context to outlive the module which it does.
164 static LLVMContext C;
Chandler Carruth74319922016-02-23 10:02:02 +0000165 SMDiagnostic Err;
166 return parseAssemblyString(IR, Err, C);
167}
168
Chandler Carruth4f837422016-09-02 01:14:05 +0000169class CGSCCPassManagerTest : public ::testing::Test {
170protected:
171 LLVMContext Context;
Chandler Carruthdc288a82016-09-26 06:29:21 +0000172 FunctionAnalysisManager FAM;
173 CGSCCAnalysisManager CGAM;
174 ModuleAnalysisManager MAM;
175
Chandler Carruth4f837422016-09-02 01:14:05 +0000176 std::unique_ptr<Module> M;
177
178public:
179 CGSCCPassManagerTest()
Chandler Carruthdc288a82016-09-26 06:29:21 +0000180 : FAM(/*DebugLogging*/ true), CGAM(/*DebugLogging*/ true),
Chandler Carruth4cf2c892016-11-28 03:40:33 +0000181 MAM(/*DebugLogging*/ true),
182 M(parseIR(
183 // Define a module with the following call graph, where calls go
184 // out the bottom of nodes and enter the top:
185 //
186 // f
187 // |\ _
188 // | \ / |
189 // g h1 |
190 // | | |
191 // | h2 |
192 // | | |
193 // | h3 |
194 // | / \_/
195 // |/
196 // x
197 //
198 "define void @f() {\n"
199 "entry:\n"
200 " call void @g()\n"
201 " call void @h1()\n"
202 " ret void\n"
203 "}\n"
204 "define void @g() {\n"
205 "entry:\n"
206 " call void @g()\n"
207 " call void @x()\n"
208 " ret void\n"
209 "}\n"
210 "define void @h1() {\n"
211 "entry:\n"
212 " call void @h2()\n"
213 " ret void\n"
214 "}\n"
215 "define void @h2() {\n"
216 "entry:\n"
217 " call void @h3()\n"
218 " call void @x()\n"
219 " ret void\n"
220 "}\n"
221 "define void @h3() {\n"
222 "entry:\n"
223 " call void @h1()\n"
224 " ret void\n"
225 "}\n"
226 "define void @x() {\n"
227 "entry:\n"
228 " ret void\n"
229 "}\n")) {
Chandler Carruthdc288a82016-09-26 06:29:21 +0000230 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
231 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
232 MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
Chandler Carruth6b981642016-12-10 06:34:44 +0000233 CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); });
Chandler Carruthdc288a82016-09-26 06:29:21 +0000234 CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
235 FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
236 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
237 }
Chandler Carruth4f837422016-09-02 01:14:05 +0000238};
239
240TEST_F(CGSCCPassManagerTest, Basic) {
Chandler Carruth74319922016-02-23 10:02:02 +0000241 int FunctionAnalysisRuns = 0;
242 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000243 int ImmutableFunctionAnalysisRuns = 0;
244 FAM.registerPass([&] {
245 return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns);
246 });
Chandler Carruth74319922016-02-23 10:02:02 +0000247
Chandler Carruth74319922016-02-23 10:02:02 +0000248 int SCCAnalysisRuns = 0;
249 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
250
Chandler Carruth74319922016-02-23 10:02:02 +0000251 int ModuleAnalysisRuns = 0;
Chandler Carruth74319922016-02-23 10:02:02 +0000252 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
253
Chandler Carruth74319922016-02-23 10:02:02 +0000254 ModulePassManager MPM(/*DebugLogging*/ true);
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000255 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
Chandler Carruth74319922016-02-23 10:02:02 +0000256
257 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
Chandler Carruth6b981642016-12-10 06:34:44 +0000258 FunctionPassManager FPM1(/*DebugLogging*/ true);
259 int FunctionPassRunCount1 = 0;
260 FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
261 ++FunctionPassRunCount1;
262 return PreservedAnalyses::none();
263 }));
264 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
265
Chandler Carruth74319922016-02-23 10:02:02 +0000266 int SCCPassRunCount1 = 0;
267 int AnalyzedInstrCount1 = 0;
268 int AnalyzedSCCFunctionCount1 = 0;
269 int AnalyzedModuleFunctionCount1 = 0;
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000270 CGPM1.addPass(
271 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
272 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
273 ++SCCPassRunCount1;
274
275 const ModuleAnalysisManager &MAM =
276 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
277 FunctionAnalysisManager &FAM =
278 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
279 if (TestModuleAnalysis::Result *TMA =
280 MAM.getCachedResult<TestModuleAnalysis>(
281 *C.begin()->getFunction().getParent()))
282 AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
283
284 TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
285 AnalyzedSCCFunctionCount1 += AR.FunctionCount;
286 for (LazyCallGraph::Node &N : C) {
287 TestFunctionAnalysis::Result &FAR =
288 FAM.getResult<TestFunctionAnalysis>(N.getFunction());
289 AnalyzedInstrCount1 += FAR.InstructionCount;
290
291 // Just ensure we get the immutable results.
292 (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction());
293 }
294
295 return PreservedAnalyses::all();
296 }));
Chandler Carruth74319922016-02-23 10:02:02 +0000297
Chandler Carruth6b981642016-12-10 06:34:44 +0000298 FunctionPassManager FPM2(/*DebugLogging*/ true);
299 int FunctionPassRunCount2 = 0;
300 FPM2.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
301 ++FunctionPassRunCount2;
302 return PreservedAnalyses::none();
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000303 }));
Chandler Carruth6b981642016-12-10 06:34:44 +0000304 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
305
Chandler Carruth74319922016-02-23 10:02:02 +0000306 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
307
Chandler Carruth6b981642016-12-10 06:34:44 +0000308 FunctionPassManager FPM3(/*DebugLogging*/ true);
309 int FunctionPassRunCount3 = 0;
310 FPM3.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
311 ++FunctionPassRunCount3;
312 return PreservedAnalyses::none();
313 }));
314 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM3)));
315
Chandler Carruthb47f8012016-03-11 11:05:24 +0000316 MPM.run(*M, MAM);
Chandler Carruth74319922016-02-23 10:02:02 +0000317
Chandler Carruth6b981642016-12-10 06:34:44 +0000318 EXPECT_EQ(4, SCCPassRunCount1);
319 EXPECT_EQ(6, FunctionPassRunCount1);
320 EXPECT_EQ(6, FunctionPassRunCount2);
321 EXPECT_EQ(6, FunctionPassRunCount3);
322
Chandler Carruth74319922016-02-23 10:02:02 +0000323 EXPECT_EQ(1, ModuleAnalysisRuns);
324 EXPECT_EQ(4, SCCAnalysisRuns);
325 EXPECT_EQ(6, FunctionAnalysisRuns);
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000326 EXPECT_EQ(6, ImmutableFunctionAnalysisRuns);
Chandler Carruth74319922016-02-23 10:02:02 +0000327
Chandler Carruth74319922016-02-23 10:02:02 +0000328 EXPECT_EQ(14, AnalyzedInstrCount1);
329 EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
330 EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
331}
332
Chandler Carruthb52b5732016-09-26 04:01:55 +0000333// Test that an SCC pass which fails to preserve a module analysis does in fact
334// invalidate that module analysis.
335TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
Chandler Carruthb52b5732016-09-26 04:01:55 +0000336 int ModuleAnalysisRuns = 0;
337 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
338
339 ModulePassManager MPM(/*DebugLogging*/ true);
340 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
341
342 // The first CGSCC run we preserve everything and make sure that works and
343 // the module analysis is available in the second CGSCC run from the one
344 // required module pass above.
345 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
346 int CountFoundModuleAnalysis1 = 0;
347 CGPM1.addPass(
348 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
349 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
350 const auto &MAM =
351 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
352 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
353 *C.begin()->getFunction().getParent());
354
355 if (TMA)
356 ++CountFoundModuleAnalysis1;
357
358 return PreservedAnalyses::all();
359 }));
360 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
361
362 // The second CGSCC run checks that the module analysis got preserved the
363 // previous time and in one SCC fails to preserve it.
364 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
365 int CountFoundModuleAnalysis2 = 0;
366 CGPM2.addPass(
367 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
368 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
369 const auto &MAM =
370 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
371 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
372 *C.begin()->getFunction().getParent());
373
374 if (TMA)
375 ++CountFoundModuleAnalysis2;
376
377 // Only fail to preserve analyses on one SCC and make sure that gets
378 // propagated.
379 return C.getName() == "(g)" ? PreservedAnalyses::none()
380 : PreservedAnalyses::all();
381 }));
382 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
383
384 // The third CGSCC run should fail to find a cached module analysis as it
385 // should have been invalidated by the above CGSCC run.
386 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
387 int CountFoundModuleAnalysis3 = 0;
388 CGPM3.addPass(
389 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
390 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
391 const auto &MAM =
392 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
393 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
394 *C.begin()->getFunction().getParent());
395
396 if (TMA)
397 ++CountFoundModuleAnalysis3;
398
399 return PreservedAnalyses::none();
400 }));
401 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
402
403 MPM.run(*M, MAM);
404
405 EXPECT_EQ(1, ModuleAnalysisRuns);
406 EXPECT_EQ(4, CountFoundModuleAnalysis1);
407 EXPECT_EQ(4, CountFoundModuleAnalysis2);
408 EXPECT_EQ(0, CountFoundModuleAnalysis3);
409}
410
Chandler Carruthe35f84a2016-09-26 04:17:12 +0000411// Similar to the above, but test that this works for function passes embedded
412// *within* a CGSCC layer.
413TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) {
Chandler Carruthe35f84a2016-09-26 04:17:12 +0000414 int ModuleAnalysisRuns = 0;
415 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
416
417 ModulePassManager MPM(/*DebugLogging*/ true);
418 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
419
420 // The first run we preserve everything and make sure that works and the
421 // module analysis is available in the second run from the one required
422 // module pass above.
423 FunctionPassManager FPM1(/*DebugLogging*/ true);
424 // Start true and mark false if we ever failed to find a module analysis
425 // because we expect this to succeed for each SCC.
426 bool FoundModuleAnalysis1 = true;
427 FPM1.addPass(
428 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
429 const auto &MAM =
430 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
431 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
432
433 if (!TMA)
434 FoundModuleAnalysis1 = false;
435
436 return PreservedAnalyses::all();
437 }));
438 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
439 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
440 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
441
442 // The second run checks that the module analysis got preserved the previous
443 // time and in one function fails to preserve it.
444 FunctionPassManager FPM2(/*DebugLogging*/ true);
445 // Again, start true and mark false if we ever failed to find a module analysis
446 // because we expect this to succeed for each SCC.
447 bool FoundModuleAnalysis2 = true;
448 FPM2.addPass(
449 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
450 const auto &MAM =
451 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
452 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
453
454 if (!TMA)
455 FoundModuleAnalysis2 = false;
456
457 // Only fail to preserve analyses on one SCC and make sure that gets
458 // propagated.
459 return F.getName() == "h2" ? PreservedAnalyses::none()
460 : PreservedAnalyses::all();
461 }));
462 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
463 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
464 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
465
466 // The third run should fail to find a cached module analysis as it should
467 // have been invalidated by the above run.
468 FunctionPassManager FPM3(/*DebugLogging*/ true);
469 // Start false and mark true if we ever *succeeded* to find a module
470 // analysis, as we expect this to fail for every function.
471 bool FoundModuleAnalysis3 = false;
472 FPM3.addPass(
473 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
474 const auto &MAM =
475 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
476 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
477
478 if (TMA)
479 FoundModuleAnalysis3 = true;
480
481 return PreservedAnalyses::none();
482 }));
483 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
484 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3)));
485 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
486
487 MPM.run(*M, MAM);
488
489 EXPECT_EQ(1, ModuleAnalysisRuns);
490 EXPECT_TRUE(FoundModuleAnalysis1);
491 EXPECT_TRUE(FoundModuleAnalysis2);
492 EXPECT_FALSE(FoundModuleAnalysis3);
493}
494
Chandler Carruth6b981642016-12-10 06:34:44 +0000495// Test that a Module pass which fails to preserve an SCC analysis in fact
496// invalidates that analysis.
497TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysis) {
498 int SCCAnalysisRuns = 0;
499 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
500
501 ModulePassManager MPM(/*DebugLogging*/ true);
502
503 // First force the analysis to be run.
504 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
505 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
506 CGSCCAnalysisManager, LazyCallGraph &,
507 CGSCCUpdateResult &>());
508 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
509
510 // Now run a module pass that preserves the LazyCallGraph and the proxy but
511 // not the SCC analysis.
512 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
513 PreservedAnalyses PA;
514 PA.preserve<LazyCallGraphAnalysis>();
515 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
516 PA.preserve<FunctionAnalysisManagerModuleProxy>();
517 return PA;
518 }));
519
520 // And now a second CGSCC run which requires the SCC analysis again. This
521 // will trigger re-running it.
522 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
523 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
524 CGSCCAnalysisManager, LazyCallGraph &,
525 CGSCCUpdateResult &>());
526 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
527
528 MPM.run(*M, MAM);
529 // Two runs and four SCCs.
530 EXPECT_EQ(2 * 4, SCCAnalysisRuns);
531}
532
533// Check that marking the SCC analysis preserved is sufficient to avoid
534// invaliadtion. This should only run the analysis once for each SCC.
535TEST_F(CGSCCPassManagerTest, TestModulePassCanPreserveSCCAnalysis) {
536 int SCCAnalysisRuns = 0;
537 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
538
539 ModulePassManager MPM(/*DebugLogging*/ true);
540
541 // First force the analysis to be run.
542 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
543 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
544 CGSCCAnalysisManager, LazyCallGraph &,
545 CGSCCUpdateResult &>());
546 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
547
548 // Now run a module pass that preserves each of the necessary components
549 // (but not everything).
550 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
551 PreservedAnalyses PA;
552 PA.preserve<LazyCallGraphAnalysis>();
553 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
554 PA.preserve<FunctionAnalysisManagerModuleProxy>();
555 PA.preserve<TestSCCAnalysis>();
556 return PA;
557 }));
558
559 // And now a second CGSCC run which requires the SCC analysis again but find
560 // it in the cache.
561 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
562 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
563 CGSCCAnalysisManager, LazyCallGraph &,
564 CGSCCUpdateResult &>());
565 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
566
567 MPM.run(*M, MAM);
568 // Four SCCs
569 EXPECT_EQ(4, SCCAnalysisRuns);
570}
571
572// Check that even when the analysis is preserved, if the SCC information isn't
573// we still nuke things because the SCC keys could change.
574TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysisOnCGChange) {
575 int SCCAnalysisRuns = 0;
576 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
577
578 ModulePassManager MPM(/*DebugLogging*/ true);
579
580 // First force the analysis to be run.
581 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
582 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
583 CGSCCAnalysisManager, LazyCallGraph &,
584 CGSCCUpdateResult &>());
585 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
586
587 // Now run a module pass that preserves the analysis but not the call
588 // graph or proxy.
589 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
590 PreservedAnalyses PA;
591 PA.preserve<TestSCCAnalysis>();
592 return PA;
593 }));
594
595 // And now a second CGSCC run which requires the SCC analysis again.
596 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
597 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
598 CGSCCAnalysisManager, LazyCallGraph &,
599 CGSCCUpdateResult &>());
600 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
601
602 MPM.run(*M, MAM);
603 // Two runs and four SCCs.
604 EXPECT_EQ(2 * 4, SCCAnalysisRuns);
605}
606
607// Test that an SCC pass which fails to preserve a Function analysis in fact
608// invalidates that analysis.
609TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesFunctionAnalysis) {
610 int FunctionAnalysisRuns = 0;
611 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
612
613 // Create a very simple module with a single function and SCC to make testing
614 // these issues much easier.
615 std::unique_ptr<Module> M = parseIR("declare void @g()\n"
616 "declare void @h()\n"
617 "define void @f() {\n"
618 "entry:\n"
619 " call void @g()\n"
620 " call void @h()\n"
621 " ret void\n"
622 "}\n");
623
624 CGSCCPassManager CGPM(/*DebugLogging*/ true);
625
626 // First force the analysis to be run.
627 FunctionPassManager FPM1(/*DebugLogging*/ true);
628 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
629 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
630
631 // Now run a module pass that preserves the LazyCallGraph and proxy but not
632 // the SCC analysis.
633 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
634 LazyCallGraph &, CGSCCUpdateResult &) {
635 PreservedAnalyses PA;
636 PA.preserve<LazyCallGraphAnalysis>();
637 return PA;
638 }));
639
640 // And now a second CGSCC run which requires the SCC analysis again. This
641 // will trigger re-running it.
642 FunctionPassManager FPM2(/*DebugLogging*/ true);
643 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
644 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
645
646 ModulePassManager MPM(/*DebugLogging*/ true);
647 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
648 MPM.run(*M, MAM);
649 EXPECT_EQ(2, FunctionAnalysisRuns);
650}
651
652// Check that marking the SCC analysis preserved is sufficient. This should
653// only run the analysis once the SCC.
654TEST_F(CGSCCPassManagerTest, TestSCCPassCanPreserveFunctionAnalysis) {
655 int FunctionAnalysisRuns = 0;
656 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
657
658 // Create a very simple module with a single function and SCC to make testing
659 // these issues much easier.
660 std::unique_ptr<Module> M = parseIR("declare void @g()\n"
661 "declare void @h()\n"
662 "define void @f() {\n"
663 "entry:\n"
664 " call void @g()\n"
665 " call void @h()\n"
666 " ret void\n"
667 "}\n");
668
669 CGSCCPassManager CGPM(/*DebugLogging*/ true);
670
671 // First force the analysis to be run.
672 FunctionPassManager FPM1(/*DebugLogging*/ true);
673 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
674 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
675
676 // Now run a module pass that preserves each of the necessary components
677 // (but
678 // not everything).
679 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
680 LazyCallGraph &, CGSCCUpdateResult &) {
681 PreservedAnalyses PA;
682 PA.preserve<LazyCallGraphAnalysis>();
683 PA.preserve<TestFunctionAnalysis>();
684 return PA;
685 }));
686
687 // And now a second CGSCC run which requires the SCC analysis again but find
688 // it in the cache.
689 FunctionPassManager FPM2(/*DebugLogging*/ true);
690 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
691 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
692
693 ModulePassManager MPM(/*DebugLogging*/ true);
694 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
695 MPM.run(*M, MAM);
696 EXPECT_EQ(1, FunctionAnalysisRuns);
697}
698
699// Note that there is no test for invalidating the call graph or other
700// structure with an SCC pass because there is no mechanism to do that from
701// withinsuch a pass. Instead, such a pass has to directly update the call
702// graph structure.
703
704// Test that a madule pass invalidates function analyses when the CGSCC proxies
705// and pass manager.
706TEST_F(CGSCCPassManagerTest,
707 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC) {
708 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
709
710 int FunctionAnalysisRuns = 0;
711 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
712
713 ModulePassManager MPM(/*DebugLogging*/ true);
714
715 // First force the analysis to be run.
716 FunctionPassManager FPM1(/*DebugLogging*/ true);
717 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
718 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
719 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
720 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
721
722 // Now run a module pass that preserves the LazyCallGraph and proxy but not
723 // the Function analysis.
724 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
725 PreservedAnalyses PA;
726 PA.preserve<LazyCallGraphAnalysis>();
727 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
728 return PA;
729 }));
730
731 // And now a second CGSCC run which requires the SCC analysis again. This
732 // will trigger re-running it.
733 FunctionPassManager FPM2(/*DebugLogging*/ true);
734 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
735 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
736 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
737 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
738
739 MPM.run(*M, MAM);
740 // Two runs and 6 functions.
741 EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
742}
743
744// Check that by marking the function pass and FAM proxy as preserved, this
745// propagates all the way through.
746TEST_F(CGSCCPassManagerTest,
747 TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC) {
748 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
749
750 int FunctionAnalysisRuns = 0;
751 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
752
753 ModulePassManager MPM(/*DebugLogging*/ true);
754
755 // First force the analysis to be run.
756 FunctionPassManager FPM1(/*DebugLogging*/ true);
757 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
758 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
759 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
760 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
761
762 // Now run a module pass that preserves the LazyCallGraph, the proxy, and
763 // the Function analysis.
764 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
765 PreservedAnalyses PA;
766 PA.preserve<LazyCallGraphAnalysis>();
767 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
768 PA.preserve<FunctionAnalysisManagerModuleProxy>();
769 PA.preserve<TestFunctionAnalysis>();
770 return PA;
771 }));
772
773 // And now a second CGSCC run which requires the SCC analysis again. This
774 // will trigger re-running it.
775 FunctionPassManager FPM2(/*DebugLogging*/ true);
776 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
777 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
778 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
779 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
780
781 MPM.run(*M, MAM);
782 // One run and 6 functions.
783 EXPECT_EQ(6, FunctionAnalysisRuns);
784}
785
786// Check that if the lazy call graph itself isn't preserved we still manage to
787// invalidate everything.
788TEST_F(CGSCCPassManagerTest,
789 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange) {
790 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
791
792 int FunctionAnalysisRuns = 0;
793 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
794
795 ModulePassManager MPM(/*DebugLogging*/ true);
796
797 // First force the analysis to be run.
798 FunctionPassManager FPM1(/*DebugLogging*/ true);
799 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
800 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
801 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
802 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
803
804 // Now run a module pass that preserves the LazyCallGraph but not the
805 // Function analysis.
806 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
807 PreservedAnalyses PA;
808 return PA;
809 }));
810
811 // And now a second CGSCC run which requires the SCC analysis again. This
812 // will trigger re-running it.
813 FunctionPassManager FPM2(/*DebugLogging*/ true);
814 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
815 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
816 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
817 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
818
819 MPM.run(*M, MAM);
820 // Two runs and 6 functions.
821 EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
822}
Chandler Carruthba90ae92016-12-27 08:40:39 +0000823
824/// A test CGSCC-level analysis pass which caches in its result another
825/// analysis pass and uses it to serve queries. This requires the result to
826/// invalidate itself when its dependency is invalidated.
827///
828/// FIXME: Currently this doesn't also depend on a function analysis, and if it
829/// did we would fail to invalidate it correctly.
830struct TestIndirectSCCAnalysis
831 : public AnalysisInfoMixin<TestIndirectSCCAnalysis> {
832 struct Result {
833 Result(TestSCCAnalysis::Result &SCCDep, TestModuleAnalysis::Result &MDep)
834 : SCCDep(SCCDep), MDep(MDep) {}
835 TestSCCAnalysis::Result &SCCDep;
836 TestModuleAnalysis::Result &MDep;
837
838 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
839 CGSCCAnalysisManager::Invalidator &Inv) {
840 auto PAC = PA.getChecker<TestIndirectSCCAnalysis>();
841 return !(PAC.preserved() ||
842 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
843 Inv.invalidate<TestSCCAnalysis>(C, PA);
844 }
845 };
846
847 TestIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
848
849 /// Run the analysis pass over the function and return a result.
850 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
851 LazyCallGraph &CG) {
852 ++Runs;
853 auto &SCCDep = AM.getResult<TestSCCAnalysis>(C, CG);
854
855 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
856 const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
857 // For the test, we insist that the module analysis starts off in the
858 // cache.
859 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(
860 *C.begin()->getFunction().getParent());
861 // Register the dependency as module analysis dependencies have to be
862 // pre-registered on the proxy.
863 ModuleProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
864 TestIndirectSCCAnalysis>();
865
866 return Result(SCCDep, MDep);
867 }
868
869private:
870 friend AnalysisInfoMixin<TestIndirectSCCAnalysis>;
871 static AnalysisKey Key;
872
873 int &Runs;
874};
875
876AnalysisKey TestIndirectSCCAnalysis::Key;
877
878/// A test analysis pass which caches in its result the result from the above
879/// indirect analysis pass.
880///
881/// This allows us to ensure that whenever an analysis pass is invalidated due
882/// to dependencies (especially dependencies across IR units that trigger
883/// asynchronous invalidation) we correctly detect that this may in turn cause
884/// other analysis to be invalidated.
885struct TestDoublyIndirectSCCAnalysis
886 : public AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis> {
887 struct Result {
888 Result(TestIndirectSCCAnalysis::Result &IDep) : IDep(IDep) {}
889 TestIndirectSCCAnalysis::Result &IDep;
890
891 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
892 CGSCCAnalysisManager::Invalidator &Inv) {
893 auto PAC = PA.getChecker<TestDoublyIndirectSCCAnalysis>();
894 return !(PAC.preserved() ||
895 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
896 Inv.invalidate<TestIndirectSCCAnalysis>(C, PA);
897 }
898 };
899
900 TestDoublyIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
901
902 /// Run the analysis pass over the function and return a result.
903 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
904 LazyCallGraph &CG) {
905 ++Runs;
906 auto &IDep = AM.getResult<TestIndirectSCCAnalysis>(C, CG);
907 return Result(IDep);
908 }
909
910private:
911 friend AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis>;
912 static AnalysisKey Key;
913
914 int &Runs;
915};
916
917AnalysisKey TestDoublyIndirectSCCAnalysis::Key;
918
919/// A test analysis pass which caches results from three different IR unit
920/// layers and requires intermediate layers to correctly propagate the entire
921/// distance.
922struct TestIndirectFunctionAnalysis
923 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
924 struct Result {
925 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep,
926 TestSCCAnalysis::Result &SCCDep)
927 : FDep(FDep), MDep(MDep), SCCDep(SCCDep) {}
928 TestFunctionAnalysis::Result &FDep;
929 TestModuleAnalysis::Result &MDep;
930 TestSCCAnalysis::Result &SCCDep;
931
932 bool invalidate(Function &F, const PreservedAnalyses &PA,
933 FunctionAnalysisManager::Invalidator &Inv) {
934 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
935 return !(PAC.preserved() ||
936 PAC.preservedSet<AllAnalysesOn<Function>>()) ||
937 Inv.invalidate<TestFunctionAnalysis>(F, PA);
938 }
939 };
940
941 TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
942
943 /// Run the analysis pass over the function and return a result.
944 Result run(Function &F, FunctionAnalysisManager &AM) {
945 ++Runs;
946 auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
947
948 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
949 const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
950 // For the test, we insist that the module analysis starts off in the
951 // cache.
952 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
953 // Register the dependency as module analysis dependencies have to be
954 // pre-registered on the proxy.
955 ModuleProxy.registerOuterAnalysisInvalidation<
956 TestModuleAnalysis, TestIndirectFunctionAnalysis>();
957
958 // For thet test we assume this is run inside a CGSCC pass manager.
959 const LazyCallGraph &CG =
960 *MAM.getCachedResult<LazyCallGraphAnalysis>(*F.getParent());
961 auto &CGSCCProxy = AM.getResult<CGSCCAnalysisManagerFunctionProxy>(F);
962 const CGSCCAnalysisManager &CGAM = CGSCCProxy.getManager();
963 // For the test, we insist that the CGSCC analysis starts off in the cache.
964 auto &SCCDep =
965 *CGAM.getCachedResult<TestSCCAnalysis>(*CG.lookupSCC(*CG.lookup(F)));
966 // Register the dependency as CGSCC analysis dependencies have to be
967 // pre-registered on the proxy.
968 CGSCCProxy.registerOuterAnalysisInvalidation<
969 TestSCCAnalysis, TestIndirectFunctionAnalysis>();
970
971 return Result(FDep, MDep, SCCDep);
972 }
973
974private:
975 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
976 static AnalysisKey Key;
977
978 int &Runs;
979};
980
981AnalysisKey TestIndirectFunctionAnalysis::Key;
982
983TEST_F(CGSCCPassManagerTest, TestIndirectAnalysisInvalidation) {
984 int ModuleAnalysisRuns = 0;
985 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
986
987 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
988 DoublyIndirectSCCAnalysisRuns = 0;
989 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
990 CGAM.registerPass(
991 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
992 CGAM.registerPass([&] {
993 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
994 });
995
996 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
997 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
998 FAM.registerPass([&] {
999 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
1000 });
1001
1002 ModulePassManager MPM(/*DebugLogging*/ true);
1003
1004 int FunctionCount = 0;
1005 CGSCCPassManager CGPM(/*DebugLogging*/ true);
1006 // First just use the analysis to get the function count and preserve
1007 // everything.
1008 CGPM.addPass(
1009 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1010 LazyCallGraph &CG, CGSCCUpdateResult &) {
1011 auto &DoublyIndirectResult =
1012 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1013 auto &IndirectResult = DoublyIndirectResult.IDep;
1014 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1015 return PreservedAnalyses::all();
1016 }));
1017 // Next, invalidate
1018 // - both analyses for the (f) and (x) SCCs,
1019 // - just the underlying (indirect) analysis for (g) SCC, and
1020 // - just the direct analysis for (h1,h2,h3) SCC.
1021 CGPM.addPass(
1022 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1023 LazyCallGraph &CG, CGSCCUpdateResult &) {
1024 auto &DoublyIndirectResult =
1025 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1026 auto &IndirectResult = DoublyIndirectResult.IDep;
1027 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1028 auto PA = PreservedAnalyses::none();
1029 if (C.getName() == "(g)")
1030 PA.preserve<TestSCCAnalysis>();
1031 else if (C.getName() == "(h3, h1, h2)")
1032 PA.preserve<TestIndirectSCCAnalysis>();
1033 return PA;
1034 }));
1035 // Finally, use the analysis again on each function, forcing re-computation
1036 // for all of them.
1037 CGPM.addPass(
1038 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1039 LazyCallGraph &CG, CGSCCUpdateResult &) {
1040 auto &DoublyIndirectResult =
1041 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1042 auto &IndirectResult = DoublyIndirectResult.IDep;
1043 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1044 return PreservedAnalyses::all();
1045 }));
1046
1047 // Create a second CGSCC pass manager. This will cause the module-level
1048 // invalidation to occur, which will force yet another invalidation of the
1049 // indirect SCC-level analysis as the module analysis it depends on gets
1050 // invalidated.
1051 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
1052 CGPM2.addPass(
1053 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1054 LazyCallGraph &CG, CGSCCUpdateResult &) {
1055 auto &DoublyIndirectResult =
1056 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1057 auto &IndirectResult = DoublyIndirectResult.IDep;
1058 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1059 return PreservedAnalyses::all();
1060 }));
1061
1062 // Add a requires pass to populate the module analysis and then our function
1063 // pass pipeline.
1064 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1065 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1066 // Now require the module analysis again (it will have been invalidated once)
1067 // and then use it again from a function pass manager.
1068 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1069 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
1070 MPM.run(*M, MAM);
1071
1072 // There are generally two possible runs for each of the four SCCs. But
1073 // for one SCC, we only invalidate the indirect analysis so the base one
1074 // only gets run seven times.
1075 EXPECT_EQ(7, SCCAnalysisRuns);
1076 // The module analysis pass should be run twice here.
1077 EXPECT_EQ(2, ModuleAnalysisRuns);
1078 // The indirect analysis is invalidated (either directly or indirectly) three
1079 // times for each of four SCCs.
1080 EXPECT_EQ(3 * 4, IndirectSCCAnalysisRuns);
1081 EXPECT_EQ(3 * 4, DoublyIndirectSCCAnalysisRuns);
1082
1083 // Four passes count each of six functions once (via SCCs).
1084 EXPECT_EQ(4 * 6, FunctionCount);
1085}
Chandler Carruth74319922016-02-23 10:02:02 +00001086}