blob: e248182659758a2c9df952b600743540c16a646b [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"
Chandler Carruthf59a8382017-07-15 08:08:19 +000012#include "llvm/Analysis/TargetLibraryInfo.h"
Chandler Carruth74319922016-02-23 10:02:02 +000013#include "llvm/AsmParser/Parser.h"
14#include "llvm/IR/Function.h"
15#include "llvm/IR/InstIterator.h"
16#include "llvm/IR/LLVMContext.h"
17#include "llvm/IR/Module.h"
18#include "llvm/IR/PassManager.h"
19#include "llvm/Support/SourceMgr.h"
20#include "gtest/gtest.h"
21
22using namespace llvm;
23
24namespace {
25
Chandler Carruthdab4eae2016-11-23 17:53:26 +000026class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
Chandler Carruth74319922016-02-23 10:02:02 +000027public:
28 struct Result {
29 Result(int Count) : FunctionCount(Count) {}
30 int FunctionCount;
31 };
32
Chandler Carruth74319922016-02-23 10:02:02 +000033 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
34
Chandler Carruthb47f8012016-03-11 11:05:24 +000035 Result run(Module &M, ModuleAnalysisManager &AM) {
Chandler Carruth74319922016-02-23 10:02:02 +000036 ++Runs;
37 return Result(M.size());
38 }
39
40private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +000041 friend AnalysisInfoMixin<TestModuleAnalysis>;
42 static AnalysisKey Key;
Chandler Carruth74319922016-02-23 10:02:02 +000043
44 int &Runs;
45};
46
Chandler Carruthdab4eae2016-11-23 17:53:26 +000047AnalysisKey TestModuleAnalysis::Key;
Chandler Carruth74319922016-02-23 10:02:02 +000048
Chandler Carruthdab4eae2016-11-23 17:53:26 +000049class TestSCCAnalysis : public AnalysisInfoMixin<TestSCCAnalysis> {
Chandler Carruth74319922016-02-23 10:02:02 +000050public:
51 struct Result {
52 Result(int Count) : FunctionCount(Count) {}
53 int FunctionCount;
54 };
55
Chandler Carruth74319922016-02-23 10:02:02 +000056 TestSCCAnalysis(int &Runs) : Runs(Runs) {}
57
Chandler Carruth88823462016-08-24 09:37:14 +000058 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &) {
Chandler Carruth74319922016-02-23 10:02:02 +000059 ++Runs;
60 return Result(C.size());
61 }
62
63private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +000064 friend AnalysisInfoMixin<TestSCCAnalysis>;
65 static AnalysisKey Key;
Chandler Carruth74319922016-02-23 10:02:02 +000066
67 int &Runs;
68};
69
Chandler Carruthdab4eae2016-11-23 17:53:26 +000070AnalysisKey TestSCCAnalysis::Key;
Chandler Carruth74319922016-02-23 10:02:02 +000071
Chandler Carruthdab4eae2016-11-23 17:53:26 +000072class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
Chandler Carruth74319922016-02-23 10:02:02 +000073public:
74 struct Result {
75 Result(int Count) : InstructionCount(Count) {}
76 int InstructionCount;
77 };
78
Chandler Carruth74319922016-02-23 10:02:02 +000079 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
80
Chandler Carruthb47f8012016-03-11 11:05:24 +000081 Result run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruth74319922016-02-23 10:02:02 +000082 ++Runs;
83 int Count = 0;
84 for (Instruction &I : instructions(F)) {
85 (void)I;
86 ++Count;
87 }
88 return Result(Count);
89 }
90
91private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +000092 friend AnalysisInfoMixin<TestFunctionAnalysis>;
93 static AnalysisKey Key;
Chandler Carruth74319922016-02-23 10:02:02 +000094
95 int &Runs;
96};
97
Chandler Carruthdab4eae2016-11-23 17:53:26 +000098AnalysisKey TestFunctionAnalysis::Key;
Chandler Carruth74319922016-02-23 10:02:02 +000099
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000100class TestImmutableFunctionAnalysis
101 : public AnalysisInfoMixin<TestImmutableFunctionAnalysis> {
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000102public:
103 struct Result {
Chandler Carruth3ab2a5a2016-11-28 22:04:31 +0000104 bool invalidate(Function &, const PreservedAnalyses &,
105 FunctionAnalysisManager::Invalidator &) {
106 return false;
107 }
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000108 };
109
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000110 TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {}
111
Chandler Carruthb47f8012016-03-11 11:05:24 +0000112 Result run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000113 ++Runs;
114 return Result();
115 }
116
117private:
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000118 friend AnalysisInfoMixin<TestImmutableFunctionAnalysis>;
119 static AnalysisKey Key;
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000120
121 int &Runs;
122};
123
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000124AnalysisKey TestImmutableFunctionAnalysis::Key;
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000125
Chandler Carruth6b981642016-12-10 06:34:44 +0000126struct LambdaModulePass : public PassInfoMixin<LambdaModulePass> {
127 template <typename T>
128 LambdaModulePass(T &&Arg) : Func(std::forward<T>(Arg)) {}
129
130 PreservedAnalyses run(Module &F, ModuleAnalysisManager &AM) {
131 return Func(F, AM);
132 }
133
134 std::function<PreservedAnalyses(Module &, ModuleAnalysisManager &)> Func;
135};
136
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000137struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> {
138 template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
Chandler Carruth74319922016-02-23 10:02:02 +0000139
Chandler Carruth88823462016-08-24 09:37:14 +0000140 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
141 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000142 return Func(C, AM, CG, UR);
Chandler Carruth74319922016-02-23 10:02:02 +0000143 }
144
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000145 std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
146 LazyCallGraph &, CGSCCUpdateResult &)>
147 Func;
Chandler Carruth74319922016-02-23 10:02:02 +0000148};
149
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000150struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> {
Chandler Carruth6b981642016-12-10 06:34:44 +0000151 template <typename T>
152 LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
Chandler Carruth74319922016-02-23 10:02:02 +0000153
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000154 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
155 return Func(F, AM);
Chandler Carruth74319922016-02-23 10:02:02 +0000156 }
157
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000158 std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func;
Chandler Carruth74319922016-02-23 10:02:02 +0000159};
160
Chandler Carruth6c138ce2016-06-28 00:38:42 +0000161std::unique_ptr<Module> parseIR(const char *IR) {
162 // We just use a static context here. This is never called from multiple
163 // threads so it is harmless no matter how it is implemented. We just need
164 // the context to outlive the module which it does.
165 static LLVMContext C;
Chandler Carruth74319922016-02-23 10:02:02 +0000166 SMDiagnostic Err;
167 return parseAssemblyString(IR, Err, C);
168}
169
Chandler Carruth4f837422016-09-02 01:14:05 +0000170class CGSCCPassManagerTest : public ::testing::Test {
171protected:
172 LLVMContext Context;
Chandler Carruthdc288a82016-09-26 06:29:21 +0000173 FunctionAnalysisManager FAM;
174 CGSCCAnalysisManager CGAM;
175 ModuleAnalysisManager MAM;
176
Chandler Carruth4f837422016-09-02 01:14:05 +0000177 std::unique_ptr<Module> M;
178
179public:
180 CGSCCPassManagerTest()
Chandler Carruthdc288a82016-09-26 06:29:21 +0000181 : FAM(/*DebugLogging*/ true), CGAM(/*DebugLogging*/ true),
Chandler Carruth4cf2c892016-11-28 03:40:33 +0000182 MAM(/*DebugLogging*/ true),
183 M(parseIR(
184 // Define a module with the following call graph, where calls go
185 // out the bottom of nodes and enter the top:
186 //
187 // f
188 // |\ _
189 // | \ / |
190 // g h1 |
191 // | | |
192 // | h2 |
193 // | | |
194 // | h3 |
195 // | / \_/
196 // |/
197 // x
198 //
199 "define void @f() {\n"
200 "entry:\n"
201 " call void @g()\n"
202 " call void @h1()\n"
203 " ret void\n"
204 "}\n"
205 "define void @g() {\n"
206 "entry:\n"
207 " call void @g()\n"
208 " call void @x()\n"
209 " ret void\n"
210 "}\n"
211 "define void @h1() {\n"
212 "entry:\n"
213 " call void @h2()\n"
214 " ret void\n"
215 "}\n"
216 "define void @h2() {\n"
217 "entry:\n"
218 " call void @h3()\n"
219 " call void @x()\n"
220 " ret void\n"
221 "}\n"
222 "define void @h3() {\n"
223 "entry:\n"
224 " call void @h1()\n"
225 " ret void\n"
226 "}\n"
227 "define void @x() {\n"
228 "entry:\n"
229 " ret void\n"
230 "}\n")) {
Chandler Carruthf59a8382017-07-15 08:08:19 +0000231 MAM.registerPass([&] { return TargetLibraryAnalysis(); });
Chandler Carruthdc288a82016-09-26 06:29:21 +0000232 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
233 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
234 MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
Chandler Carruth6b981642016-12-10 06:34:44 +0000235 CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); });
Chandler Carruthdc288a82016-09-26 06:29:21 +0000236 CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
237 FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
238 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
239 }
Chandler Carruth4f837422016-09-02 01:14:05 +0000240};
241
242TEST_F(CGSCCPassManagerTest, Basic) {
Chandler Carruth74319922016-02-23 10:02:02 +0000243 int FunctionAnalysisRuns = 0;
244 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000245 int ImmutableFunctionAnalysisRuns = 0;
246 FAM.registerPass([&] {
247 return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns);
248 });
Chandler Carruth74319922016-02-23 10:02:02 +0000249
Chandler Carruth74319922016-02-23 10:02:02 +0000250 int SCCAnalysisRuns = 0;
251 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
252
Chandler Carruth74319922016-02-23 10:02:02 +0000253 int ModuleAnalysisRuns = 0;
Chandler Carruth74319922016-02-23 10:02:02 +0000254 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
255
Chandler Carruth74319922016-02-23 10:02:02 +0000256 ModulePassManager MPM(/*DebugLogging*/ true);
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000257 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
Chandler Carruth74319922016-02-23 10:02:02 +0000258
259 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
Chandler Carruth6b981642016-12-10 06:34:44 +0000260 FunctionPassManager FPM1(/*DebugLogging*/ true);
261 int FunctionPassRunCount1 = 0;
262 FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
263 ++FunctionPassRunCount1;
264 return PreservedAnalyses::none();
265 }));
266 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
267
Chandler Carruth74319922016-02-23 10:02:02 +0000268 int SCCPassRunCount1 = 0;
269 int AnalyzedInstrCount1 = 0;
270 int AnalyzedSCCFunctionCount1 = 0;
271 int AnalyzedModuleFunctionCount1 = 0;
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000272 CGPM1.addPass(
273 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
274 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
275 ++SCCPassRunCount1;
276
277 const ModuleAnalysisManager &MAM =
278 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
279 FunctionAnalysisManager &FAM =
280 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
281 if (TestModuleAnalysis::Result *TMA =
282 MAM.getCachedResult<TestModuleAnalysis>(
283 *C.begin()->getFunction().getParent()))
284 AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
285
286 TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
287 AnalyzedSCCFunctionCount1 += AR.FunctionCount;
288 for (LazyCallGraph::Node &N : C) {
289 TestFunctionAnalysis::Result &FAR =
290 FAM.getResult<TestFunctionAnalysis>(N.getFunction());
291 AnalyzedInstrCount1 += FAR.InstructionCount;
292
293 // Just ensure we get the immutable results.
294 (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction());
295 }
296
297 return PreservedAnalyses::all();
298 }));
Chandler Carruth74319922016-02-23 10:02:02 +0000299
Chandler Carruth6b981642016-12-10 06:34:44 +0000300 FunctionPassManager FPM2(/*DebugLogging*/ true);
301 int FunctionPassRunCount2 = 0;
302 FPM2.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
303 ++FunctionPassRunCount2;
304 return PreservedAnalyses::none();
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000305 }));
Chandler Carruth6b981642016-12-10 06:34:44 +0000306 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
307
Chandler Carruth74319922016-02-23 10:02:02 +0000308 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
309
Chandler Carruth6b981642016-12-10 06:34:44 +0000310 FunctionPassManager FPM3(/*DebugLogging*/ true);
311 int FunctionPassRunCount3 = 0;
312 FPM3.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
313 ++FunctionPassRunCount3;
314 return PreservedAnalyses::none();
315 }));
316 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM3)));
317
Chandler Carruthb47f8012016-03-11 11:05:24 +0000318 MPM.run(*M, MAM);
Chandler Carruth74319922016-02-23 10:02:02 +0000319
Chandler Carruth6b981642016-12-10 06:34:44 +0000320 EXPECT_EQ(4, SCCPassRunCount1);
321 EXPECT_EQ(6, FunctionPassRunCount1);
322 EXPECT_EQ(6, FunctionPassRunCount2);
323 EXPECT_EQ(6, FunctionPassRunCount3);
324
Chandler Carruth74319922016-02-23 10:02:02 +0000325 EXPECT_EQ(1, ModuleAnalysisRuns);
326 EXPECT_EQ(4, SCCAnalysisRuns);
327 EXPECT_EQ(6, FunctionAnalysisRuns);
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000328 EXPECT_EQ(6, ImmutableFunctionAnalysisRuns);
Chandler Carruth74319922016-02-23 10:02:02 +0000329
Chandler Carruth74319922016-02-23 10:02:02 +0000330 EXPECT_EQ(14, AnalyzedInstrCount1);
331 EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
332 EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
333}
334
Chandler Carruthb52b5732016-09-26 04:01:55 +0000335// Test that an SCC pass which fails to preserve a module analysis does in fact
336// invalidate that module analysis.
337TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
Chandler Carruthb52b5732016-09-26 04:01:55 +0000338 int ModuleAnalysisRuns = 0;
339 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
340
341 ModulePassManager MPM(/*DebugLogging*/ true);
342 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
343
344 // The first CGSCC run we preserve everything and make sure that works and
345 // the module analysis is available in the second CGSCC run from the one
346 // required module pass above.
347 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
348 int CountFoundModuleAnalysis1 = 0;
349 CGPM1.addPass(
350 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
351 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
352 const auto &MAM =
353 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
354 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
355 *C.begin()->getFunction().getParent());
356
357 if (TMA)
358 ++CountFoundModuleAnalysis1;
359
360 return PreservedAnalyses::all();
361 }));
362 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
363
364 // The second CGSCC run checks that the module analysis got preserved the
365 // previous time and in one SCC fails to preserve it.
366 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
367 int CountFoundModuleAnalysis2 = 0;
368 CGPM2.addPass(
369 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
370 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
371 const auto &MAM =
372 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
373 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
374 *C.begin()->getFunction().getParent());
375
376 if (TMA)
377 ++CountFoundModuleAnalysis2;
378
379 // Only fail to preserve analyses on one SCC and make sure that gets
380 // propagated.
381 return C.getName() == "(g)" ? PreservedAnalyses::none()
382 : PreservedAnalyses::all();
383 }));
384 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
385
386 // The third CGSCC run should fail to find a cached module analysis as it
387 // should have been invalidated by the above CGSCC run.
388 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
389 int CountFoundModuleAnalysis3 = 0;
390 CGPM3.addPass(
391 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
392 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
393 const auto &MAM =
394 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
395 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
396 *C.begin()->getFunction().getParent());
397
398 if (TMA)
399 ++CountFoundModuleAnalysis3;
400
401 return PreservedAnalyses::none();
402 }));
403 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
404
405 MPM.run(*M, MAM);
406
407 EXPECT_EQ(1, ModuleAnalysisRuns);
408 EXPECT_EQ(4, CountFoundModuleAnalysis1);
409 EXPECT_EQ(4, CountFoundModuleAnalysis2);
410 EXPECT_EQ(0, CountFoundModuleAnalysis3);
411}
412
Chandler Carruthe35f84a2016-09-26 04:17:12 +0000413// Similar to the above, but test that this works for function passes embedded
414// *within* a CGSCC layer.
415TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) {
Chandler Carruthe35f84a2016-09-26 04:17:12 +0000416 int ModuleAnalysisRuns = 0;
417 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
418
419 ModulePassManager MPM(/*DebugLogging*/ true);
420 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
421
422 // The first run we preserve everything and make sure that works and the
423 // module analysis is available in the second run from the one required
424 // module pass above.
425 FunctionPassManager FPM1(/*DebugLogging*/ true);
426 // Start true and mark false if we ever failed to find a module analysis
427 // because we expect this to succeed for each SCC.
428 bool FoundModuleAnalysis1 = true;
429 FPM1.addPass(
430 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
431 const auto &MAM =
432 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
433 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
434
435 if (!TMA)
436 FoundModuleAnalysis1 = false;
437
438 return PreservedAnalyses::all();
439 }));
440 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
441 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
442 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
443
444 // The second run checks that the module analysis got preserved the previous
445 // time and in one function fails to preserve it.
446 FunctionPassManager FPM2(/*DebugLogging*/ true);
447 // Again, start true and mark false if we ever failed to find a module analysis
448 // because we expect this to succeed for each SCC.
449 bool FoundModuleAnalysis2 = true;
450 FPM2.addPass(
451 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
452 const auto &MAM =
453 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
454 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
455
456 if (!TMA)
457 FoundModuleAnalysis2 = false;
458
459 // Only fail to preserve analyses on one SCC and make sure that gets
460 // propagated.
461 return F.getName() == "h2" ? PreservedAnalyses::none()
462 : PreservedAnalyses::all();
463 }));
464 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
465 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
466 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
467
468 // The third run should fail to find a cached module analysis as it should
469 // have been invalidated by the above run.
470 FunctionPassManager FPM3(/*DebugLogging*/ true);
471 // Start false and mark true if we ever *succeeded* to find a module
472 // analysis, as we expect this to fail for every function.
473 bool FoundModuleAnalysis3 = false;
474 FPM3.addPass(
475 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
476 const auto &MAM =
477 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
478 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
479
480 if (TMA)
481 FoundModuleAnalysis3 = true;
482
483 return PreservedAnalyses::none();
484 }));
485 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
486 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3)));
487 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
488
489 MPM.run(*M, MAM);
490
491 EXPECT_EQ(1, ModuleAnalysisRuns);
492 EXPECT_TRUE(FoundModuleAnalysis1);
493 EXPECT_TRUE(FoundModuleAnalysis2);
494 EXPECT_FALSE(FoundModuleAnalysis3);
495}
496
Chandler Carruth6b981642016-12-10 06:34:44 +0000497// Test that a Module pass which fails to preserve an SCC analysis in fact
498// invalidates that analysis.
499TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysis) {
500 int SCCAnalysisRuns = 0;
501 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
502
503 ModulePassManager MPM(/*DebugLogging*/ true);
504
505 // First force the analysis to be run.
506 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
507 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
508 CGSCCAnalysisManager, LazyCallGraph &,
509 CGSCCUpdateResult &>());
510 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
511
512 // Now run a module pass that preserves the LazyCallGraph and the proxy but
513 // not the SCC analysis.
514 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
515 PreservedAnalyses PA;
516 PA.preserve<LazyCallGraphAnalysis>();
517 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
518 PA.preserve<FunctionAnalysisManagerModuleProxy>();
519 return PA;
520 }));
521
522 // And now a second CGSCC run which requires the SCC analysis again. This
523 // will trigger re-running it.
524 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
525 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
526 CGSCCAnalysisManager, LazyCallGraph &,
527 CGSCCUpdateResult &>());
528 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
529
530 MPM.run(*M, MAM);
531 // Two runs and four SCCs.
532 EXPECT_EQ(2 * 4, SCCAnalysisRuns);
533}
534
535// Check that marking the SCC analysis preserved is sufficient to avoid
536// invaliadtion. This should only run the analysis once for each SCC.
537TEST_F(CGSCCPassManagerTest, TestModulePassCanPreserveSCCAnalysis) {
538 int SCCAnalysisRuns = 0;
539 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
540
541 ModulePassManager MPM(/*DebugLogging*/ true);
542
543 // First force the analysis to be run.
544 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
545 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
546 CGSCCAnalysisManager, LazyCallGraph &,
547 CGSCCUpdateResult &>());
548 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
549
550 // Now run a module pass that preserves each of the necessary components
551 // (but not everything).
552 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
553 PreservedAnalyses PA;
554 PA.preserve<LazyCallGraphAnalysis>();
555 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
556 PA.preserve<FunctionAnalysisManagerModuleProxy>();
557 PA.preserve<TestSCCAnalysis>();
558 return PA;
559 }));
560
561 // And now a second CGSCC run which requires the SCC analysis again but find
562 // it in the cache.
563 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
564 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
565 CGSCCAnalysisManager, LazyCallGraph &,
566 CGSCCUpdateResult &>());
567 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
568
569 MPM.run(*M, MAM);
570 // Four SCCs
571 EXPECT_EQ(4, SCCAnalysisRuns);
572}
573
574// Check that even when the analysis is preserved, if the SCC information isn't
575// we still nuke things because the SCC keys could change.
576TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysisOnCGChange) {
577 int SCCAnalysisRuns = 0;
578 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
579
580 ModulePassManager MPM(/*DebugLogging*/ true);
581
582 // First force the analysis to be run.
583 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
584 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
585 CGSCCAnalysisManager, LazyCallGraph &,
586 CGSCCUpdateResult &>());
587 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
588
589 // Now run a module pass that preserves the analysis but not the call
590 // graph or proxy.
591 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
592 PreservedAnalyses PA;
593 PA.preserve<TestSCCAnalysis>();
594 return PA;
595 }));
596
597 // And now a second CGSCC run which requires the SCC analysis again.
598 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
599 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
600 CGSCCAnalysisManager, LazyCallGraph &,
601 CGSCCUpdateResult &>());
602 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
603
604 MPM.run(*M, MAM);
605 // Two runs and four SCCs.
606 EXPECT_EQ(2 * 4, SCCAnalysisRuns);
607}
608
609// Test that an SCC pass which fails to preserve a Function analysis in fact
610// invalidates that analysis.
611TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesFunctionAnalysis) {
612 int FunctionAnalysisRuns = 0;
613 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
614
615 // Create a very simple module with a single function and SCC to make testing
616 // these issues much easier.
617 std::unique_ptr<Module> M = parseIR("declare void @g()\n"
618 "declare void @h()\n"
619 "define void @f() {\n"
620 "entry:\n"
621 " call void @g()\n"
622 " call void @h()\n"
623 " ret void\n"
624 "}\n");
625
626 CGSCCPassManager CGPM(/*DebugLogging*/ true);
627
628 // First force the analysis to be run.
629 FunctionPassManager FPM1(/*DebugLogging*/ true);
630 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
631 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
632
633 // Now run a module pass that preserves the LazyCallGraph and proxy but not
634 // the SCC analysis.
635 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
636 LazyCallGraph &, CGSCCUpdateResult &) {
637 PreservedAnalyses PA;
638 PA.preserve<LazyCallGraphAnalysis>();
639 return PA;
640 }));
641
642 // And now a second CGSCC run which requires the SCC analysis again. This
643 // will trigger re-running it.
644 FunctionPassManager FPM2(/*DebugLogging*/ true);
645 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
646 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
647
648 ModulePassManager MPM(/*DebugLogging*/ true);
649 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
650 MPM.run(*M, MAM);
651 EXPECT_EQ(2, FunctionAnalysisRuns);
652}
653
654// Check that marking the SCC analysis preserved is sufficient. This should
655// only run the analysis once the SCC.
656TEST_F(CGSCCPassManagerTest, TestSCCPassCanPreserveFunctionAnalysis) {
657 int FunctionAnalysisRuns = 0;
658 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
659
660 // Create a very simple module with a single function and SCC to make testing
661 // these issues much easier.
662 std::unique_ptr<Module> M = parseIR("declare void @g()\n"
663 "declare void @h()\n"
664 "define void @f() {\n"
665 "entry:\n"
666 " call void @g()\n"
667 " call void @h()\n"
668 " ret void\n"
669 "}\n");
670
671 CGSCCPassManager CGPM(/*DebugLogging*/ true);
672
673 // First force the analysis to be run.
674 FunctionPassManager FPM1(/*DebugLogging*/ true);
675 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
676 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
677
678 // Now run a module pass that preserves each of the necessary components
679 // (but
680 // not everything).
681 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
682 LazyCallGraph &, CGSCCUpdateResult &) {
683 PreservedAnalyses PA;
684 PA.preserve<LazyCallGraphAnalysis>();
Chandler Carruthbd9c2902017-07-09 03:59:31 +0000685 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
Chandler Carruth6b981642016-12-10 06:34:44 +0000686 PA.preserve<TestFunctionAnalysis>();
687 return PA;
688 }));
689
690 // And now a second CGSCC run which requires the SCC analysis again but find
691 // it in the cache.
692 FunctionPassManager FPM2(/*DebugLogging*/ true);
693 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
694 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
695
696 ModulePassManager MPM(/*DebugLogging*/ true);
697 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
698 MPM.run(*M, MAM);
699 EXPECT_EQ(1, FunctionAnalysisRuns);
700}
701
702// Note that there is no test for invalidating the call graph or other
703// structure with an SCC pass because there is no mechanism to do that from
704// withinsuch a pass. Instead, such a pass has to directly update the call
705// graph structure.
706
707// Test that a madule pass invalidates function analyses when the CGSCC proxies
708// and pass manager.
709TEST_F(CGSCCPassManagerTest,
710 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC) {
711 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
712
713 int FunctionAnalysisRuns = 0;
714 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
715
716 ModulePassManager MPM(/*DebugLogging*/ true);
717
718 // First force the analysis to be run.
719 FunctionPassManager FPM1(/*DebugLogging*/ true);
720 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
721 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
722 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
723 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
724
Chandler Carruthbd9c2902017-07-09 03:59:31 +0000725 // Now run a module pass that preserves the LazyCallGraph and proxies but not
Chandler Carruth6b981642016-12-10 06:34:44 +0000726 // the Function analysis.
727 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
728 PreservedAnalyses PA;
729 PA.preserve<LazyCallGraphAnalysis>();
730 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
Chandler Carruthbd9c2902017-07-09 03:59:31 +0000731 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
732 PA.preserve<FunctionAnalysisManagerModuleProxy>();
Chandler Carruth6b981642016-12-10 06:34:44 +0000733 return PA;
734 }));
735
736 // And now a second CGSCC run which requires the SCC analysis again. This
737 // will trigger re-running it.
738 FunctionPassManager FPM2(/*DebugLogging*/ true);
739 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
740 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
741 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
742 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
743
744 MPM.run(*M, MAM);
745 // Two runs and 6 functions.
746 EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
747}
748
Chandler Carruthbd9c2902017-07-09 03:59:31 +0000749// Check that by marking the function pass and proxies as preserved, this
Chandler Carruth6b981642016-12-10 06:34:44 +0000750// propagates all the way through.
751TEST_F(CGSCCPassManagerTest,
752 TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC) {
753 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
754
755 int FunctionAnalysisRuns = 0;
756 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
757
758 ModulePassManager MPM(/*DebugLogging*/ true);
759
760 // First force the analysis to be run.
761 FunctionPassManager FPM1(/*DebugLogging*/ true);
762 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
763 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
764 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
765 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
766
767 // Now run a module pass that preserves the LazyCallGraph, the proxy, and
768 // the Function analysis.
769 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
770 PreservedAnalyses PA;
771 PA.preserve<LazyCallGraphAnalysis>();
772 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
Chandler Carruthbd9c2902017-07-09 03:59:31 +0000773 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
Chandler Carruth6b981642016-12-10 06:34:44 +0000774 PA.preserve<FunctionAnalysisManagerModuleProxy>();
775 PA.preserve<TestFunctionAnalysis>();
776 return PA;
777 }));
778
779 // And now a second CGSCC run which requires the SCC analysis again. This
780 // will trigger re-running it.
781 FunctionPassManager FPM2(/*DebugLogging*/ true);
782 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
783 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
784 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
785 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
786
787 MPM.run(*M, MAM);
788 // One run and 6 functions.
789 EXPECT_EQ(6, FunctionAnalysisRuns);
790}
791
792// Check that if the lazy call graph itself isn't preserved we still manage to
793// invalidate everything.
794TEST_F(CGSCCPassManagerTest,
795 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange) {
796 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
797
798 int FunctionAnalysisRuns = 0;
799 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
800
801 ModulePassManager MPM(/*DebugLogging*/ true);
802
803 // First force the analysis to be run.
804 FunctionPassManager FPM1(/*DebugLogging*/ true);
805 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
806 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
807 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
808 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
809
810 // Now run a module pass that preserves the LazyCallGraph but not the
811 // Function analysis.
812 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
813 PreservedAnalyses PA;
814 return PA;
815 }));
816
817 // And now a second CGSCC run which requires the SCC analysis again. This
818 // will trigger re-running it.
819 FunctionPassManager FPM2(/*DebugLogging*/ true);
820 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
821 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
822 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
823 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
824
825 MPM.run(*M, MAM);
826 // Two runs and 6 functions.
827 EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
828}
Chandler Carruthba90ae92016-12-27 08:40:39 +0000829
830/// A test CGSCC-level analysis pass which caches in its result another
831/// analysis pass and uses it to serve queries. This requires the result to
832/// invalidate itself when its dependency is invalidated.
833///
834/// FIXME: Currently this doesn't also depend on a function analysis, and if it
835/// did we would fail to invalidate it correctly.
836struct TestIndirectSCCAnalysis
837 : public AnalysisInfoMixin<TestIndirectSCCAnalysis> {
838 struct Result {
839 Result(TestSCCAnalysis::Result &SCCDep, TestModuleAnalysis::Result &MDep)
840 : SCCDep(SCCDep), MDep(MDep) {}
841 TestSCCAnalysis::Result &SCCDep;
842 TestModuleAnalysis::Result &MDep;
843
844 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
845 CGSCCAnalysisManager::Invalidator &Inv) {
846 auto PAC = PA.getChecker<TestIndirectSCCAnalysis>();
847 return !(PAC.preserved() ||
848 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
849 Inv.invalidate<TestSCCAnalysis>(C, PA);
850 }
851 };
852
853 TestIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
854
855 /// Run the analysis pass over the function and return a result.
856 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
857 LazyCallGraph &CG) {
858 ++Runs;
859 auto &SCCDep = AM.getResult<TestSCCAnalysis>(C, CG);
860
861 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
862 const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
863 // For the test, we insist that the module analysis starts off in the
864 // cache.
865 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(
866 *C.begin()->getFunction().getParent());
867 // Register the dependency as module analysis dependencies have to be
868 // pre-registered on the proxy.
869 ModuleProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
870 TestIndirectSCCAnalysis>();
871
872 return Result(SCCDep, MDep);
873 }
874
875private:
876 friend AnalysisInfoMixin<TestIndirectSCCAnalysis>;
877 static AnalysisKey Key;
878
879 int &Runs;
880};
881
882AnalysisKey TestIndirectSCCAnalysis::Key;
883
884/// A test analysis pass which caches in its result the result from the above
885/// indirect analysis pass.
886///
887/// This allows us to ensure that whenever an analysis pass is invalidated due
888/// to dependencies (especially dependencies across IR units that trigger
889/// asynchronous invalidation) we correctly detect that this may in turn cause
890/// other analysis to be invalidated.
891struct TestDoublyIndirectSCCAnalysis
892 : public AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis> {
893 struct Result {
894 Result(TestIndirectSCCAnalysis::Result &IDep) : IDep(IDep) {}
895 TestIndirectSCCAnalysis::Result &IDep;
896
897 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
898 CGSCCAnalysisManager::Invalidator &Inv) {
899 auto PAC = PA.getChecker<TestDoublyIndirectSCCAnalysis>();
900 return !(PAC.preserved() ||
901 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
902 Inv.invalidate<TestIndirectSCCAnalysis>(C, PA);
903 }
904 };
905
906 TestDoublyIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
907
908 /// Run the analysis pass over the function and return a result.
909 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
910 LazyCallGraph &CG) {
911 ++Runs;
912 auto &IDep = AM.getResult<TestIndirectSCCAnalysis>(C, CG);
913 return Result(IDep);
914 }
915
916private:
917 friend AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis>;
918 static AnalysisKey Key;
919
920 int &Runs;
921};
922
923AnalysisKey TestDoublyIndirectSCCAnalysis::Key;
924
925/// A test analysis pass which caches results from three different IR unit
926/// layers and requires intermediate layers to correctly propagate the entire
927/// distance.
928struct TestIndirectFunctionAnalysis
929 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
930 struct Result {
931 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep,
932 TestSCCAnalysis::Result &SCCDep)
933 : FDep(FDep), MDep(MDep), SCCDep(SCCDep) {}
934 TestFunctionAnalysis::Result &FDep;
935 TestModuleAnalysis::Result &MDep;
936 TestSCCAnalysis::Result &SCCDep;
937
938 bool invalidate(Function &F, const PreservedAnalyses &PA,
939 FunctionAnalysisManager::Invalidator &Inv) {
940 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
941 return !(PAC.preserved() ||
942 PAC.preservedSet<AllAnalysesOn<Function>>()) ||
943 Inv.invalidate<TestFunctionAnalysis>(F, PA);
944 }
945 };
946
947 TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
948
949 /// Run the analysis pass over the function and return a result.
950 Result run(Function &F, FunctionAnalysisManager &AM) {
951 ++Runs;
952 auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
953
954 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
955 const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
956 // For the test, we insist that the module analysis starts off in the
957 // cache.
958 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
959 // Register the dependency as module analysis dependencies have to be
960 // pre-registered on the proxy.
961 ModuleProxy.registerOuterAnalysisInvalidation<
962 TestModuleAnalysis, TestIndirectFunctionAnalysis>();
963
964 // For thet test we assume this is run inside a CGSCC pass manager.
965 const LazyCallGraph &CG =
966 *MAM.getCachedResult<LazyCallGraphAnalysis>(*F.getParent());
967 auto &CGSCCProxy = AM.getResult<CGSCCAnalysisManagerFunctionProxy>(F);
968 const CGSCCAnalysisManager &CGAM = CGSCCProxy.getManager();
969 // For the test, we insist that the CGSCC analysis starts off in the cache.
970 auto &SCCDep =
971 *CGAM.getCachedResult<TestSCCAnalysis>(*CG.lookupSCC(*CG.lookup(F)));
972 // Register the dependency as CGSCC analysis dependencies have to be
973 // pre-registered on the proxy.
974 CGSCCProxy.registerOuterAnalysisInvalidation<
975 TestSCCAnalysis, TestIndirectFunctionAnalysis>();
976
977 return Result(FDep, MDep, SCCDep);
978 }
979
980private:
981 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
982 static AnalysisKey Key;
983
984 int &Runs;
985};
986
987AnalysisKey TestIndirectFunctionAnalysis::Key;
988
989TEST_F(CGSCCPassManagerTest, TestIndirectAnalysisInvalidation) {
990 int ModuleAnalysisRuns = 0;
991 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
992
993 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
994 DoublyIndirectSCCAnalysisRuns = 0;
995 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
996 CGAM.registerPass(
997 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
998 CGAM.registerPass([&] {
999 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
1000 });
1001
1002 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
1003 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
1004 FAM.registerPass([&] {
1005 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
1006 });
1007
1008 ModulePassManager MPM(/*DebugLogging*/ true);
1009
1010 int FunctionCount = 0;
1011 CGSCCPassManager CGPM(/*DebugLogging*/ true);
1012 // First just use the analysis to get the function count and preserve
1013 // everything.
1014 CGPM.addPass(
1015 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1016 LazyCallGraph &CG, CGSCCUpdateResult &) {
1017 auto &DoublyIndirectResult =
1018 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1019 auto &IndirectResult = DoublyIndirectResult.IDep;
1020 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1021 return PreservedAnalyses::all();
1022 }));
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001023 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1024 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1025
Chandler Carruthba90ae92016-12-27 08:40:39 +00001026 // Next, invalidate
1027 // - both analyses for the (f) and (x) SCCs,
1028 // - just the underlying (indirect) analysis for (g) SCC, and
1029 // - just the direct analysis for (h1,h2,h3) SCC.
1030 CGPM.addPass(
1031 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1032 LazyCallGraph &CG, CGSCCUpdateResult &) {
1033 auto &DoublyIndirectResult =
1034 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1035 auto &IndirectResult = DoublyIndirectResult.IDep;
1036 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1037 auto PA = PreservedAnalyses::none();
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001038 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1039 PA.preserveSet<AllAnalysesOn<Function>>();
Chandler Carruthba90ae92016-12-27 08:40:39 +00001040 if (C.getName() == "(g)")
1041 PA.preserve<TestSCCAnalysis>();
1042 else if (C.getName() == "(h3, h1, h2)")
1043 PA.preserve<TestIndirectSCCAnalysis>();
1044 return PA;
1045 }));
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001046 // Finally, use the analysis again on each SCC (and function), forcing
1047 // re-computation for all of them.
Chandler Carruthba90ae92016-12-27 08:40:39 +00001048 CGPM.addPass(
1049 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1050 LazyCallGraph &CG, CGSCCUpdateResult &) {
1051 auto &DoublyIndirectResult =
1052 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1053 auto &IndirectResult = DoublyIndirectResult.IDep;
1054 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1055 return PreservedAnalyses::all();
1056 }));
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001057 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1058 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
Chandler Carruthba90ae92016-12-27 08:40:39 +00001059
1060 // Create a second CGSCC pass manager. This will cause the module-level
1061 // invalidation to occur, which will force yet another invalidation of the
1062 // indirect SCC-level analysis as the module analysis it depends on gets
1063 // invalidated.
1064 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
1065 CGPM2.addPass(
1066 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1067 LazyCallGraph &CG, CGSCCUpdateResult &) {
1068 auto &DoublyIndirectResult =
1069 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1070 auto &IndirectResult = DoublyIndirectResult.IDep;
1071 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1072 return PreservedAnalyses::all();
1073 }));
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001074 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
1075 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
Chandler Carruthba90ae92016-12-27 08:40:39 +00001076
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001077 // Add a requires pass to populate the module analysis and then our CGSCC
Chandler Carruthba90ae92016-12-27 08:40:39 +00001078 // pass pipeline.
1079 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1080 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1081 // Now require the module analysis again (it will have been invalidated once)
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001082 // and then use it again from our second CGSCC pipeline..
Chandler Carruthba90ae92016-12-27 08:40:39 +00001083 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1084 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
1085 MPM.run(*M, MAM);
1086
1087 // There are generally two possible runs for each of the four SCCs. But
1088 // for one SCC, we only invalidate the indirect analysis so the base one
1089 // only gets run seven times.
1090 EXPECT_EQ(7, SCCAnalysisRuns);
1091 // The module analysis pass should be run twice here.
1092 EXPECT_EQ(2, ModuleAnalysisRuns);
1093 // The indirect analysis is invalidated (either directly or indirectly) three
1094 // times for each of four SCCs.
1095 EXPECT_EQ(3 * 4, IndirectSCCAnalysisRuns);
1096 EXPECT_EQ(3 * 4, DoublyIndirectSCCAnalysisRuns);
1097
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001098 // We run the indirect function analysis once per function the first time.
1099 // Then we re-run it for every SCC but "(g)". Then we re-run it for every
1100 // function again.
1101 EXPECT_EQ(6 + 5 + 6, IndirectFunctionAnalysisRuns);
1102
Chandler Carruthba90ae92016-12-27 08:40:39 +00001103 // Four passes count each of six functions once (via SCCs).
1104 EXPECT_EQ(4 * 6, FunctionCount);
1105}
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001106
1107TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) {
1108 int ModuleAnalysisRuns = 0;
1109 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
1110
1111 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
1112 DoublyIndirectSCCAnalysisRuns = 0;
1113 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
1114 CGAM.registerPass(
1115 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
1116 CGAM.registerPass([&] {
1117 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
1118 });
1119
1120 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
1121 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
1122 FAM.registerPass([&] {
1123 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
1124 });
1125
1126 ModulePassManager MPM(/*DebugLogging*/ true);
1127
1128 CGSCCPassManager CGPM(/*DebugLogging*/ true);
1129 // First just use the analysis to get the function count and preserve
1130 // everything.
1131 using RequireTestIndirectFunctionAnalysisPass =
1132 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>;
1133 using RequireTestDoublyIndirectSCCAnalysisPass =
1134 RequireAnalysisPass<TestDoublyIndirectSCCAnalysis, LazyCallGraph::SCC,
1135 CGSCCAnalysisManager, LazyCallGraph &,
1136 CGSCCUpdateResult &>;
1137 CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1138 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1139 RequireTestIndirectFunctionAnalysisPass()));
1140
1141 // Next, we inject an SCC pass that invalidates everything for the `(h3, h1,
1142 // h2)` SCC but also deletes the call edge from `h2` to `h3` and updates the
1143 // CG. This should successfully invalidate (and force to be re-run) all the
1144 // analyses for that SCC and for the functions.
1145 CGPM.addPass(
1146 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1147 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1148 (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1149 if (C.getName() != "(h3, h1, h2)")
1150 return PreservedAnalyses::all();
1151
1152 // Build the preserved set.
1153 auto PA = PreservedAnalyses::none();
1154 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1155 PA.preserve<TestIndirectSCCAnalysis>();
1156 PA.preserve<TestDoublyIndirectSCCAnalysis>();
1157
1158 // Delete the call from `h2` to `h3`.
1159 auto &H2N = *llvm::find_if(
1160 C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
1161 auto &H2F = H2N.getFunction();
1162 auto &H3F = *cast<CallInst>(H2F.begin()->begin())->getCalledFunction();
1163 assert(H3F.getName() == "h3" && "Wrong called function!");
1164 H2F.begin()->begin()->eraseFromParent();
1165 // Insert a bitcast of `h3` so that we retain a ref edge to it.
1166 (void)CastInst::CreatePointerCast(&H3F,
1167 Type::getInt8PtrTy(H2F.getContext()),
1168 "dummy", &*H2F.begin()->begin());
1169
1170 // Now update the call graph.
1171 auto &NewC = updateCGAndAnalysisManagerForFunctionPass(
1172 CG, C, H2N, AM, UR, /*DebugLogging*/ true);
1173 assert(&NewC != &C && "Should get a new SCC due to update!");
NAKAMURA Takumi3733fc42017-07-09 23:06:05 +00001174 (void)&NewC;
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001175
1176 return PA;
1177 }));
1178 // Now use the analysis again on each SCC and function, forcing
1179 // re-computation for all of them.
1180 CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1181 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1182 RequireTestIndirectFunctionAnalysisPass()));
1183
1184 // Create another CGSCC pipeline that requires all the analyses again.
1185 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
1186 CGPM2.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1187 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
1188 RequireTestIndirectFunctionAnalysisPass()));
1189
1190 // Next we inject an SCC pass that finds the `(h2)` SCC, adds a call to `h3`
1191 // back to `h2`, and then invalidates everything for what will then be the
1192 // `(h3, h1, h2)` SCC again.
1193 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
1194 CGPM3.addPass(
1195 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1196 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1197 (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1198 if (C.getName() != "(h2)")
1199 return PreservedAnalyses::all();
1200
1201 // Build the preserved set.
1202 auto PA = PreservedAnalyses::none();
1203 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1204 PA.preserve<TestIndirectSCCAnalysis>();
1205 PA.preserve<TestDoublyIndirectSCCAnalysis>();
1206
1207 // Delete the bitcast of `h3` that we added earlier.
1208 auto &H2N = *C.begin();
1209 auto &H2F = H2N.getFunction();
1210 auto &H3F = *cast<Function>(cast<BitCastInst>(H2F.begin()->begin())->getOperand(0));
1211 assert(H3F.getName() == "h3" && "Wrong called function!");
1212 H2F.begin()->begin()->eraseFromParent();
1213 // And insert a call to `h3`.
1214 (void)CallInst::Create(&H3F, {}, "", &*H2F.begin()->begin());
1215
1216 // Now update the call graph.
1217 auto &NewC = updateCGAndAnalysisManagerForFunctionPass(
1218 CG, C, H2N, AM, UR, /*DebugLogging*/ true);
1219 assert(&NewC != &C && "Should get a new SCC due to update!");
NAKAMURA Takumi3733fc42017-07-09 23:06:05 +00001220 (void)&NewC;
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001221
1222 return PA;
1223 }));
1224 // Now use the analysis again on each SCC and function, forcing
1225 // re-computation for all of them.
1226 CGPM3.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1227 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(
1228 RequireTestIndirectFunctionAnalysisPass()));
1229
1230 // Create a second CGSCC pass manager. This will cause the module-level
1231 // invalidation to occur, which will force yet another invalidation of the
1232 // indirect SCC-level analysis as the module analysis it depends on gets
1233 // invalidated.
1234 CGSCCPassManager CGPM4(/*DebugLogging*/ true);
1235 CGPM4.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1236 CGPM4.addPass(createCGSCCToFunctionPassAdaptor(
1237 RequireTestIndirectFunctionAnalysisPass()));
1238
1239 // Add a requires pass to populate the module analysis and then one of our
1240 // CGSCC pipelines. Repeat for all four CGSCC pipelines.
1241 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1242 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1243 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1244 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
1245 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1246 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
1247 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1248 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM4)));
1249 MPM.run(*M, MAM);
1250
1251 // We run over four SCCs the first time. But then we split an SCC into three.
1252 // And then we merge those three back into one.
1253 EXPECT_EQ(4 + 3 + 1, SCCAnalysisRuns);
1254 // The module analysis pass should be run three times.
1255 EXPECT_EQ(3, ModuleAnalysisRuns);
1256 // We run over four SCCs the first time. Then over the two new ones. Then the
1257 // entire module is invalidated causing a full run over all seven. Then we
1258 // fold three SCCs back to one, and then run over the whole module again.
1259 EXPECT_EQ(4 + 2 + 7 + 1 + 4, IndirectSCCAnalysisRuns);
1260 EXPECT_EQ(4 + 2 + 7 + 1 + 4, DoublyIndirectSCCAnalysisRuns);
1261
1262 // First we run over all six functions. Then we re-run it over three when we
1263 // split their SCCs. Then we re-run over the whole module. Then we re-run
1264 // over three functions merged back into a single SCC, and then over the
1265 // whole module again.
Chandler Carruth051bdb02017-07-12 09:08:11 +00001266 EXPECT_EQ(6 + 3 + 6 + 3 + 6, FunctionAnalysisRuns);
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001267
Chandler Carruth051bdb02017-07-12 09:08:11 +00001268 // Re run the function analysis over the entire module, and then re-run it
1269 // over the `(h3, h1, h2)` SCC due to invalidation. Then we re-run it over
1270 // the entire module, then the three functions merged back into a single SCC,
1271 // and then over the whole module.
1272 EXPECT_EQ(6 + 3 + 6 + 3 + 6, IndirectFunctionAnalysisRuns);
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001273}
Chandler Carruth74319922016-02-23 10:02:02 +00001274}