blob: 95c107a93a222c0bda786df60761d00624b2e6fe [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 Carruth74319922016-02-23 10:02:02 +0000823}