blob: f1ed35d72bd65a55233eae864bed0ea3a97b6af8 [file] [log] [blame]
Chandler Carruth74319922016-02-23 10:02:02 +00001//===- CGSCCPassManagerTest.cpp -------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Chandler Carruth74319922016-02-23 10:02:02 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/Analysis/CGSCCPassManager.h"
10#include "llvm/Analysis/LazyCallGraph.h"
Chandler Carruthf59a8382017-07-15 08:08:19 +000011#include "llvm/Analysis/TargetLibraryInfo.h"
Chandler Carruth74319922016-02-23 10:02:02 +000012#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 Carruthf59a8382017-07-15 08:08:19 +0000230 MAM.registerPass([&] { return TargetLibraryAnalysis(); });
Chandler Carruthdc288a82016-09-26 06:29:21 +0000231 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
232 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
Fedor Sergeevee8d31c2018-09-20 17:08:45 +0000233
234 // Register required pass instrumentation analysis.
235 MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
236 CGAM.registerPass([&] { return PassInstrumentationAnalysis(); });
237 FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
238
239 // Cross-register proxies.
Chandler Carruthdc288a82016-09-26 06:29:21 +0000240 MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
Chandler Carruth6b981642016-12-10 06:34:44 +0000241 CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); });
Chandler Carruthdc288a82016-09-26 06:29:21 +0000242 CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
243 FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
244 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
245 }
Chandler Carruth4f837422016-09-02 01:14:05 +0000246};
247
248TEST_F(CGSCCPassManagerTest, Basic) {
Chandler Carruth74319922016-02-23 10:02:02 +0000249 int FunctionAnalysisRuns = 0;
250 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000251 int ImmutableFunctionAnalysisRuns = 0;
252 FAM.registerPass([&] {
253 return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns);
254 });
Chandler Carruth74319922016-02-23 10:02:02 +0000255
Chandler Carruth74319922016-02-23 10:02:02 +0000256 int SCCAnalysisRuns = 0;
257 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
258
Chandler Carruth74319922016-02-23 10:02:02 +0000259 int ModuleAnalysisRuns = 0;
Chandler Carruth74319922016-02-23 10:02:02 +0000260 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
261
Chandler Carruth74319922016-02-23 10:02:02 +0000262 ModulePassManager MPM(/*DebugLogging*/ true);
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000263 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
Chandler Carruth74319922016-02-23 10:02:02 +0000264
265 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
Chandler Carruth6b981642016-12-10 06:34:44 +0000266 FunctionPassManager FPM1(/*DebugLogging*/ true);
267 int FunctionPassRunCount1 = 0;
268 FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
269 ++FunctionPassRunCount1;
270 return PreservedAnalyses::none();
271 }));
272 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
273
Chandler Carruth74319922016-02-23 10:02:02 +0000274 int SCCPassRunCount1 = 0;
275 int AnalyzedInstrCount1 = 0;
276 int AnalyzedSCCFunctionCount1 = 0;
277 int AnalyzedModuleFunctionCount1 = 0;
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000278 CGPM1.addPass(
279 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
280 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
281 ++SCCPassRunCount1;
282
283 const ModuleAnalysisManager &MAM =
284 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
285 FunctionAnalysisManager &FAM =
286 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
287 if (TestModuleAnalysis::Result *TMA =
288 MAM.getCachedResult<TestModuleAnalysis>(
289 *C.begin()->getFunction().getParent()))
290 AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
291
292 TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
293 AnalyzedSCCFunctionCount1 += AR.FunctionCount;
294 for (LazyCallGraph::Node &N : C) {
295 TestFunctionAnalysis::Result &FAR =
296 FAM.getResult<TestFunctionAnalysis>(N.getFunction());
297 AnalyzedInstrCount1 += FAR.InstructionCount;
298
299 // Just ensure we get the immutable results.
300 (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction());
301 }
302
303 return PreservedAnalyses::all();
304 }));
Chandler Carruth74319922016-02-23 10:02:02 +0000305
Chandler Carruth6b981642016-12-10 06:34:44 +0000306 FunctionPassManager FPM2(/*DebugLogging*/ true);
307 int FunctionPassRunCount2 = 0;
308 FPM2.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
309 ++FunctionPassRunCount2;
310 return PreservedAnalyses::none();
Chandler Carruthd4e80a92016-09-02 01:08:04 +0000311 }));
Chandler Carruth6b981642016-12-10 06:34:44 +0000312 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
313
Chandler Carruth74319922016-02-23 10:02:02 +0000314 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
315
Chandler Carruth6b981642016-12-10 06:34:44 +0000316 FunctionPassManager FPM3(/*DebugLogging*/ true);
317 int FunctionPassRunCount3 = 0;
318 FPM3.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
319 ++FunctionPassRunCount3;
320 return PreservedAnalyses::none();
321 }));
322 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM3)));
323
Chandler Carruthb47f8012016-03-11 11:05:24 +0000324 MPM.run(*M, MAM);
Chandler Carruth74319922016-02-23 10:02:02 +0000325
Chandler Carruth6b981642016-12-10 06:34:44 +0000326 EXPECT_EQ(4, SCCPassRunCount1);
327 EXPECT_EQ(6, FunctionPassRunCount1);
328 EXPECT_EQ(6, FunctionPassRunCount2);
329 EXPECT_EQ(6, FunctionPassRunCount3);
330
Chandler Carruth74319922016-02-23 10:02:02 +0000331 EXPECT_EQ(1, ModuleAnalysisRuns);
332 EXPECT_EQ(4, SCCAnalysisRuns);
333 EXPECT_EQ(6, FunctionAnalysisRuns);
Chandler Carruthc5d211e2016-02-23 10:47:57 +0000334 EXPECT_EQ(6, ImmutableFunctionAnalysisRuns);
Chandler Carruth74319922016-02-23 10:02:02 +0000335
Chandler Carruth74319922016-02-23 10:02:02 +0000336 EXPECT_EQ(14, AnalyzedInstrCount1);
337 EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
338 EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
339}
340
Chandler Carruthb52b5732016-09-26 04:01:55 +0000341// Test that an SCC pass which fails to preserve a module analysis does in fact
342// invalidate that module analysis.
343TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
Chandler Carruthb52b5732016-09-26 04:01:55 +0000344 int ModuleAnalysisRuns = 0;
345 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
346
347 ModulePassManager MPM(/*DebugLogging*/ true);
348 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
349
350 // The first CGSCC run we preserve everything and make sure that works and
351 // the module analysis is available in the second CGSCC run from the one
352 // required module pass above.
353 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
354 int CountFoundModuleAnalysis1 = 0;
355 CGPM1.addPass(
356 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
357 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
358 const auto &MAM =
359 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
360 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
361 *C.begin()->getFunction().getParent());
362
363 if (TMA)
364 ++CountFoundModuleAnalysis1;
365
366 return PreservedAnalyses::all();
367 }));
368 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
369
370 // The second CGSCC run checks that the module analysis got preserved the
371 // previous time and in one SCC fails to preserve it.
372 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
373 int CountFoundModuleAnalysis2 = 0;
374 CGPM2.addPass(
375 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
376 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
377 const auto &MAM =
378 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
379 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
380 *C.begin()->getFunction().getParent());
381
382 if (TMA)
383 ++CountFoundModuleAnalysis2;
384
385 // Only fail to preserve analyses on one SCC and make sure that gets
386 // propagated.
387 return C.getName() == "(g)" ? PreservedAnalyses::none()
388 : PreservedAnalyses::all();
389 }));
390 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
391
392 // The third CGSCC run should fail to find a cached module analysis as it
393 // should have been invalidated by the above CGSCC run.
394 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
395 int CountFoundModuleAnalysis3 = 0;
396 CGPM3.addPass(
397 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
398 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
399 const auto &MAM =
400 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
401 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
402 *C.begin()->getFunction().getParent());
403
404 if (TMA)
405 ++CountFoundModuleAnalysis3;
406
407 return PreservedAnalyses::none();
408 }));
409 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
410
411 MPM.run(*M, MAM);
412
413 EXPECT_EQ(1, ModuleAnalysisRuns);
414 EXPECT_EQ(4, CountFoundModuleAnalysis1);
415 EXPECT_EQ(4, CountFoundModuleAnalysis2);
416 EXPECT_EQ(0, CountFoundModuleAnalysis3);
417}
418
Chandler Carruthe35f84a2016-09-26 04:17:12 +0000419// Similar to the above, but test that this works for function passes embedded
420// *within* a CGSCC layer.
421TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) {
Chandler Carruthe35f84a2016-09-26 04:17:12 +0000422 int ModuleAnalysisRuns = 0;
423 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
424
425 ModulePassManager MPM(/*DebugLogging*/ true);
426 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
427
428 // The first run we preserve everything and make sure that works and the
429 // module analysis is available in the second run from the one required
430 // module pass above.
431 FunctionPassManager FPM1(/*DebugLogging*/ true);
432 // Start true and mark false if we ever failed to find a module analysis
433 // because we expect this to succeed for each SCC.
434 bool FoundModuleAnalysis1 = true;
435 FPM1.addPass(
436 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
437 const auto &MAM =
438 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
439 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
440
441 if (!TMA)
442 FoundModuleAnalysis1 = false;
443
444 return PreservedAnalyses::all();
445 }));
446 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
447 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
448 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
449
450 // The second run checks that the module analysis got preserved the previous
451 // time and in one function fails to preserve it.
452 FunctionPassManager FPM2(/*DebugLogging*/ true);
453 // Again, start true and mark false if we ever failed to find a module analysis
454 // because we expect this to succeed for each SCC.
455 bool FoundModuleAnalysis2 = true;
456 FPM2.addPass(
457 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
458 const auto &MAM =
459 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
460 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
461
462 if (!TMA)
463 FoundModuleAnalysis2 = false;
464
465 // Only fail to preserve analyses on one SCC and make sure that gets
466 // propagated.
467 return F.getName() == "h2" ? PreservedAnalyses::none()
468 : PreservedAnalyses::all();
469 }));
470 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
471 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
472 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
473
474 // The third run should fail to find a cached module analysis as it should
475 // have been invalidated by the above run.
476 FunctionPassManager FPM3(/*DebugLogging*/ true);
477 // Start false and mark true if we ever *succeeded* to find a module
478 // analysis, as we expect this to fail for every function.
479 bool FoundModuleAnalysis3 = false;
480 FPM3.addPass(
481 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
482 const auto &MAM =
483 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
484 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
485
486 if (TMA)
487 FoundModuleAnalysis3 = true;
488
489 return PreservedAnalyses::none();
490 }));
491 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
492 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3)));
493 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
494
495 MPM.run(*M, MAM);
496
497 EXPECT_EQ(1, ModuleAnalysisRuns);
498 EXPECT_TRUE(FoundModuleAnalysis1);
499 EXPECT_TRUE(FoundModuleAnalysis2);
500 EXPECT_FALSE(FoundModuleAnalysis3);
501}
502
Chandler Carruth6b981642016-12-10 06:34:44 +0000503// Test that a Module pass which fails to preserve an SCC analysis in fact
504// invalidates that analysis.
505TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysis) {
506 int SCCAnalysisRuns = 0;
507 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
508
509 ModulePassManager MPM(/*DebugLogging*/ true);
510
511 // First force the analysis to be run.
512 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
513 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
514 CGSCCAnalysisManager, LazyCallGraph &,
515 CGSCCUpdateResult &>());
516 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
517
518 // Now run a module pass that preserves the LazyCallGraph and the proxy but
519 // not the SCC analysis.
520 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
521 PreservedAnalyses PA;
522 PA.preserve<LazyCallGraphAnalysis>();
523 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
524 PA.preserve<FunctionAnalysisManagerModuleProxy>();
525 return PA;
526 }));
527
528 // And now a second CGSCC run which requires the SCC analysis again. This
529 // will trigger re-running it.
530 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
531 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
532 CGSCCAnalysisManager, LazyCallGraph &,
533 CGSCCUpdateResult &>());
534 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
535
536 MPM.run(*M, MAM);
537 // Two runs and four SCCs.
538 EXPECT_EQ(2 * 4, SCCAnalysisRuns);
539}
540
541// Check that marking the SCC analysis preserved is sufficient to avoid
542// invaliadtion. This should only run the analysis once for each SCC.
543TEST_F(CGSCCPassManagerTest, TestModulePassCanPreserveSCCAnalysis) {
544 int SCCAnalysisRuns = 0;
545 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
546
547 ModulePassManager MPM(/*DebugLogging*/ true);
548
549 // First force the analysis to be run.
550 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
551 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
552 CGSCCAnalysisManager, LazyCallGraph &,
553 CGSCCUpdateResult &>());
554 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
555
556 // Now run a module pass that preserves each of the necessary components
557 // (but not everything).
558 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
559 PreservedAnalyses PA;
560 PA.preserve<LazyCallGraphAnalysis>();
561 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
562 PA.preserve<FunctionAnalysisManagerModuleProxy>();
563 PA.preserve<TestSCCAnalysis>();
564 return PA;
565 }));
566
567 // And now a second CGSCC run which requires the SCC analysis again but find
568 // it in the cache.
569 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
570 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
571 CGSCCAnalysisManager, LazyCallGraph &,
572 CGSCCUpdateResult &>());
573 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
574
575 MPM.run(*M, MAM);
576 // Four SCCs
577 EXPECT_EQ(4, SCCAnalysisRuns);
578}
579
580// Check that even when the analysis is preserved, if the SCC information isn't
581// we still nuke things because the SCC keys could change.
582TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysisOnCGChange) {
583 int SCCAnalysisRuns = 0;
584 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
585
586 ModulePassManager MPM(/*DebugLogging*/ true);
587
588 // First force the analysis to be run.
589 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
590 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
591 CGSCCAnalysisManager, LazyCallGraph &,
592 CGSCCUpdateResult &>());
593 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
594
595 // Now run a module pass that preserves the analysis but not the call
596 // graph or proxy.
597 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
598 PreservedAnalyses PA;
599 PA.preserve<TestSCCAnalysis>();
600 return PA;
601 }));
602
603 // And now a second CGSCC run which requires the SCC analysis again.
604 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
605 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
606 CGSCCAnalysisManager, LazyCallGraph &,
607 CGSCCUpdateResult &>());
608 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
609
610 MPM.run(*M, MAM);
611 // Two runs and four SCCs.
612 EXPECT_EQ(2 * 4, SCCAnalysisRuns);
613}
614
615// Test that an SCC pass which fails to preserve a Function analysis in fact
616// invalidates that analysis.
617TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesFunctionAnalysis) {
618 int FunctionAnalysisRuns = 0;
619 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
620
621 // Create a very simple module with a single function and SCC to make testing
622 // these issues much easier.
623 std::unique_ptr<Module> M = parseIR("declare void @g()\n"
624 "declare void @h()\n"
625 "define void @f() {\n"
626 "entry:\n"
627 " call void @g()\n"
628 " call void @h()\n"
629 " ret void\n"
630 "}\n");
631
632 CGSCCPassManager CGPM(/*DebugLogging*/ true);
633
634 // First force the analysis to be run.
635 FunctionPassManager FPM1(/*DebugLogging*/ true);
636 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
637 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
638
639 // Now run a module pass that preserves the LazyCallGraph and proxy but not
640 // the SCC analysis.
641 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
642 LazyCallGraph &, CGSCCUpdateResult &) {
643 PreservedAnalyses PA;
644 PA.preserve<LazyCallGraphAnalysis>();
645 return PA;
646 }));
647
648 // And now a second CGSCC run which requires the SCC analysis again. This
649 // will trigger re-running it.
650 FunctionPassManager FPM2(/*DebugLogging*/ true);
651 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
652 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
653
654 ModulePassManager MPM(/*DebugLogging*/ true);
655 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
656 MPM.run(*M, MAM);
657 EXPECT_EQ(2, FunctionAnalysisRuns);
658}
659
660// Check that marking the SCC analysis preserved is sufficient. This should
661// only run the analysis once the SCC.
662TEST_F(CGSCCPassManagerTest, TestSCCPassCanPreserveFunctionAnalysis) {
663 int FunctionAnalysisRuns = 0;
664 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
665
666 // Create a very simple module with a single function and SCC to make testing
667 // these issues much easier.
668 std::unique_ptr<Module> M = parseIR("declare void @g()\n"
669 "declare void @h()\n"
670 "define void @f() {\n"
671 "entry:\n"
672 " call void @g()\n"
673 " call void @h()\n"
674 " ret void\n"
675 "}\n");
676
677 CGSCCPassManager CGPM(/*DebugLogging*/ true);
678
679 // First force the analysis to be run.
680 FunctionPassManager FPM1(/*DebugLogging*/ true);
681 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
682 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
683
684 // Now run a module pass that preserves each of the necessary components
685 // (but
686 // not everything).
687 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
688 LazyCallGraph &, CGSCCUpdateResult &) {
689 PreservedAnalyses PA;
690 PA.preserve<LazyCallGraphAnalysis>();
Chandler Carruthbd9c2902017-07-09 03:59:31 +0000691 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
Chandler Carruth6b981642016-12-10 06:34:44 +0000692 PA.preserve<TestFunctionAnalysis>();
693 return PA;
694 }));
695
696 // And now a second CGSCC run which requires the SCC analysis again but find
697 // it in the cache.
698 FunctionPassManager FPM2(/*DebugLogging*/ true);
699 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
700 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
701
702 ModulePassManager MPM(/*DebugLogging*/ true);
703 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
704 MPM.run(*M, MAM);
705 EXPECT_EQ(1, FunctionAnalysisRuns);
706}
707
708// Note that there is no test for invalidating the call graph or other
709// structure with an SCC pass because there is no mechanism to do that from
710// withinsuch a pass. Instead, such a pass has to directly update the call
711// graph structure.
712
713// Test that a madule pass invalidates function analyses when the CGSCC proxies
714// and pass manager.
715TEST_F(CGSCCPassManagerTest,
716 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC) {
717 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
718
719 int FunctionAnalysisRuns = 0;
720 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
721
722 ModulePassManager MPM(/*DebugLogging*/ true);
723
724 // First force the analysis to be run.
725 FunctionPassManager FPM1(/*DebugLogging*/ true);
726 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
727 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
728 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
729 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
730
Chandler Carruthbd9c2902017-07-09 03:59:31 +0000731 // Now run a module pass that preserves the LazyCallGraph and proxies but not
Chandler Carruth6b981642016-12-10 06:34:44 +0000732 // the Function analysis.
733 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
734 PreservedAnalyses PA;
735 PA.preserve<LazyCallGraphAnalysis>();
736 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
Chandler Carruthbd9c2902017-07-09 03:59:31 +0000737 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
738 PA.preserve<FunctionAnalysisManagerModuleProxy>();
Chandler Carruth6b981642016-12-10 06:34:44 +0000739 return PA;
740 }));
741
742 // And now a second CGSCC run which requires the SCC analysis again. This
743 // will trigger re-running it.
744 FunctionPassManager FPM2(/*DebugLogging*/ true);
745 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
746 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
747 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
748 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
749
750 MPM.run(*M, MAM);
751 // Two runs and 6 functions.
752 EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
753}
754
Chandler Carruthbd9c2902017-07-09 03:59:31 +0000755// Check that by marking the function pass and proxies as preserved, this
Chandler Carruth6b981642016-12-10 06:34:44 +0000756// propagates all the way through.
757TEST_F(CGSCCPassManagerTest,
758 TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC) {
759 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
760
761 int FunctionAnalysisRuns = 0;
762 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
763
764 ModulePassManager MPM(/*DebugLogging*/ true);
765
766 // First force the analysis to be run.
767 FunctionPassManager FPM1(/*DebugLogging*/ true);
768 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
769 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
770 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
771 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
772
773 // Now run a module pass that preserves the LazyCallGraph, the proxy, and
774 // the Function analysis.
775 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
776 PreservedAnalyses PA;
777 PA.preserve<LazyCallGraphAnalysis>();
778 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
Chandler Carruthbd9c2902017-07-09 03:59:31 +0000779 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
Chandler Carruth6b981642016-12-10 06:34:44 +0000780 PA.preserve<FunctionAnalysisManagerModuleProxy>();
781 PA.preserve<TestFunctionAnalysis>();
782 return PA;
783 }));
784
785 // And now a second CGSCC run which requires the SCC analysis again. This
786 // will trigger re-running it.
787 FunctionPassManager FPM2(/*DebugLogging*/ true);
788 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
789 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
790 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
791 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
792
793 MPM.run(*M, MAM);
794 // One run and 6 functions.
795 EXPECT_EQ(6, FunctionAnalysisRuns);
796}
797
798// Check that if the lazy call graph itself isn't preserved we still manage to
799// invalidate everything.
800TEST_F(CGSCCPassManagerTest,
801 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange) {
802 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
803
804 int FunctionAnalysisRuns = 0;
805 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
806
807 ModulePassManager MPM(/*DebugLogging*/ true);
808
809 // First force the analysis to be run.
810 FunctionPassManager FPM1(/*DebugLogging*/ true);
811 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
812 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
813 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
814 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
815
816 // Now run a module pass that preserves the LazyCallGraph but not the
817 // Function analysis.
818 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
819 PreservedAnalyses PA;
820 return PA;
821 }));
822
823 // And now a second CGSCC run which requires the SCC analysis again. This
824 // will trigger re-running it.
825 FunctionPassManager FPM2(/*DebugLogging*/ true);
826 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
827 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
828 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
829 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
830
831 MPM.run(*M, MAM);
832 // Two runs and 6 functions.
833 EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
834}
Chandler Carruthba90ae92016-12-27 08:40:39 +0000835
836/// A test CGSCC-level analysis pass which caches in its result another
837/// analysis pass and uses it to serve queries. This requires the result to
838/// invalidate itself when its dependency is invalidated.
839///
840/// FIXME: Currently this doesn't also depend on a function analysis, and if it
841/// did we would fail to invalidate it correctly.
842struct TestIndirectSCCAnalysis
843 : public AnalysisInfoMixin<TestIndirectSCCAnalysis> {
844 struct Result {
845 Result(TestSCCAnalysis::Result &SCCDep, TestModuleAnalysis::Result &MDep)
846 : SCCDep(SCCDep), MDep(MDep) {}
847 TestSCCAnalysis::Result &SCCDep;
848 TestModuleAnalysis::Result &MDep;
849
850 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
851 CGSCCAnalysisManager::Invalidator &Inv) {
852 auto PAC = PA.getChecker<TestIndirectSCCAnalysis>();
853 return !(PAC.preserved() ||
854 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
855 Inv.invalidate<TestSCCAnalysis>(C, PA);
856 }
857 };
858
859 TestIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
860
861 /// Run the analysis pass over the function and return a result.
862 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
863 LazyCallGraph &CG) {
864 ++Runs;
865 auto &SCCDep = AM.getResult<TestSCCAnalysis>(C, CG);
866
867 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
868 const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
869 // For the test, we insist that the module analysis starts off in the
870 // cache.
871 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(
872 *C.begin()->getFunction().getParent());
873 // Register the dependency as module analysis dependencies have to be
874 // pre-registered on the proxy.
875 ModuleProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
876 TestIndirectSCCAnalysis>();
877
878 return Result(SCCDep, MDep);
879 }
880
881private:
882 friend AnalysisInfoMixin<TestIndirectSCCAnalysis>;
883 static AnalysisKey Key;
884
885 int &Runs;
886};
887
888AnalysisKey TestIndirectSCCAnalysis::Key;
889
890/// A test analysis pass which caches in its result the result from the above
891/// indirect analysis pass.
892///
893/// This allows us to ensure that whenever an analysis pass is invalidated due
894/// to dependencies (especially dependencies across IR units that trigger
895/// asynchronous invalidation) we correctly detect that this may in turn cause
896/// other analysis to be invalidated.
897struct TestDoublyIndirectSCCAnalysis
898 : public AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis> {
899 struct Result {
900 Result(TestIndirectSCCAnalysis::Result &IDep) : IDep(IDep) {}
901 TestIndirectSCCAnalysis::Result &IDep;
902
903 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
904 CGSCCAnalysisManager::Invalidator &Inv) {
905 auto PAC = PA.getChecker<TestDoublyIndirectSCCAnalysis>();
906 return !(PAC.preserved() ||
907 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
908 Inv.invalidate<TestIndirectSCCAnalysis>(C, PA);
909 }
910 };
911
912 TestDoublyIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
913
914 /// Run the analysis pass over the function and return a result.
915 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
916 LazyCallGraph &CG) {
917 ++Runs;
918 auto &IDep = AM.getResult<TestIndirectSCCAnalysis>(C, CG);
919 return Result(IDep);
920 }
921
922private:
923 friend AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis>;
924 static AnalysisKey Key;
925
926 int &Runs;
927};
928
929AnalysisKey TestDoublyIndirectSCCAnalysis::Key;
930
931/// A test analysis pass which caches results from three different IR unit
932/// layers and requires intermediate layers to correctly propagate the entire
933/// distance.
934struct TestIndirectFunctionAnalysis
935 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
936 struct Result {
937 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep,
938 TestSCCAnalysis::Result &SCCDep)
939 : FDep(FDep), MDep(MDep), SCCDep(SCCDep) {}
940 TestFunctionAnalysis::Result &FDep;
941 TestModuleAnalysis::Result &MDep;
942 TestSCCAnalysis::Result &SCCDep;
943
944 bool invalidate(Function &F, const PreservedAnalyses &PA,
945 FunctionAnalysisManager::Invalidator &Inv) {
946 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
947 return !(PAC.preserved() ||
948 PAC.preservedSet<AllAnalysesOn<Function>>()) ||
949 Inv.invalidate<TestFunctionAnalysis>(F, PA);
950 }
951 };
952
953 TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
954
955 /// Run the analysis pass over the function and return a result.
956 Result run(Function &F, FunctionAnalysisManager &AM) {
957 ++Runs;
958 auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
959
960 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
961 const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
962 // For the test, we insist that the module analysis starts off in the
963 // cache.
964 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
965 // Register the dependency as module analysis dependencies have to be
966 // pre-registered on the proxy.
967 ModuleProxy.registerOuterAnalysisInvalidation<
968 TestModuleAnalysis, TestIndirectFunctionAnalysis>();
969
970 // For thet test we assume this is run inside a CGSCC pass manager.
971 const LazyCallGraph &CG =
972 *MAM.getCachedResult<LazyCallGraphAnalysis>(*F.getParent());
973 auto &CGSCCProxy = AM.getResult<CGSCCAnalysisManagerFunctionProxy>(F);
974 const CGSCCAnalysisManager &CGAM = CGSCCProxy.getManager();
975 // For the test, we insist that the CGSCC analysis starts off in the cache.
976 auto &SCCDep =
977 *CGAM.getCachedResult<TestSCCAnalysis>(*CG.lookupSCC(*CG.lookup(F)));
978 // Register the dependency as CGSCC analysis dependencies have to be
979 // pre-registered on the proxy.
980 CGSCCProxy.registerOuterAnalysisInvalidation<
981 TestSCCAnalysis, TestIndirectFunctionAnalysis>();
982
983 return Result(FDep, MDep, SCCDep);
984 }
985
986private:
987 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
988 static AnalysisKey Key;
989
990 int &Runs;
991};
992
993AnalysisKey TestIndirectFunctionAnalysis::Key;
994
995TEST_F(CGSCCPassManagerTest, TestIndirectAnalysisInvalidation) {
996 int ModuleAnalysisRuns = 0;
997 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
998
999 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
1000 DoublyIndirectSCCAnalysisRuns = 0;
1001 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
1002 CGAM.registerPass(
1003 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
1004 CGAM.registerPass([&] {
1005 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
1006 });
1007
1008 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
1009 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
1010 FAM.registerPass([&] {
1011 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
1012 });
1013
1014 ModulePassManager MPM(/*DebugLogging*/ true);
1015
1016 int FunctionCount = 0;
1017 CGSCCPassManager CGPM(/*DebugLogging*/ true);
1018 // First just use the analysis to get the function count and preserve
1019 // everything.
1020 CGPM.addPass(
1021 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1022 LazyCallGraph &CG, CGSCCUpdateResult &) {
1023 auto &DoublyIndirectResult =
1024 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1025 auto &IndirectResult = DoublyIndirectResult.IDep;
1026 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1027 return PreservedAnalyses::all();
1028 }));
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001029 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1030 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1031
Chandler Carruthba90ae92016-12-27 08:40:39 +00001032 // Next, invalidate
1033 // - both analyses for the (f) and (x) SCCs,
1034 // - just the underlying (indirect) analysis for (g) SCC, and
1035 // - just the direct analysis for (h1,h2,h3) SCC.
1036 CGPM.addPass(
1037 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1038 LazyCallGraph &CG, CGSCCUpdateResult &) {
1039 auto &DoublyIndirectResult =
1040 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1041 auto &IndirectResult = DoublyIndirectResult.IDep;
1042 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1043 auto PA = PreservedAnalyses::none();
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001044 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1045 PA.preserveSet<AllAnalysesOn<Function>>();
Chandler Carruthba90ae92016-12-27 08:40:39 +00001046 if (C.getName() == "(g)")
1047 PA.preserve<TestSCCAnalysis>();
1048 else if (C.getName() == "(h3, h1, h2)")
1049 PA.preserve<TestIndirectSCCAnalysis>();
1050 return PA;
1051 }));
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001052 // Finally, use the analysis again on each SCC (and function), forcing
1053 // re-computation for all of them.
Chandler Carruthba90ae92016-12-27 08:40:39 +00001054 CGPM.addPass(
1055 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1056 LazyCallGraph &CG, CGSCCUpdateResult &) {
1057 auto &DoublyIndirectResult =
1058 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1059 auto &IndirectResult = DoublyIndirectResult.IDep;
1060 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1061 return PreservedAnalyses::all();
1062 }));
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001063 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1064 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
Chandler Carruthba90ae92016-12-27 08:40:39 +00001065
1066 // Create a second CGSCC pass manager. This will cause the module-level
1067 // invalidation to occur, which will force yet another invalidation of the
1068 // indirect SCC-level analysis as the module analysis it depends on gets
1069 // invalidated.
1070 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
1071 CGPM2.addPass(
1072 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1073 LazyCallGraph &CG, CGSCCUpdateResult &) {
1074 auto &DoublyIndirectResult =
1075 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1076 auto &IndirectResult = DoublyIndirectResult.IDep;
1077 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1078 return PreservedAnalyses::all();
1079 }));
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001080 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
1081 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
Chandler Carruthba90ae92016-12-27 08:40:39 +00001082
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001083 // Add a requires pass to populate the module analysis and then our CGSCC
Chandler Carruthba90ae92016-12-27 08:40:39 +00001084 // pass pipeline.
1085 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1086 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1087 // Now require the module analysis again (it will have been invalidated once)
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001088 // and then use it again from our second CGSCC pipeline..
Chandler Carruthba90ae92016-12-27 08:40:39 +00001089 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1090 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
1091 MPM.run(*M, MAM);
1092
1093 // There are generally two possible runs for each of the four SCCs. But
1094 // for one SCC, we only invalidate the indirect analysis so the base one
1095 // only gets run seven times.
1096 EXPECT_EQ(7, SCCAnalysisRuns);
1097 // The module analysis pass should be run twice here.
1098 EXPECT_EQ(2, ModuleAnalysisRuns);
1099 // The indirect analysis is invalidated (either directly or indirectly) three
1100 // times for each of four SCCs.
1101 EXPECT_EQ(3 * 4, IndirectSCCAnalysisRuns);
1102 EXPECT_EQ(3 * 4, DoublyIndirectSCCAnalysisRuns);
1103
Chandler Carruthbd9c2902017-07-09 03:59:31 +00001104 // We run the indirect function analysis once per function the first time.
1105 // Then we re-run it for every SCC but "(g)". Then we re-run it for every
1106 // function again.
1107 EXPECT_EQ(6 + 5 + 6, IndirectFunctionAnalysisRuns);
1108
Chandler Carruthba90ae92016-12-27 08:40:39 +00001109 // Four passes count each of six functions once (via SCCs).
1110 EXPECT_EQ(4 * 6, FunctionCount);
1111}
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001112
1113TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) {
1114 int ModuleAnalysisRuns = 0;
1115 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
1116
1117 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
1118 DoublyIndirectSCCAnalysisRuns = 0;
1119 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
1120 CGAM.registerPass(
1121 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
1122 CGAM.registerPass([&] {
1123 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
1124 });
1125
1126 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
1127 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
1128 FAM.registerPass([&] {
1129 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
1130 });
1131
1132 ModulePassManager MPM(/*DebugLogging*/ true);
1133
1134 CGSCCPassManager CGPM(/*DebugLogging*/ true);
1135 // First just use the analysis to get the function count and preserve
1136 // everything.
1137 using RequireTestIndirectFunctionAnalysisPass =
1138 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>;
1139 using RequireTestDoublyIndirectSCCAnalysisPass =
1140 RequireAnalysisPass<TestDoublyIndirectSCCAnalysis, LazyCallGraph::SCC,
1141 CGSCCAnalysisManager, LazyCallGraph &,
1142 CGSCCUpdateResult &>;
1143 CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1144 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1145 RequireTestIndirectFunctionAnalysisPass()));
1146
1147 // Next, we inject an SCC pass that invalidates everything for the `(h3, h1,
1148 // h2)` SCC but also deletes the call edge from `h2` to `h3` and updates the
1149 // CG. This should successfully invalidate (and force to be re-run) all the
1150 // analyses for that SCC and for the functions.
1151 CGPM.addPass(
1152 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1153 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1154 (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1155 if (C.getName() != "(h3, h1, h2)")
1156 return PreservedAnalyses::all();
1157
1158 // Build the preserved set.
1159 auto PA = PreservedAnalyses::none();
1160 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1161 PA.preserve<TestIndirectSCCAnalysis>();
1162 PA.preserve<TestDoublyIndirectSCCAnalysis>();
1163
1164 // Delete the call from `h2` to `h3`.
1165 auto &H2N = *llvm::find_if(
1166 C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
1167 auto &H2F = H2N.getFunction();
1168 auto &H3F = *cast<CallInst>(H2F.begin()->begin())->getCalledFunction();
1169 assert(H3F.getName() == "h3" && "Wrong called function!");
1170 H2F.begin()->begin()->eraseFromParent();
1171 // Insert a bitcast of `h3` so that we retain a ref edge to it.
1172 (void)CastInst::CreatePointerCast(&H3F,
1173 Type::getInt8PtrTy(H2F.getContext()),
1174 "dummy", &*H2F.begin()->begin());
1175
1176 // Now update the call graph.
Chandler Carruth19913b22017-08-11 05:47:13 +00001177 auto &NewC =
1178 updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR);
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001179 assert(&NewC != &C && "Should get a new SCC due to update!");
NAKAMURA Takumi3733fc42017-07-09 23:06:05 +00001180 (void)&NewC;
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001181
1182 return PA;
1183 }));
1184 // Now use the analysis again on each SCC and function, forcing
1185 // re-computation for all of them.
1186 CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1187 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1188 RequireTestIndirectFunctionAnalysisPass()));
1189
1190 // Create another CGSCC pipeline that requires all the analyses again.
1191 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
1192 CGPM2.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1193 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
1194 RequireTestIndirectFunctionAnalysisPass()));
1195
1196 // Next we inject an SCC pass that finds the `(h2)` SCC, adds a call to `h3`
1197 // back to `h2`, and then invalidates everything for what will then be the
1198 // `(h3, h1, h2)` SCC again.
1199 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
1200 CGPM3.addPass(
1201 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1202 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1203 (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1204 if (C.getName() != "(h2)")
1205 return PreservedAnalyses::all();
1206
1207 // Build the preserved set.
1208 auto PA = PreservedAnalyses::none();
1209 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1210 PA.preserve<TestIndirectSCCAnalysis>();
1211 PA.preserve<TestDoublyIndirectSCCAnalysis>();
1212
1213 // Delete the bitcast of `h3` that we added earlier.
1214 auto &H2N = *C.begin();
1215 auto &H2F = H2N.getFunction();
1216 auto &H3F = *cast<Function>(cast<BitCastInst>(H2F.begin()->begin())->getOperand(0));
1217 assert(H3F.getName() == "h3" && "Wrong called function!");
1218 H2F.begin()->begin()->eraseFromParent();
1219 // And insert a call to `h3`.
1220 (void)CallInst::Create(&H3F, {}, "", &*H2F.begin()->begin());
1221
1222 // Now update the call graph.
Chandler Carruth19913b22017-08-11 05:47:13 +00001223 auto &NewC =
1224 updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR);
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001225 assert(&NewC != &C && "Should get a new SCC due to update!");
NAKAMURA Takumi3733fc42017-07-09 23:06:05 +00001226 (void)&NewC;
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001227
1228 return PA;
1229 }));
1230 // Now use the analysis again on each SCC and function, forcing
1231 // re-computation for all of them.
1232 CGPM3.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1233 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(
1234 RequireTestIndirectFunctionAnalysisPass()));
1235
1236 // Create a second CGSCC pass manager. This will cause the module-level
1237 // invalidation to occur, which will force yet another invalidation of the
1238 // indirect SCC-level analysis as the module analysis it depends on gets
1239 // invalidated.
1240 CGSCCPassManager CGPM4(/*DebugLogging*/ true);
1241 CGPM4.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1242 CGPM4.addPass(createCGSCCToFunctionPassAdaptor(
1243 RequireTestIndirectFunctionAnalysisPass()));
1244
1245 // Add a requires pass to populate the module analysis and then one of our
1246 // CGSCC pipelines. Repeat for all four CGSCC pipelines.
1247 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1248 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1249 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1250 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
1251 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1252 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
1253 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1254 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM4)));
1255 MPM.run(*M, MAM);
1256
1257 // We run over four SCCs the first time. But then we split an SCC into three.
Chandler Carruth923ff552019-03-28 00:51:36 +00001258 // And then we merge those three back into one. However, this also
1259 // invalidates all three SCCs further down in the PO walk.
1260 EXPECT_EQ(4 + 3 + 1 + 3, SCCAnalysisRuns);
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001261 // The module analysis pass should be run three times.
1262 EXPECT_EQ(3, ModuleAnalysisRuns);
1263 // We run over four SCCs the first time. Then over the two new ones. Then the
1264 // entire module is invalidated causing a full run over all seven. Then we
Chandler Carruth923ff552019-03-28 00:51:36 +00001265 // fold three SCCs back to one, re-compute for it and the two SCCs above it
1266 // in the graph, and then run over the whole module again.
1267 EXPECT_EQ(4 + 2 + 7 + 1 + 3 + 4, IndirectSCCAnalysisRuns);
1268 EXPECT_EQ(4 + 2 + 7 + 1 + 3 + 4, DoublyIndirectSCCAnalysisRuns);
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001269
1270 // First we run over all six functions. Then we re-run it over three when we
1271 // split their SCCs. Then we re-run over the whole module. Then we re-run
Chandler Carruth923ff552019-03-28 00:51:36 +00001272 // over three functions merged back into a single SCC, then those three
1273 // functions again, the two functions in SCCs above it in the graph, and then
1274 // over the whole module again.
1275 EXPECT_EQ(6 + 3 + 6 + 3 + 3 + 2 + 6, FunctionAnalysisRuns);
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001276
Chandler Carruth051bdb02017-07-12 09:08:11 +00001277 // Re run the function analysis over the entire module, and then re-run it
1278 // over the `(h3, h1, h2)` SCC due to invalidation. Then we re-run it over
1279 // the entire module, then the three functions merged back into a single SCC,
Chandler Carruth923ff552019-03-28 00:51:36 +00001280 // those three functions again, then the two functions in SCCs above it in
1281 // the graph, and then over the whole module.
1282 EXPECT_EQ(6 + 3 + 6 + 3 + 3 + 2 + 6, IndirectFunctionAnalysisRuns);
Chandler Carruth7c8964d2017-07-09 13:16:55 +00001283}
Chandler Carruth74319922016-02-23 10:02:02 +00001284}