[llvm-exegesis] Fix missing std::move.
[llvm-complete.git] / unittests / Analysis / CGSCCPassManagerTest.cpp
blob60da2bbc314aac32653804ddf7c4c0382075dc0a
1 //===- 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 //===----------------------------------------------------------------------===//
10 #include "llvm/Analysis/CGSCCPassManager.h"
11 #include "llvm/Analysis/LazyCallGraph.h"
12 #include "llvm/Analysis/TargetLibraryInfo.h"
13 #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"
22 using namespace llvm;
24 namespace {
26 class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
27 public:
28 struct Result {
29 Result(int Count) : FunctionCount(Count) {}
30 int FunctionCount;
33 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
35 Result run(Module &M, ModuleAnalysisManager &AM) {
36 ++Runs;
37 return Result(M.size());
40 private:
41 friend AnalysisInfoMixin<TestModuleAnalysis>;
42 static AnalysisKey Key;
44 int &Runs;
47 AnalysisKey TestModuleAnalysis::Key;
49 class TestSCCAnalysis : public AnalysisInfoMixin<TestSCCAnalysis> {
50 public:
51 struct Result {
52 Result(int Count) : FunctionCount(Count) {}
53 int FunctionCount;
56 TestSCCAnalysis(int &Runs) : Runs(Runs) {}
58 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &) {
59 ++Runs;
60 return Result(C.size());
63 private:
64 friend AnalysisInfoMixin<TestSCCAnalysis>;
65 static AnalysisKey Key;
67 int &Runs;
70 AnalysisKey TestSCCAnalysis::Key;
72 class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
73 public:
74 struct Result {
75 Result(int Count) : InstructionCount(Count) {}
76 int InstructionCount;
79 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
81 Result run(Function &F, FunctionAnalysisManager &AM) {
82 ++Runs;
83 int Count = 0;
84 for (Instruction &I : instructions(F)) {
85 (void)I;
86 ++Count;
88 return Result(Count);
91 private:
92 friend AnalysisInfoMixin<TestFunctionAnalysis>;
93 static AnalysisKey Key;
95 int &Runs;
98 AnalysisKey TestFunctionAnalysis::Key;
100 class TestImmutableFunctionAnalysis
101 : public AnalysisInfoMixin<TestImmutableFunctionAnalysis> {
102 public:
103 struct Result {
104 bool invalidate(Function &, const PreservedAnalyses &,
105 FunctionAnalysisManager::Invalidator &) {
106 return false;
110 TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {}
112 Result run(Function &F, FunctionAnalysisManager &AM) {
113 ++Runs;
114 return Result();
117 private:
118 friend AnalysisInfoMixin<TestImmutableFunctionAnalysis>;
119 static AnalysisKey Key;
121 int &Runs;
124 AnalysisKey TestImmutableFunctionAnalysis::Key;
126 struct LambdaModulePass : public PassInfoMixin<LambdaModulePass> {
127 template <typename T>
128 LambdaModulePass(T &&Arg) : Func(std::forward<T>(Arg)) {}
130 PreservedAnalyses run(Module &F, ModuleAnalysisManager &AM) {
131 return Func(F, AM);
134 std::function<PreservedAnalyses(Module &, ModuleAnalysisManager &)> Func;
137 struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> {
138 template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
140 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
141 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
142 return Func(C, AM, CG, UR);
145 std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
146 LazyCallGraph &, CGSCCUpdateResult &)>
147 Func;
150 struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> {
151 template <typename T>
152 LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
154 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
155 return Func(F, AM);
158 std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func;
161 std::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;
166 SMDiagnostic Err;
167 return parseAssemblyString(IR, Err, C);
170 class CGSCCPassManagerTest : public ::testing::Test {
171 protected:
172 LLVMContext Context;
173 FunctionAnalysisManager FAM;
174 CGSCCAnalysisManager CGAM;
175 ModuleAnalysisManager MAM;
177 std::unique_ptr<Module> M;
179 public:
180 CGSCCPassManagerTest()
181 : FAM(/*DebugLogging*/ true), CGAM(/*DebugLogging*/ true),
182 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:
187 // f
188 // |\ _
189 // | \ / |
190 // g h1 |
191 // | | |
192 // | h2 |
193 // | | |
194 // | h3 |
195 // | / \_/
196 // |/
197 // x
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")) {
231 MAM.registerPass([&] { return TargetLibraryAnalysis(); });
232 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
233 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
235 // Register required pass instrumentation analysis.
236 MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
237 CGAM.registerPass([&] { return PassInstrumentationAnalysis(); });
238 FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
240 // Cross-register proxies.
241 MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
242 CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); });
243 CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
244 FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
245 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
249 TEST_F(CGSCCPassManagerTest, Basic) {
250 int FunctionAnalysisRuns = 0;
251 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
252 int ImmutableFunctionAnalysisRuns = 0;
253 FAM.registerPass([&] {
254 return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns);
257 int SCCAnalysisRuns = 0;
258 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
260 int ModuleAnalysisRuns = 0;
261 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
263 ModulePassManager MPM(/*DebugLogging*/ true);
264 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
266 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
267 FunctionPassManager FPM1(/*DebugLogging*/ true);
268 int FunctionPassRunCount1 = 0;
269 FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
270 ++FunctionPassRunCount1;
271 return PreservedAnalyses::none();
272 }));
273 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
275 int SCCPassRunCount1 = 0;
276 int AnalyzedInstrCount1 = 0;
277 int AnalyzedSCCFunctionCount1 = 0;
278 int AnalyzedModuleFunctionCount1 = 0;
279 CGPM1.addPass(
280 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
281 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
282 ++SCCPassRunCount1;
284 const ModuleAnalysisManager &MAM =
285 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
286 FunctionAnalysisManager &FAM =
287 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
288 if (TestModuleAnalysis::Result *TMA =
289 MAM.getCachedResult<TestModuleAnalysis>(
290 *C.begin()->getFunction().getParent()))
291 AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
293 TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
294 AnalyzedSCCFunctionCount1 += AR.FunctionCount;
295 for (LazyCallGraph::Node &N : C) {
296 TestFunctionAnalysis::Result &FAR =
297 FAM.getResult<TestFunctionAnalysis>(N.getFunction());
298 AnalyzedInstrCount1 += FAR.InstructionCount;
300 // Just ensure we get the immutable results.
301 (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction());
304 return PreservedAnalyses::all();
305 }));
307 FunctionPassManager FPM2(/*DebugLogging*/ true);
308 int FunctionPassRunCount2 = 0;
309 FPM2.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
310 ++FunctionPassRunCount2;
311 return PreservedAnalyses::none();
312 }));
313 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
315 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
317 FunctionPassManager FPM3(/*DebugLogging*/ true);
318 int FunctionPassRunCount3 = 0;
319 FPM3.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
320 ++FunctionPassRunCount3;
321 return PreservedAnalyses::none();
322 }));
323 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM3)));
325 MPM.run(*M, MAM);
327 EXPECT_EQ(4, SCCPassRunCount1);
328 EXPECT_EQ(6, FunctionPassRunCount1);
329 EXPECT_EQ(6, FunctionPassRunCount2);
330 EXPECT_EQ(6, FunctionPassRunCount3);
332 EXPECT_EQ(1, ModuleAnalysisRuns);
333 EXPECT_EQ(4, SCCAnalysisRuns);
334 EXPECT_EQ(6, FunctionAnalysisRuns);
335 EXPECT_EQ(6, ImmutableFunctionAnalysisRuns);
337 EXPECT_EQ(14, AnalyzedInstrCount1);
338 EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
339 EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
342 // Test that an SCC pass which fails to preserve a module analysis does in fact
343 // invalidate that module analysis.
344 TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
345 int ModuleAnalysisRuns = 0;
346 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
348 ModulePassManager MPM(/*DebugLogging*/ true);
349 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
351 // The first CGSCC run we preserve everything and make sure that works and
352 // the module analysis is available in the second CGSCC run from the one
353 // required module pass above.
354 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
355 int CountFoundModuleAnalysis1 = 0;
356 CGPM1.addPass(
357 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
358 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
359 const auto &MAM =
360 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
361 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
362 *C.begin()->getFunction().getParent());
364 if (TMA)
365 ++CountFoundModuleAnalysis1;
367 return PreservedAnalyses::all();
368 }));
369 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
371 // The second CGSCC run checks that the module analysis got preserved the
372 // previous time and in one SCC fails to preserve it.
373 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
374 int CountFoundModuleAnalysis2 = 0;
375 CGPM2.addPass(
376 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
377 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
378 const auto &MAM =
379 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
380 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
381 *C.begin()->getFunction().getParent());
383 if (TMA)
384 ++CountFoundModuleAnalysis2;
386 // Only fail to preserve analyses on one SCC and make sure that gets
387 // propagated.
388 return C.getName() == "(g)" ? PreservedAnalyses::none()
389 : PreservedAnalyses::all();
390 }));
391 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
393 // The third CGSCC run should fail to find a cached module analysis as it
394 // should have been invalidated by the above CGSCC run.
395 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
396 int CountFoundModuleAnalysis3 = 0;
397 CGPM3.addPass(
398 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
399 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
400 const auto &MAM =
401 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
402 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
403 *C.begin()->getFunction().getParent());
405 if (TMA)
406 ++CountFoundModuleAnalysis3;
408 return PreservedAnalyses::none();
409 }));
410 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
412 MPM.run(*M, MAM);
414 EXPECT_EQ(1, ModuleAnalysisRuns);
415 EXPECT_EQ(4, CountFoundModuleAnalysis1);
416 EXPECT_EQ(4, CountFoundModuleAnalysis2);
417 EXPECT_EQ(0, CountFoundModuleAnalysis3);
420 // Similar to the above, but test that this works for function passes embedded
421 // *within* a CGSCC layer.
422 TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) {
423 int ModuleAnalysisRuns = 0;
424 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
426 ModulePassManager MPM(/*DebugLogging*/ true);
427 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
429 // The first run we preserve everything and make sure that works and the
430 // module analysis is available in the second run from the one required
431 // module pass above.
432 FunctionPassManager FPM1(/*DebugLogging*/ true);
433 // Start true and mark false if we ever failed to find a module analysis
434 // because we expect this to succeed for each SCC.
435 bool FoundModuleAnalysis1 = true;
436 FPM1.addPass(
437 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
438 const auto &MAM =
439 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
440 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
442 if (!TMA)
443 FoundModuleAnalysis1 = false;
445 return PreservedAnalyses::all();
446 }));
447 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
448 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
449 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
451 // The second run checks that the module analysis got preserved the previous
452 // time and in one function fails to preserve it.
453 FunctionPassManager FPM2(/*DebugLogging*/ true);
454 // Again, start true and mark false if we ever failed to find a module analysis
455 // because we expect this to succeed for each SCC.
456 bool FoundModuleAnalysis2 = true;
457 FPM2.addPass(
458 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
459 const auto &MAM =
460 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
461 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
463 if (!TMA)
464 FoundModuleAnalysis2 = false;
466 // Only fail to preserve analyses on one SCC and make sure that gets
467 // propagated.
468 return F.getName() == "h2" ? PreservedAnalyses::none()
469 : PreservedAnalyses::all();
470 }));
471 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
472 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
473 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
475 // The third run should fail to find a cached module analysis as it should
476 // have been invalidated by the above run.
477 FunctionPassManager FPM3(/*DebugLogging*/ true);
478 // Start false and mark true if we ever *succeeded* to find a module
479 // analysis, as we expect this to fail for every function.
480 bool FoundModuleAnalysis3 = false;
481 FPM3.addPass(
482 LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
483 const auto &MAM =
484 AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
485 auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
487 if (TMA)
488 FoundModuleAnalysis3 = true;
490 return PreservedAnalyses::none();
491 }));
492 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
493 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3)));
494 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
496 MPM.run(*M, MAM);
498 EXPECT_EQ(1, ModuleAnalysisRuns);
499 EXPECT_TRUE(FoundModuleAnalysis1);
500 EXPECT_TRUE(FoundModuleAnalysis2);
501 EXPECT_FALSE(FoundModuleAnalysis3);
504 // Test that a Module pass which fails to preserve an SCC analysis in fact
505 // invalidates that analysis.
506 TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysis) {
507 int SCCAnalysisRuns = 0;
508 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
510 ModulePassManager MPM(/*DebugLogging*/ true);
512 // First force the analysis to be run.
513 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
514 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
515 CGSCCAnalysisManager, LazyCallGraph &,
516 CGSCCUpdateResult &>());
517 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
519 // Now run a module pass that preserves the LazyCallGraph and the proxy but
520 // not the SCC analysis.
521 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
522 PreservedAnalyses PA;
523 PA.preserve<LazyCallGraphAnalysis>();
524 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
525 PA.preserve<FunctionAnalysisManagerModuleProxy>();
526 return PA;
527 }));
529 // And now a second CGSCC run which requires the SCC analysis again. This
530 // will trigger re-running it.
531 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
532 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
533 CGSCCAnalysisManager, LazyCallGraph &,
534 CGSCCUpdateResult &>());
535 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
537 MPM.run(*M, MAM);
538 // Two runs and four SCCs.
539 EXPECT_EQ(2 * 4, SCCAnalysisRuns);
542 // Check that marking the SCC analysis preserved is sufficient to avoid
543 // invaliadtion. This should only run the analysis once for each SCC.
544 TEST_F(CGSCCPassManagerTest, TestModulePassCanPreserveSCCAnalysis) {
545 int SCCAnalysisRuns = 0;
546 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
548 ModulePassManager MPM(/*DebugLogging*/ true);
550 // First force the analysis to be run.
551 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
552 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
553 CGSCCAnalysisManager, LazyCallGraph &,
554 CGSCCUpdateResult &>());
555 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
557 // Now run a module pass that preserves each of the necessary components
558 // (but not everything).
559 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
560 PreservedAnalyses PA;
561 PA.preserve<LazyCallGraphAnalysis>();
562 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
563 PA.preserve<FunctionAnalysisManagerModuleProxy>();
564 PA.preserve<TestSCCAnalysis>();
565 return PA;
566 }));
568 // And now a second CGSCC run which requires the SCC analysis again but find
569 // it in the cache.
570 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
571 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
572 CGSCCAnalysisManager, LazyCallGraph &,
573 CGSCCUpdateResult &>());
574 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
576 MPM.run(*M, MAM);
577 // Four SCCs
578 EXPECT_EQ(4, SCCAnalysisRuns);
581 // Check that even when the analysis is preserved, if the SCC information isn't
582 // we still nuke things because the SCC keys could change.
583 TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysisOnCGChange) {
584 int SCCAnalysisRuns = 0;
585 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
587 ModulePassManager MPM(/*DebugLogging*/ true);
589 // First force the analysis to be run.
590 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
591 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
592 CGSCCAnalysisManager, LazyCallGraph &,
593 CGSCCUpdateResult &>());
594 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
596 // Now run a module pass that preserves the analysis but not the call
597 // graph or proxy.
598 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
599 PreservedAnalyses PA;
600 PA.preserve<TestSCCAnalysis>();
601 return PA;
602 }));
604 // And now a second CGSCC run which requires the SCC analysis again.
605 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
606 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
607 CGSCCAnalysisManager, LazyCallGraph &,
608 CGSCCUpdateResult &>());
609 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
611 MPM.run(*M, MAM);
612 // Two runs and four SCCs.
613 EXPECT_EQ(2 * 4, SCCAnalysisRuns);
616 // Test that an SCC pass which fails to preserve a Function analysis in fact
617 // invalidates that analysis.
618 TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesFunctionAnalysis) {
619 int FunctionAnalysisRuns = 0;
620 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
622 // Create a very simple module with a single function and SCC to make testing
623 // these issues much easier.
624 std::unique_ptr<Module> M = parseIR("declare void @g()\n"
625 "declare void @h()\n"
626 "define void @f() {\n"
627 "entry:\n"
628 " call void @g()\n"
629 " call void @h()\n"
630 " ret void\n"
631 "}\n");
633 CGSCCPassManager CGPM(/*DebugLogging*/ true);
635 // First force the analysis to be run.
636 FunctionPassManager FPM1(/*DebugLogging*/ true);
637 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
638 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
640 // Now run a module pass that preserves the LazyCallGraph and proxy but not
641 // the SCC analysis.
642 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
643 LazyCallGraph &, CGSCCUpdateResult &) {
644 PreservedAnalyses PA;
645 PA.preserve<LazyCallGraphAnalysis>();
646 return PA;
647 }));
649 // And now a second CGSCC run which requires the SCC analysis again. This
650 // will trigger re-running it.
651 FunctionPassManager FPM2(/*DebugLogging*/ true);
652 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
653 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
655 ModulePassManager MPM(/*DebugLogging*/ true);
656 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
657 MPM.run(*M, MAM);
658 EXPECT_EQ(2, FunctionAnalysisRuns);
661 // Check that marking the SCC analysis preserved is sufficient. This should
662 // only run the analysis once the SCC.
663 TEST_F(CGSCCPassManagerTest, TestSCCPassCanPreserveFunctionAnalysis) {
664 int FunctionAnalysisRuns = 0;
665 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
667 // Create a very simple module with a single function and SCC to make testing
668 // these issues much easier.
669 std::unique_ptr<Module> M = parseIR("declare void @g()\n"
670 "declare void @h()\n"
671 "define void @f() {\n"
672 "entry:\n"
673 " call void @g()\n"
674 " call void @h()\n"
675 " ret void\n"
676 "}\n");
678 CGSCCPassManager CGPM(/*DebugLogging*/ true);
680 // First force the analysis to be run.
681 FunctionPassManager FPM1(/*DebugLogging*/ true);
682 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
683 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
685 // Now run a module pass that preserves each of the necessary components
686 // (but
687 // not everything).
688 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
689 LazyCallGraph &, CGSCCUpdateResult &) {
690 PreservedAnalyses PA;
691 PA.preserve<LazyCallGraphAnalysis>();
692 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
693 PA.preserve<TestFunctionAnalysis>();
694 return PA;
695 }));
697 // And now a second CGSCC run which requires the SCC analysis again but find
698 // it in the cache.
699 FunctionPassManager FPM2(/*DebugLogging*/ true);
700 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
701 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
703 ModulePassManager MPM(/*DebugLogging*/ true);
704 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
705 MPM.run(*M, MAM);
706 EXPECT_EQ(1, FunctionAnalysisRuns);
709 // Note that there is no test for invalidating the call graph or other
710 // structure with an SCC pass because there is no mechanism to do that from
711 // withinsuch a pass. Instead, such a pass has to directly update the call
712 // graph structure.
714 // Test that a madule pass invalidates function analyses when the CGSCC proxies
715 // and pass manager.
716 TEST_F(CGSCCPassManagerTest,
717 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC) {
718 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
720 int FunctionAnalysisRuns = 0;
721 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
723 ModulePassManager MPM(/*DebugLogging*/ true);
725 // First force the analysis to be run.
726 FunctionPassManager FPM1(/*DebugLogging*/ true);
727 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
728 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
729 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
730 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
732 // Now run a module pass that preserves the LazyCallGraph and proxies but not
733 // the Function analysis.
734 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
735 PreservedAnalyses PA;
736 PA.preserve<LazyCallGraphAnalysis>();
737 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
738 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
739 PA.preserve<FunctionAnalysisManagerModuleProxy>();
740 return PA;
741 }));
743 // And now a second CGSCC run which requires the SCC analysis again. This
744 // will trigger re-running it.
745 FunctionPassManager FPM2(/*DebugLogging*/ true);
746 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
747 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
748 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
749 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
751 MPM.run(*M, MAM);
752 // Two runs and 6 functions.
753 EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
756 // Check that by marking the function pass and proxies as preserved, this
757 // propagates all the way through.
758 TEST_F(CGSCCPassManagerTest,
759 TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC) {
760 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
762 int FunctionAnalysisRuns = 0;
763 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
765 ModulePassManager MPM(/*DebugLogging*/ true);
767 // First force the analysis to be run.
768 FunctionPassManager FPM1(/*DebugLogging*/ true);
769 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
770 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
771 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
772 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
774 // Now run a module pass that preserves the LazyCallGraph, the proxy, and
775 // the Function analysis.
776 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
777 PreservedAnalyses PA;
778 PA.preserve<LazyCallGraphAnalysis>();
779 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
780 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
781 PA.preserve<FunctionAnalysisManagerModuleProxy>();
782 PA.preserve<TestFunctionAnalysis>();
783 return PA;
784 }));
786 // And now a second CGSCC run which requires the SCC analysis again. This
787 // will trigger re-running it.
788 FunctionPassManager FPM2(/*DebugLogging*/ true);
789 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
790 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
791 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
792 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
794 MPM.run(*M, MAM);
795 // One run and 6 functions.
796 EXPECT_EQ(6, FunctionAnalysisRuns);
799 // Check that if the lazy call graph itself isn't preserved we still manage to
800 // invalidate everything.
801 TEST_F(CGSCCPassManagerTest,
802 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange) {
803 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
805 int FunctionAnalysisRuns = 0;
806 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
808 ModulePassManager MPM(/*DebugLogging*/ true);
810 // First force the analysis to be run.
811 FunctionPassManager FPM1(/*DebugLogging*/ true);
812 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
813 CGSCCPassManager CGPM1(/*DebugLogging*/ true);
814 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
815 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
817 // Now run a module pass that preserves the LazyCallGraph but not the
818 // Function analysis.
819 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
820 PreservedAnalyses PA;
821 return PA;
822 }));
824 // And now a second CGSCC run which requires the SCC analysis again. This
825 // will trigger re-running it.
826 FunctionPassManager FPM2(/*DebugLogging*/ true);
827 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
828 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
829 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
830 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
832 MPM.run(*M, MAM);
833 // Two runs and 6 functions.
834 EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
837 /// A test CGSCC-level analysis pass which caches in its result another
838 /// analysis pass and uses it to serve queries. This requires the result to
839 /// invalidate itself when its dependency is invalidated.
841 /// FIXME: Currently this doesn't also depend on a function analysis, and if it
842 /// did we would fail to invalidate it correctly.
843 struct TestIndirectSCCAnalysis
844 : public AnalysisInfoMixin<TestIndirectSCCAnalysis> {
845 struct Result {
846 Result(TestSCCAnalysis::Result &SCCDep, TestModuleAnalysis::Result &MDep)
847 : SCCDep(SCCDep), MDep(MDep) {}
848 TestSCCAnalysis::Result &SCCDep;
849 TestModuleAnalysis::Result &MDep;
851 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
852 CGSCCAnalysisManager::Invalidator &Inv) {
853 auto PAC = PA.getChecker<TestIndirectSCCAnalysis>();
854 return !(PAC.preserved() ||
855 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
856 Inv.invalidate<TestSCCAnalysis>(C, PA);
860 TestIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
862 /// Run the analysis pass over the function and return a result.
863 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
864 LazyCallGraph &CG) {
865 ++Runs;
866 auto &SCCDep = AM.getResult<TestSCCAnalysis>(C, CG);
868 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
869 const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
870 // For the test, we insist that the module analysis starts off in the
871 // cache.
872 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(
873 *C.begin()->getFunction().getParent());
874 // Register the dependency as module analysis dependencies have to be
875 // pre-registered on the proxy.
876 ModuleProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
877 TestIndirectSCCAnalysis>();
879 return Result(SCCDep, MDep);
882 private:
883 friend AnalysisInfoMixin<TestIndirectSCCAnalysis>;
884 static AnalysisKey Key;
886 int &Runs;
889 AnalysisKey TestIndirectSCCAnalysis::Key;
891 /// A test analysis pass which caches in its result the result from the above
892 /// indirect analysis pass.
894 /// This allows us to ensure that whenever an analysis pass is invalidated due
895 /// to dependencies (especially dependencies across IR units that trigger
896 /// asynchronous invalidation) we correctly detect that this may in turn cause
897 /// other analysis to be invalidated.
898 struct TestDoublyIndirectSCCAnalysis
899 : public AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis> {
900 struct Result {
901 Result(TestIndirectSCCAnalysis::Result &IDep) : IDep(IDep) {}
902 TestIndirectSCCAnalysis::Result &IDep;
904 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
905 CGSCCAnalysisManager::Invalidator &Inv) {
906 auto PAC = PA.getChecker<TestDoublyIndirectSCCAnalysis>();
907 return !(PAC.preserved() ||
908 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
909 Inv.invalidate<TestIndirectSCCAnalysis>(C, PA);
913 TestDoublyIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
915 /// Run the analysis pass over the function and return a result.
916 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
917 LazyCallGraph &CG) {
918 ++Runs;
919 auto &IDep = AM.getResult<TestIndirectSCCAnalysis>(C, CG);
920 return Result(IDep);
923 private:
924 friend AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis>;
925 static AnalysisKey Key;
927 int &Runs;
930 AnalysisKey TestDoublyIndirectSCCAnalysis::Key;
932 /// A test analysis pass which caches results from three different IR unit
933 /// layers and requires intermediate layers to correctly propagate the entire
934 /// distance.
935 struct TestIndirectFunctionAnalysis
936 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
937 struct Result {
938 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep,
939 TestSCCAnalysis::Result &SCCDep)
940 : FDep(FDep), MDep(MDep), SCCDep(SCCDep) {}
941 TestFunctionAnalysis::Result &FDep;
942 TestModuleAnalysis::Result &MDep;
943 TestSCCAnalysis::Result &SCCDep;
945 bool invalidate(Function &F, const PreservedAnalyses &PA,
946 FunctionAnalysisManager::Invalidator &Inv) {
947 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
948 return !(PAC.preserved() ||
949 PAC.preservedSet<AllAnalysesOn<Function>>()) ||
950 Inv.invalidate<TestFunctionAnalysis>(F, PA);
954 TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
956 /// Run the analysis pass over the function and return a result.
957 Result run(Function &F, FunctionAnalysisManager &AM) {
958 ++Runs;
959 auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
961 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
962 const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
963 // For the test, we insist that the module analysis starts off in the
964 // cache.
965 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
966 // Register the dependency as module analysis dependencies have to be
967 // pre-registered on the proxy.
968 ModuleProxy.registerOuterAnalysisInvalidation<
969 TestModuleAnalysis, TestIndirectFunctionAnalysis>();
971 // For thet test we assume this is run inside a CGSCC pass manager.
972 const LazyCallGraph &CG =
973 *MAM.getCachedResult<LazyCallGraphAnalysis>(*F.getParent());
974 auto &CGSCCProxy = AM.getResult<CGSCCAnalysisManagerFunctionProxy>(F);
975 const CGSCCAnalysisManager &CGAM = CGSCCProxy.getManager();
976 // For the test, we insist that the CGSCC analysis starts off in the cache.
977 auto &SCCDep =
978 *CGAM.getCachedResult<TestSCCAnalysis>(*CG.lookupSCC(*CG.lookup(F)));
979 // Register the dependency as CGSCC analysis dependencies have to be
980 // pre-registered on the proxy.
981 CGSCCProxy.registerOuterAnalysisInvalidation<
982 TestSCCAnalysis, TestIndirectFunctionAnalysis>();
984 return Result(FDep, MDep, SCCDep);
987 private:
988 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
989 static AnalysisKey Key;
991 int &Runs;
994 AnalysisKey TestIndirectFunctionAnalysis::Key;
996 TEST_F(CGSCCPassManagerTest, TestIndirectAnalysisInvalidation) {
997 int ModuleAnalysisRuns = 0;
998 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
1000 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
1001 DoublyIndirectSCCAnalysisRuns = 0;
1002 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
1003 CGAM.registerPass(
1004 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
1005 CGAM.registerPass([&] {
1006 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
1009 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
1010 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
1011 FAM.registerPass([&] {
1012 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
1015 ModulePassManager MPM(/*DebugLogging*/ true);
1017 int FunctionCount = 0;
1018 CGSCCPassManager CGPM(/*DebugLogging*/ true);
1019 // First just use the analysis to get the function count and preserve
1020 // everything.
1021 CGPM.addPass(
1022 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1023 LazyCallGraph &CG, CGSCCUpdateResult &) {
1024 auto &DoublyIndirectResult =
1025 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1026 auto &IndirectResult = DoublyIndirectResult.IDep;
1027 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1028 return PreservedAnalyses::all();
1029 }));
1030 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1031 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1033 // Next, invalidate
1034 // - both analyses for the (f) and (x) SCCs,
1035 // - just the underlying (indirect) analysis for (g) SCC, and
1036 // - just the direct analysis for (h1,h2,h3) SCC.
1037 CGPM.addPass(
1038 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1039 LazyCallGraph &CG, CGSCCUpdateResult &) {
1040 auto &DoublyIndirectResult =
1041 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1042 auto &IndirectResult = DoublyIndirectResult.IDep;
1043 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1044 auto PA = PreservedAnalyses::none();
1045 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1046 PA.preserveSet<AllAnalysesOn<Function>>();
1047 if (C.getName() == "(g)")
1048 PA.preserve<TestSCCAnalysis>();
1049 else if (C.getName() == "(h3, h1, h2)")
1050 PA.preserve<TestIndirectSCCAnalysis>();
1051 return PA;
1052 }));
1053 // Finally, use the analysis again on each SCC (and function), forcing
1054 // re-computation for all of them.
1055 CGPM.addPass(
1056 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1057 LazyCallGraph &CG, CGSCCUpdateResult &) {
1058 auto &DoublyIndirectResult =
1059 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1060 auto &IndirectResult = DoublyIndirectResult.IDep;
1061 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1062 return PreservedAnalyses::all();
1063 }));
1064 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1065 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1067 // Create a second CGSCC pass manager. This will cause the module-level
1068 // invalidation to occur, which will force yet another invalidation of the
1069 // indirect SCC-level analysis as the module analysis it depends on gets
1070 // invalidated.
1071 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
1072 CGPM2.addPass(
1073 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1074 LazyCallGraph &CG, CGSCCUpdateResult &) {
1075 auto &DoublyIndirectResult =
1076 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1077 auto &IndirectResult = DoublyIndirectResult.IDep;
1078 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1079 return PreservedAnalyses::all();
1080 }));
1081 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
1082 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1084 // Add a requires pass to populate the module analysis and then our CGSCC
1085 // pass pipeline.
1086 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1087 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1088 // Now require the module analysis again (it will have been invalidated once)
1089 // and then use it again from our second CGSCC pipeline..
1090 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1091 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
1092 MPM.run(*M, MAM);
1094 // There are generally two possible runs for each of the four SCCs. But
1095 // for one SCC, we only invalidate the indirect analysis so the base one
1096 // only gets run seven times.
1097 EXPECT_EQ(7, SCCAnalysisRuns);
1098 // The module analysis pass should be run twice here.
1099 EXPECT_EQ(2, ModuleAnalysisRuns);
1100 // The indirect analysis is invalidated (either directly or indirectly) three
1101 // times for each of four SCCs.
1102 EXPECT_EQ(3 * 4, IndirectSCCAnalysisRuns);
1103 EXPECT_EQ(3 * 4, DoublyIndirectSCCAnalysisRuns);
1105 // We run the indirect function analysis once per function the first time.
1106 // Then we re-run it for every SCC but "(g)". Then we re-run it for every
1107 // function again.
1108 EXPECT_EQ(6 + 5 + 6, IndirectFunctionAnalysisRuns);
1110 // Four passes count each of six functions once (via SCCs).
1111 EXPECT_EQ(4 * 6, FunctionCount);
1114 TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) {
1115 int ModuleAnalysisRuns = 0;
1116 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
1118 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
1119 DoublyIndirectSCCAnalysisRuns = 0;
1120 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
1121 CGAM.registerPass(
1122 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
1123 CGAM.registerPass([&] {
1124 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
1127 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
1128 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
1129 FAM.registerPass([&] {
1130 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
1133 ModulePassManager MPM(/*DebugLogging*/ true);
1135 CGSCCPassManager CGPM(/*DebugLogging*/ true);
1136 // First just use the analysis to get the function count and preserve
1137 // everything.
1138 using RequireTestIndirectFunctionAnalysisPass =
1139 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>;
1140 using RequireTestDoublyIndirectSCCAnalysisPass =
1141 RequireAnalysisPass<TestDoublyIndirectSCCAnalysis, LazyCallGraph::SCC,
1142 CGSCCAnalysisManager, LazyCallGraph &,
1143 CGSCCUpdateResult &>;
1144 CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1145 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1146 RequireTestIndirectFunctionAnalysisPass()));
1148 // Next, we inject an SCC pass that invalidates everything for the `(h3, h1,
1149 // h2)` SCC but also deletes the call edge from `h2` to `h3` and updates the
1150 // CG. This should successfully invalidate (and force to be re-run) all the
1151 // analyses for that SCC and for the functions.
1152 CGPM.addPass(
1153 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1154 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1155 (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1156 if (C.getName() != "(h3, h1, h2)")
1157 return PreservedAnalyses::all();
1159 // Build the preserved set.
1160 auto PA = PreservedAnalyses::none();
1161 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1162 PA.preserve<TestIndirectSCCAnalysis>();
1163 PA.preserve<TestDoublyIndirectSCCAnalysis>();
1165 // Delete the call from `h2` to `h3`.
1166 auto &H2N = *llvm::find_if(
1167 C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
1168 auto &H2F = H2N.getFunction();
1169 auto &H3F = *cast<CallInst>(H2F.begin()->begin())->getCalledFunction();
1170 assert(H3F.getName() == "h3" && "Wrong called function!");
1171 H2F.begin()->begin()->eraseFromParent();
1172 // Insert a bitcast of `h3` so that we retain a ref edge to it.
1173 (void)CastInst::CreatePointerCast(&H3F,
1174 Type::getInt8PtrTy(H2F.getContext()),
1175 "dummy", &*H2F.begin()->begin());
1177 // Now update the call graph.
1178 auto &NewC =
1179 updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR);
1180 assert(&NewC != &C && "Should get a new SCC due to update!");
1181 (void)&NewC;
1183 return PA;
1184 }));
1185 // Now use the analysis again on each SCC and function, forcing
1186 // re-computation for all of them.
1187 CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1188 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1189 RequireTestIndirectFunctionAnalysisPass()));
1191 // Create another CGSCC pipeline that requires all the analyses again.
1192 CGSCCPassManager CGPM2(/*DebugLogging*/ true);
1193 CGPM2.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1194 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
1195 RequireTestIndirectFunctionAnalysisPass()));
1197 // Next we inject an SCC pass that finds the `(h2)` SCC, adds a call to `h3`
1198 // back to `h2`, and then invalidates everything for what will then be the
1199 // `(h3, h1, h2)` SCC again.
1200 CGSCCPassManager CGPM3(/*DebugLogging*/ true);
1201 CGPM3.addPass(
1202 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1203 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1204 (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1205 if (C.getName() != "(h2)")
1206 return PreservedAnalyses::all();
1208 // Build the preserved set.
1209 auto PA = PreservedAnalyses::none();
1210 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1211 PA.preserve<TestIndirectSCCAnalysis>();
1212 PA.preserve<TestDoublyIndirectSCCAnalysis>();
1214 // Delete the bitcast of `h3` that we added earlier.
1215 auto &H2N = *C.begin();
1216 auto &H2F = H2N.getFunction();
1217 auto &H3F = *cast<Function>(cast<BitCastInst>(H2F.begin()->begin())->getOperand(0));
1218 assert(H3F.getName() == "h3" && "Wrong called function!");
1219 H2F.begin()->begin()->eraseFromParent();
1220 // And insert a call to `h3`.
1221 (void)CallInst::Create(&H3F, {}, "", &*H2F.begin()->begin());
1223 // Now update the call graph.
1224 auto &NewC =
1225 updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR);
1226 assert(&NewC != &C && "Should get a new SCC due to update!");
1227 (void)&NewC;
1229 return PA;
1230 }));
1231 // Now use the analysis again on each SCC and function, forcing
1232 // re-computation for all of them.
1233 CGPM3.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1234 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(
1235 RequireTestIndirectFunctionAnalysisPass()));
1237 // Create a second CGSCC pass manager. This will cause the module-level
1238 // invalidation to occur, which will force yet another invalidation of the
1239 // indirect SCC-level analysis as the module analysis it depends on gets
1240 // invalidated.
1241 CGSCCPassManager CGPM4(/*DebugLogging*/ true);
1242 CGPM4.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1243 CGPM4.addPass(createCGSCCToFunctionPassAdaptor(
1244 RequireTestIndirectFunctionAnalysisPass()));
1246 // Add a requires pass to populate the module analysis and then one of our
1247 // CGSCC pipelines. Repeat for all four CGSCC pipelines.
1248 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1249 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1250 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1251 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
1252 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1253 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
1254 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1255 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM4)));
1256 MPM.run(*M, MAM);
1258 // We run over four SCCs the first time. But then we split an SCC into three.
1259 // And then we merge those three back into one.
1260 EXPECT_EQ(4 + 3 + 1, SCCAnalysisRuns);
1261 // 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
1265 // fold three SCCs back to one, and then run over the whole module again.
1266 EXPECT_EQ(4 + 2 + 7 + 1 + 4, IndirectSCCAnalysisRuns);
1267 EXPECT_EQ(4 + 2 + 7 + 1 + 4, DoublyIndirectSCCAnalysisRuns);
1269 // First we run over all six functions. Then we re-run it over three when we
1270 // split their SCCs. Then we re-run over the whole module. Then we re-run
1271 // over three functions merged back into a single SCC, and then over the
1272 // whole module again.
1273 EXPECT_EQ(6 + 3 + 6 + 3 + 6, FunctionAnalysisRuns);
1275 // Re run the function analysis over the entire module, and then re-run it
1276 // over the `(h3, h1, h2)` SCC due to invalidation. Then we re-run it over
1277 // the entire module, then the three functions merged back into a single SCC,
1278 // and then over the whole module.
1279 EXPECT_EQ(6 + 3 + 6 + 3 + 6, IndirectFunctionAnalysisRuns);