Fix test failures introduced by PR #113697 (#116941)
[llvm-project.git] / llvm / unittests / Analysis / CGSCCPassManagerTest.cpp
blob5c71bc8063d6c9b89ceca76ee12ae541bed56371
1 //===- CGSCCPassManagerTest.cpp -------------------------------------------===//
2 //
3 // 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
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/CGSCCPassManager.h"
10 #include "llvm/Analysis/LazyCallGraph.h"
11 #include "llvm/Analysis/TargetLibraryInfo.h"
12 #include "llvm/AsmParser/Parser.h"
13 #include "llvm/IR/Constants.h"
14 #include "llvm/IR/Function.h"
15 #include "llvm/IR/InstIterator.h"
16 #include "llvm/IR/Instructions.h"
17 #include "llvm/IR/LLVMContext.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/IR/PassManager.h"
20 #include "llvm/IR/PassInstrumentation.h"
21 #include "llvm/IR/Verifier.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include "llvm/Transforms/Utils/CallGraphUpdater.h"
24 #include "gtest/gtest.h"
26 using namespace llvm;
28 namespace {
30 class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
31 public:
32 struct Result {
33 Result(int Count) : FunctionCount(Count) {}
34 int FunctionCount;
35 bool invalidate(Module &, const PreservedAnalyses &PA,
36 ModuleAnalysisManager::Invalidator &) {
37 // Check whether the analysis or all analyses on modules have been
38 // preserved.
39 auto PAC = PA.getChecker<TestModuleAnalysis>();
40 return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>());
44 TestModuleAnalysis(int &Runs) : Runs(Runs) {}
46 Result run(Module &M, ModuleAnalysisManager &AM) {
47 ++Runs;
48 return Result(M.size());
51 private:
52 friend AnalysisInfoMixin<TestModuleAnalysis>;
53 static AnalysisKey Key;
55 int &Runs;
58 AnalysisKey TestModuleAnalysis::Key;
60 class TestSCCAnalysis : public AnalysisInfoMixin<TestSCCAnalysis> {
61 public:
62 struct Result {
63 Result(int Count) : FunctionCount(Count) {}
64 int FunctionCount;
65 bool invalidate(LazyCallGraph::SCC &, const PreservedAnalyses &PA,
66 CGSCCAnalysisManager::Invalidator &) {
67 // Check whether the analysis or all analyses on SCCs have been
68 // preserved.
69 auto PAC = PA.getChecker<TestSCCAnalysis>();
70 return !(PAC.preserved() ||
71 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>());
75 TestSCCAnalysis(int &Runs) : Runs(Runs) {}
77 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &) {
78 ++Runs;
79 return Result(C.size());
82 private:
83 friend AnalysisInfoMixin<TestSCCAnalysis>;
84 static AnalysisKey Key;
86 int &Runs;
89 AnalysisKey TestSCCAnalysis::Key;
91 class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
92 public:
93 struct Result {
94 Result(int Count) : InstructionCount(Count) {}
95 int InstructionCount;
96 bool invalidate(Function &, const PreservedAnalyses &PA,
97 FunctionAnalysisManager::Invalidator &) {
98 // Check whether the analysis or all analyses on functions have been
99 // preserved.
100 auto PAC = PA.getChecker<TestFunctionAnalysis>();
101 return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>());
105 TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
107 Result run(Function &F, FunctionAnalysisManager &AM) {
108 ++Runs;
109 int Count = 0;
110 for (Instruction &I : instructions(F)) {
111 (void)I;
112 ++Count;
114 return Result(Count);
117 private:
118 friend AnalysisInfoMixin<TestFunctionAnalysis>;
119 static AnalysisKey Key;
121 int &Runs;
124 AnalysisKey TestFunctionAnalysis::Key;
126 class TestImmutableFunctionAnalysis
127 : public AnalysisInfoMixin<TestImmutableFunctionAnalysis> {
128 public:
129 struct Result {
130 bool invalidate(Function &, const PreservedAnalyses &,
131 FunctionAnalysisManager::Invalidator &) {
132 return false;
136 TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {}
138 Result run(Function &F, FunctionAnalysisManager &AM) {
139 ++Runs;
140 return Result();
143 private:
144 friend AnalysisInfoMixin<TestImmutableFunctionAnalysis>;
145 static AnalysisKey Key;
147 int &Runs;
150 AnalysisKey TestImmutableFunctionAnalysis::Key;
152 struct LambdaModulePass : public PassInfoMixin<LambdaModulePass> {
153 template <typename T>
154 LambdaModulePass(T &&Arg) : Func(std::forward<T>(Arg)) {}
156 PreservedAnalyses run(Module &F, ModuleAnalysisManager &AM) {
157 return Func(F, AM);
160 std::function<PreservedAnalyses(Module &, ModuleAnalysisManager &)> Func;
163 struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> {
164 template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
166 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
167 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
168 return Func(C, AM, CG, UR);
171 std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
172 LazyCallGraph &, CGSCCUpdateResult &)>
173 Func;
176 struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> {
177 template <typename T>
178 LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
180 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
181 return Func(F, AM);
184 std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func;
187 std::unique_ptr<Module> parseIR(const char *IR) {
188 // We just use a static context here. This is never called from multiple
189 // threads so it is harmless no matter how it is implemented. We just need
190 // the context to outlive the module which it does.
191 static LLVMContext C;
192 SMDiagnostic Err;
193 return parseAssemblyString(IR, Err, C);
196 class CGSCCPassManagerTest : public ::testing::Test {
197 protected:
198 LLVMContext Context;
199 FunctionAnalysisManager FAM;
200 CGSCCAnalysisManager CGAM;
201 ModuleAnalysisManager MAM;
203 std::unique_ptr<Module> M;
205 public:
206 CGSCCPassManagerTest()
207 : FAM(), CGAM(), MAM(),
208 M(parseIR(
209 // Define a module with the following call graph, where calls go
210 // out the bottom of nodes and enter the top:
212 // f
213 // |\ _
214 // | \ / |
215 // g h1 |
216 // | | |
217 // | h2 |
218 // | | |
219 // | h3 |
220 // | / \_/
221 // |/
222 // x
224 "define void @x() {\n"
225 "entry:\n"
226 " ret void\n"
227 "}\n"
228 "define void @h3() {\n"
229 "entry:\n"
230 " call void @h1()\n"
231 " ret void\n"
232 "}\n"
233 "define void @h2() {\n"
234 "entry:\n"
235 " call void @h3()\n"
236 " call void @x()\n"
237 " ret void\n"
238 "}\n"
239 "define void @h1() {\n"
240 "entry:\n"
241 " call void @h2()\n"
242 " ret void\n"
243 "}\n"
244 "define void @g() {\n"
245 "entry:\n"
246 " call void @g()\n"
247 " call void @x()\n"
248 " ret void\n"
249 "}\n"
250 "define void @f() {\n"
251 "entry:\n"
252 " call void @g()\n"
253 " call void @h1()\n"
254 " ret void\n"
255 "}\n")) {
256 FAM.registerPass([&] { return TargetLibraryAnalysis(); });
257 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
258 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
260 // Register required pass instrumentation analysis.
261 MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
262 CGAM.registerPass([&] { return PassInstrumentationAnalysis(); });
263 FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
265 // Cross-register proxies.
266 MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
267 CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); });
268 CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
269 FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
270 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
274 TEST_F(CGSCCPassManagerTest, Basic) {
275 int FunctionAnalysisRuns = 0;
276 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
277 int ImmutableFunctionAnalysisRuns = 0;
278 FAM.registerPass([&] {
279 return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns);
282 int SCCAnalysisRuns = 0;
283 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
285 int ModuleAnalysisRuns = 0;
286 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
288 ModulePassManager MPM;
289 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
291 CGSCCPassManager CGPM1;
292 FunctionPassManager FPM1;
293 int FunctionPassRunCount1 = 0;
294 FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
295 ++FunctionPassRunCount1;
296 return PreservedAnalyses::none();
297 }));
298 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
300 int SCCPassRunCount1 = 0;
301 int AnalyzedInstrCount1 = 0;
302 int AnalyzedSCCFunctionCount1 = 0;
303 int AnalyzedModuleFunctionCount1 = 0;
304 CGPM1.addPass(
305 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
306 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
307 ++SCCPassRunCount1;
309 // Note: The proper way to get to a module pass from a CGSCC pass is
310 // through the ModuleAnalysisManagerCGSCCProxy:
311 // ```
312 // const auto &MAMProxy =
313 // AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
314 // ```
315 // However getting a stateful analysis is incorrect usage, and the call
316 // to getCachedResult below asserts:
317 // ```
318 // if (TestModuleAnalysis::Result *TMA =
319 // MAMProxy.getCachedResult<TestModuleAnalysis>(
320 // *C.begin()->getFunction().getParent()))
321 // AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
322 // ```
323 // For the purposes of this unittest, use the above MAM directly.
324 if (TestModuleAnalysis::Result *TMA =
325 MAM.getCachedResult<TestModuleAnalysis>(
326 *C.begin()->getFunction().getParent()))
327 AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
329 FunctionAnalysisManager &FAM =
330 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
331 TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
332 AnalyzedSCCFunctionCount1 += AR.FunctionCount;
333 for (LazyCallGraph::Node &N : C) {
334 TestFunctionAnalysis::Result &FAR =
335 FAM.getResult<TestFunctionAnalysis>(N.getFunction());
336 AnalyzedInstrCount1 += FAR.InstructionCount;
338 // Just ensure we get the immutable results.
339 (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction());
342 return PreservedAnalyses::all();
343 }));
345 FunctionPassManager FPM2;
346 int FunctionPassRunCount2 = 0;
347 FPM2.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
348 ++FunctionPassRunCount2;
349 return PreservedAnalyses::none();
350 }));
351 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
353 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
355 FunctionPassManager FPM3;
356 int FunctionPassRunCount3 = 0;
357 FPM3.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
358 ++FunctionPassRunCount3;
359 return PreservedAnalyses::none();
360 }));
361 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM3)));
363 MPM.run(*M, MAM);
365 EXPECT_EQ(4, SCCPassRunCount1);
366 EXPECT_EQ(6, FunctionPassRunCount1);
367 EXPECT_EQ(6, FunctionPassRunCount2);
368 EXPECT_EQ(6, FunctionPassRunCount3);
370 EXPECT_EQ(1, ModuleAnalysisRuns);
371 EXPECT_EQ(4, SCCAnalysisRuns);
372 EXPECT_EQ(6, FunctionAnalysisRuns);
373 EXPECT_EQ(6, ImmutableFunctionAnalysisRuns);
375 EXPECT_EQ(14, AnalyzedInstrCount1);
376 EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
377 EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
380 // Test that an SCC pass which fails to preserve a module analysis does in fact
381 // invalidate that module analysis.
382 TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
383 int ModuleAnalysisRuns = 0;
384 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
386 ModulePassManager MPM;
387 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
389 // The first CGSCC run we preserve everything and make sure that works and
390 // the module analysis is available in the second CGSCC run from the one
391 // required module pass above.
392 CGSCCPassManager CGPM1;
393 int CountFoundModuleAnalysis1 = 0;
394 CGPM1.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C,
395 CGSCCAnalysisManager &AM, LazyCallGraph &CG,
396 CGSCCUpdateResult &UR) {
397 const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
398 if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
399 *C.begin()->getFunction().getParent()))
400 ++CountFoundModuleAnalysis1;
402 return PreservedAnalyses::all();
403 }));
404 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
406 // The second CGSCC run checks that the module analysis got preserved the
407 // previous time and in one SCC fails to preserve it.
408 CGSCCPassManager CGPM2;
409 int CountFoundModuleAnalysis2 = 0;
410 CGPM2.addPass(
411 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
412 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
413 const auto &MAMProxy =
414 AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
415 if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
416 *C.begin()->getFunction().getParent()))
417 ++CountFoundModuleAnalysis2;
419 // Only fail to preserve analyses on one SCC and make sure that gets
420 // propagated.
421 return C.getName() == "(g)" ? PreservedAnalyses::none()
422 : PreservedAnalyses::all();
423 }));
424 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
426 // The third CGSCC run should fail to find a cached module analysis as it
427 // should have been invalidated by the above CGSCC run.
428 CGSCCPassManager CGPM3;
429 int CountFoundModuleAnalysis3 = 0;
430 CGPM3.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C,
431 CGSCCAnalysisManager &AM, LazyCallGraph &CG,
432 CGSCCUpdateResult &UR) {
433 const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
434 if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
435 *C.begin()->getFunction().getParent()))
436 ++CountFoundModuleAnalysis3;
438 return PreservedAnalyses::none();
439 }));
440 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
442 MPM.run(*M, MAM);
444 EXPECT_EQ(1, ModuleAnalysisRuns);
445 EXPECT_EQ(4, CountFoundModuleAnalysis1);
446 EXPECT_EQ(4, CountFoundModuleAnalysis2);
447 EXPECT_EQ(0, CountFoundModuleAnalysis3);
450 // Similar to the above, but test that this works for function passes embedded
451 // *within* a CGSCC layer.
452 TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) {
453 int ModuleAnalysisRuns = 0;
454 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
456 ModulePassManager MPM;
457 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
459 // The first run we preserve everything and make sure that works and the
460 // module analysis is available in the second run from the one required
461 // module pass above.
462 FunctionPassManager FPM1;
463 // Start true and mark false if we ever failed to find a module analysis
464 // because we expect this to succeed for each SCC.
465 bool FoundModuleAnalysis1 = true;
466 FPM1.addPass(LambdaFunctionPass([&](Function &F,
467 FunctionAnalysisManager &AM) {
468 const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
469 if (!MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
470 FoundModuleAnalysis1 = false;
472 return PreservedAnalyses::all();
473 }));
474 CGSCCPassManager CGPM1;
475 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
476 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
478 // The second run checks that the module analysis got preserved the previous
479 // time and in one function fails to preserve it.
480 FunctionPassManager FPM2;
481 // Again, start true and mark false if we ever failed to find a module analysis
482 // because we expect this to succeed for each SCC.
483 bool FoundModuleAnalysis2 = true;
484 FPM2.addPass(LambdaFunctionPass([&](Function &F,
485 FunctionAnalysisManager &AM) {
486 const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
487 if (!MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
488 FoundModuleAnalysis2 = false;
490 // Only fail to preserve analyses on one SCC and make sure that gets
491 // propagated.
492 return F.getName() == "h2" ? PreservedAnalyses::none()
493 : PreservedAnalyses::all();
494 }));
495 CGSCCPassManager CGPM2;
496 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
497 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
499 // The third run should fail to find a cached module analysis as it should
500 // have been invalidated by the above run.
501 FunctionPassManager FPM3;
502 // Start false and mark true if we ever *succeeded* to find a module
503 // analysis, as we expect this to fail for every function.
504 bool FoundModuleAnalysis3 = false;
505 FPM3.addPass(LambdaFunctionPass([&](Function &F,
506 FunctionAnalysisManager &AM) {
507 const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
508 if (MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
509 FoundModuleAnalysis3 = true;
511 return PreservedAnalyses::none();
512 }));
513 CGSCCPassManager CGPM3;
514 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3)));
515 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
517 MPM.run(*M, MAM);
519 EXPECT_EQ(1, ModuleAnalysisRuns);
520 EXPECT_TRUE(FoundModuleAnalysis1);
521 EXPECT_TRUE(FoundModuleAnalysis2);
522 EXPECT_FALSE(FoundModuleAnalysis3);
525 // Test that a Module pass which fails to preserve an SCC analysis in fact
526 // invalidates that analysis.
527 TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysis) {
528 int SCCAnalysisRuns = 0;
529 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
531 ModulePassManager MPM;
533 // First force the analysis to be run.
534 CGSCCPassManager CGPM1;
535 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
536 CGSCCAnalysisManager, LazyCallGraph &,
537 CGSCCUpdateResult &>());
538 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
540 // Now run a module pass that preserves the LazyCallGraph and the proxy but
541 // not the SCC analysis.
542 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
543 PreservedAnalyses PA;
544 PA.preserve<LazyCallGraphAnalysis>();
545 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
546 PA.preserve<FunctionAnalysisManagerModuleProxy>();
547 return PA;
548 }));
550 // And now a second CGSCC run which requires the SCC analysis again. This
551 // will trigger re-running it.
552 CGSCCPassManager CGPM2;
553 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
554 CGSCCAnalysisManager, LazyCallGraph &,
555 CGSCCUpdateResult &>());
556 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
558 MPM.run(*M, MAM);
559 // Two runs and four SCCs.
560 EXPECT_EQ(2 * 4, SCCAnalysisRuns);
563 // Check that marking the SCC analysis preserved is sufficient to avoid
564 // invaliadtion. This should only run the analysis once for each SCC.
565 TEST_F(CGSCCPassManagerTest, TestModulePassCanPreserveSCCAnalysis) {
566 int SCCAnalysisRuns = 0;
567 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
569 ModulePassManager MPM;
571 // First force the analysis to be run.
572 CGSCCPassManager CGPM1;
573 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
574 CGSCCAnalysisManager, LazyCallGraph &,
575 CGSCCUpdateResult &>());
576 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
578 // Now run a module pass that preserves each of the necessary components
579 // (but not everything).
580 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
581 PreservedAnalyses PA;
582 PA.preserve<LazyCallGraphAnalysis>();
583 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
584 PA.preserve<FunctionAnalysisManagerModuleProxy>();
585 PA.preserve<TestSCCAnalysis>();
586 return PA;
587 }));
589 // And now a second CGSCC run which requires the SCC analysis again but find
590 // it in the cache.
591 CGSCCPassManager CGPM2;
592 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
593 CGSCCAnalysisManager, LazyCallGraph &,
594 CGSCCUpdateResult &>());
595 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
597 MPM.run(*M, MAM);
598 // Four SCCs
599 EXPECT_EQ(4, SCCAnalysisRuns);
602 // Check that even when the analysis is preserved, if the SCC information isn't
603 // we still nuke things because the SCC keys could change.
604 TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysisOnCGChange) {
605 int SCCAnalysisRuns = 0;
606 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
608 ModulePassManager MPM;
610 // First force the analysis to be run.
611 CGSCCPassManager CGPM1;
612 CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
613 CGSCCAnalysisManager, LazyCallGraph &,
614 CGSCCUpdateResult &>());
615 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
617 // Now run a module pass that preserves the analysis but not the call
618 // graph or proxy.
619 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
620 PreservedAnalyses PA;
621 PA.preserve<TestSCCAnalysis>();
622 return PA;
623 }));
625 // And now a second CGSCC run which requires the SCC analysis again.
626 CGSCCPassManager CGPM2;
627 CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
628 CGSCCAnalysisManager, LazyCallGraph &,
629 CGSCCUpdateResult &>());
630 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
632 MPM.run(*M, MAM);
633 // Two runs and four SCCs.
634 EXPECT_EQ(2 * 4, SCCAnalysisRuns);
637 // Test that an SCC pass which fails to preserve a Function analysis in fact
638 // invalidates that analysis.
639 TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesFunctionAnalysis) {
640 int FunctionAnalysisRuns = 0;
641 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
643 // Create a very simple module with a single function and SCC to make testing
644 // these issues much easier.
645 std::unique_ptr<Module> M = parseIR("declare void @g()\n"
646 "declare void @h()\n"
647 "define void @f() {\n"
648 "entry:\n"
649 " call void @g()\n"
650 " call void @h()\n"
651 " ret void\n"
652 "}\n");
654 CGSCCPassManager CGPM;
656 // First force the analysis to be run.
657 FunctionPassManager FPM1;
658 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
659 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
661 // Now run a module pass that preserves the LazyCallGraph and proxy but not
662 // the SCC analysis.
663 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
664 LazyCallGraph &, CGSCCUpdateResult &) {
665 PreservedAnalyses PA;
666 PA.preserve<LazyCallGraphAnalysis>();
667 return PA;
668 }));
670 // And now a second CGSCC run which requires the SCC analysis again. This
671 // will trigger re-running it.
672 FunctionPassManager FPM2;
673 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
674 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
676 ModulePassManager MPM;
677 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
678 MPM.run(*M, MAM);
679 EXPECT_EQ(2, FunctionAnalysisRuns);
682 // Check that marking the SCC analysis preserved is sufficient. This should
683 // only run the analysis once the SCC.
684 TEST_F(CGSCCPassManagerTest, TestSCCPassCanPreserveFunctionAnalysis) {
685 int FunctionAnalysisRuns = 0;
686 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
688 // Create a very simple module with a single function and SCC to make testing
689 // these issues much easier.
690 std::unique_ptr<Module> M = parseIR("declare void @g()\n"
691 "declare void @h()\n"
692 "define void @f() {\n"
693 "entry:\n"
694 " call void @g()\n"
695 " call void @h()\n"
696 " ret void\n"
697 "}\n");
699 CGSCCPassManager CGPM;
701 // First force the analysis to be run.
702 FunctionPassManager FPM1;
703 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
704 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
706 // Now run a module pass that preserves each of the necessary components
707 // (but
708 // not everything).
709 CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
710 LazyCallGraph &, CGSCCUpdateResult &) {
711 PreservedAnalyses PA;
712 PA.preserve<LazyCallGraphAnalysis>();
713 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
714 PA.preserve<TestFunctionAnalysis>();
715 return PA;
716 }));
718 // And now a second CGSCC run which requires the SCC analysis again but find
719 // it in the cache.
720 FunctionPassManager FPM2;
721 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
722 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
724 ModulePassManager MPM;
725 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
726 MPM.run(*M, MAM);
727 EXPECT_EQ(1, FunctionAnalysisRuns);
730 // Note that there is no test for invalidating the call graph or other
731 // structure with an SCC pass because there is no mechanism to do that from
732 // withinsuch a pass. Instead, such a pass has to directly update the call
733 // graph structure.
735 // Test that a madule pass invalidates function analyses when the CGSCC proxies
736 // and pass manager.
737 TEST_F(CGSCCPassManagerTest,
738 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC) {
739 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
741 int FunctionAnalysisRuns = 0;
742 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
744 ModulePassManager MPM;
746 // First force the analysis to be run.
747 FunctionPassManager FPM1;
748 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
749 CGSCCPassManager CGPM1;
750 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
751 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
753 // Now run a module pass that preserves the LazyCallGraph and proxies but not
754 // the Function analysis.
755 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
756 PreservedAnalyses PA;
757 PA.preserve<LazyCallGraphAnalysis>();
758 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
759 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
760 PA.preserve<FunctionAnalysisManagerModuleProxy>();
761 return PA;
762 }));
764 // And now a second CGSCC run which requires the SCC analysis again. This
765 // will trigger re-running it.
766 FunctionPassManager FPM2;
767 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
768 CGSCCPassManager CGPM2;
769 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
770 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
772 MPM.run(*M, MAM);
773 // Two runs and 6 functions.
774 EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
777 // Check that by marking the function pass and proxies as preserved, this
778 // propagates all the way through.
779 TEST_F(CGSCCPassManagerTest,
780 TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC) {
781 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
783 int FunctionAnalysisRuns = 0;
784 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
786 ModulePassManager MPM;
788 // First force the analysis to be run.
789 FunctionPassManager FPM1;
790 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
791 CGSCCPassManager CGPM1;
792 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
793 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
795 // Now run a module pass that preserves the LazyCallGraph, the proxy, and
796 // the Function analysis.
797 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
798 PreservedAnalyses PA;
799 PA.preserve<LazyCallGraphAnalysis>();
800 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
801 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
802 PA.preserve<FunctionAnalysisManagerModuleProxy>();
803 PA.preserve<TestFunctionAnalysis>();
804 return PA;
805 }));
807 // And now a second CGSCC run which requires the SCC analysis again. This
808 // will trigger re-running it.
809 FunctionPassManager FPM2;
810 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
811 CGSCCPassManager CGPM2;
812 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
813 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
815 MPM.run(*M, MAM);
816 // One run and 6 functions.
817 EXPECT_EQ(6, FunctionAnalysisRuns);
820 // Check that if the lazy call graph itself isn't preserved we still manage to
821 // invalidate everything.
822 TEST_F(CGSCCPassManagerTest,
823 TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange) {
824 MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
826 int FunctionAnalysisRuns = 0;
827 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
829 ModulePassManager MPM;
831 // First force the analysis to be run.
832 FunctionPassManager FPM1;
833 FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
834 CGSCCPassManager CGPM1;
835 CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
836 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
838 // Now run a module pass that preserves the LazyCallGraph but not the
839 // Function analysis.
840 MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
841 PreservedAnalyses PA;
842 return PA;
843 }));
845 // And now a second CGSCC run which requires the SCC analysis again. This
846 // will trigger re-running it.
847 FunctionPassManager FPM2;
848 FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
849 CGSCCPassManager CGPM2;
850 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
851 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
853 MPM.run(*M, MAM);
854 // Two runs and 6 functions.
855 EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
858 /// A test CGSCC-level analysis pass which caches in its result another
859 /// analysis pass and uses it to serve queries. This requires the result to
860 /// invalidate itself when its dependency is invalidated.
862 /// FIXME: Currently this doesn't also depend on a function analysis, and if it
863 /// did we would fail to invalidate it correctly.
864 struct TestIndirectSCCAnalysis
865 : public AnalysisInfoMixin<TestIndirectSCCAnalysis> {
866 struct Result {
867 Result(TestSCCAnalysis::Result &SCCDep, TestModuleAnalysis::Result &MDep)
868 : SCCDep(SCCDep), MDep(MDep) {}
869 TestSCCAnalysis::Result &SCCDep;
870 TestModuleAnalysis::Result &MDep;
872 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
873 CGSCCAnalysisManager::Invalidator &Inv) {
874 auto PAC = PA.getChecker<TestIndirectSCCAnalysis>();
875 return !(PAC.preserved() ||
876 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
877 Inv.invalidate<TestSCCAnalysis>(C, PA);
881 TestIndirectSCCAnalysis(int &Runs, ModuleAnalysisManager &MAM)
882 : Runs(Runs), MAM(MAM) {}
884 /// Run the analysis pass over the function and return a result.
885 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
886 LazyCallGraph &CG) {
887 ++Runs;
888 auto &SCCDep = AM.getResult<TestSCCAnalysis>(C, CG);
890 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
891 // For the test, we insist that the module analysis starts off in the
892 // cache. Getting a cached result that isn't stateless triggers an assert.
893 // auto &MDep = *ModuleProxy.getCachedResult<TestModuleAnalysis>(
894 // *C.begin()->getFunction().getParent());
895 // Use MAM, for the purposes of this unittest.
896 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(
897 *C.begin()->getFunction().getParent());
898 // Register the dependency as module analysis dependencies have to be
899 // pre-registered on the proxy.
900 ModuleProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
901 TestIndirectSCCAnalysis>();
903 return Result(SCCDep, MDep);
906 private:
907 friend AnalysisInfoMixin<TestIndirectSCCAnalysis>;
908 static AnalysisKey Key;
910 int &Runs;
911 ModuleAnalysisManager &MAM;
914 AnalysisKey TestIndirectSCCAnalysis::Key;
916 /// A test analysis pass which caches in its result the result from the above
917 /// indirect analysis pass.
919 /// This allows us to ensure that whenever an analysis pass is invalidated due
920 /// to dependencies (especially dependencies across IR units that trigger
921 /// asynchronous invalidation) we correctly detect that this may in turn cause
922 /// other analysis to be invalidated.
923 struct TestDoublyIndirectSCCAnalysis
924 : public AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis> {
925 struct Result {
926 Result(TestIndirectSCCAnalysis::Result &IDep) : IDep(IDep) {}
927 TestIndirectSCCAnalysis::Result &IDep;
929 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
930 CGSCCAnalysisManager::Invalidator &Inv) {
931 auto PAC = PA.getChecker<TestDoublyIndirectSCCAnalysis>();
932 return !(PAC.preserved() ||
933 PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
934 Inv.invalidate<TestIndirectSCCAnalysis>(C, PA);
938 TestDoublyIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
940 /// Run the analysis pass over the function and return a result.
941 Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
942 LazyCallGraph &CG) {
943 ++Runs;
944 auto &IDep = AM.getResult<TestIndirectSCCAnalysis>(C, CG);
945 return Result(IDep);
948 private:
949 friend AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis>;
950 static AnalysisKey Key;
952 int &Runs;
955 AnalysisKey TestDoublyIndirectSCCAnalysis::Key;
957 /// A test analysis pass which caches results from three different IR unit
958 /// layers and requires intermediate layers to correctly propagate the entire
959 /// distance.
960 struct TestIndirectFunctionAnalysis
961 : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
962 struct Result {
963 Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep,
964 TestSCCAnalysis::Result &SCCDep)
965 : FDep(FDep), MDep(MDep), SCCDep(SCCDep) {}
966 TestFunctionAnalysis::Result &FDep;
967 TestModuleAnalysis::Result &MDep;
968 TestSCCAnalysis::Result &SCCDep;
970 bool invalidate(Function &F, const PreservedAnalyses &PA,
971 FunctionAnalysisManager::Invalidator &Inv) {
972 auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
973 return !(PAC.preserved() ||
974 PAC.preservedSet<AllAnalysesOn<Function>>()) ||
975 Inv.invalidate<TestFunctionAnalysis>(F, PA);
979 TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM,
980 CGSCCAnalysisManager &CGAM)
981 : Runs(Runs), MAM(MAM), CGAM(CGAM) {}
983 /// Run the analysis pass over the function and return a result.
984 Result run(Function &F, FunctionAnalysisManager &AM) {
985 ++Runs;
986 auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
988 auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
989 // For the test, we insist that the module analysis starts off in the
990 // cache. Getting a cached result that isn't stateless triggers an assert.
991 // Use MAM, for the purposes of this unittest.
992 auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
993 // Register the dependency as module analysis dependencies have to be
994 // pre-registered on the proxy.
995 ModuleProxy.registerOuterAnalysisInvalidation<
996 TestModuleAnalysis, TestIndirectFunctionAnalysis>();
998 // For the test we assume this is run inside a CGSCC pass manager.
999 // Use MAM, for the purposes of this unittest.
1000 const LazyCallGraph &CG =
1001 *MAM.getCachedResult<LazyCallGraphAnalysis>(*F.getParent());
1002 auto &CGSCCProxy = AM.getResult<CGSCCAnalysisManagerFunctionProxy>(F);
1003 // For the test, we insist that the CGSCC analysis starts off in the cache.
1004 // Getting a cached result that isn't stateless triggers an assert.
1005 // Use CGAM, for the purposes of this unittest.
1006 auto &SCCDep =
1007 *CGAM.getCachedResult<TestSCCAnalysis>(*CG.lookupSCC(*CG.lookup(F)));
1008 // Register the dependency as CGSCC analysis dependencies have to be
1009 // pre-registered on the proxy.
1010 CGSCCProxy.registerOuterAnalysisInvalidation<
1011 TestSCCAnalysis, TestIndirectFunctionAnalysis>();
1013 return Result(FDep, MDep, SCCDep);
1016 private:
1017 friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
1018 static AnalysisKey Key;
1020 int &Runs;
1021 ModuleAnalysisManager &MAM;
1022 CGSCCAnalysisManager &CGAM;
1025 AnalysisKey TestIndirectFunctionAnalysis::Key;
1027 TEST_F(CGSCCPassManagerTest, TestIndirectAnalysisInvalidation) {
1028 int ModuleAnalysisRuns = 0;
1029 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
1031 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
1032 DoublyIndirectSCCAnalysisRuns = 0;
1033 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
1034 CGAM.registerPass(
1035 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); });
1036 CGAM.registerPass([&] {
1037 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
1040 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
1041 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
1042 FAM.registerPass([&] {
1043 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM,
1044 CGAM);
1047 ModulePassManager MPM;
1049 int FunctionCount = 0;
1050 CGSCCPassManager CGPM;
1051 // First just use the analysis to get the function count and preserve
1052 // everything.
1053 CGPM.addPass(
1054 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1055 LazyCallGraph &CG, CGSCCUpdateResult &) {
1056 auto &DoublyIndirectResult =
1057 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1058 auto &IndirectResult = DoublyIndirectResult.IDep;
1059 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1060 return PreservedAnalyses::all();
1061 }));
1062 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1063 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1065 // Next, invalidate
1066 // - both analyses for the (f) and (x) SCCs,
1067 // - just the underlying (indirect) analysis for (g) SCC, and
1068 // - just the direct analysis for (h1,h2,h3) SCC.
1069 CGPM.addPass(
1070 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1071 LazyCallGraph &CG, CGSCCUpdateResult &) {
1072 auto &DoublyIndirectResult =
1073 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1074 auto &IndirectResult = DoublyIndirectResult.IDep;
1075 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1076 auto PA = PreservedAnalyses::none();
1077 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1078 PA.preserveSet<AllAnalysesOn<Function>>();
1079 if (C.getName() == "(g)")
1080 PA.preserve<TestSCCAnalysis>();
1081 else if (C.getName() == "(h3, h1, h2)")
1082 PA.preserve<TestIndirectSCCAnalysis>();
1083 return PA;
1084 }));
1085 // Finally, use the analysis again on each SCC (and function), forcing
1086 // re-computation for all of them.
1087 CGPM.addPass(
1088 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1089 LazyCallGraph &CG, CGSCCUpdateResult &) {
1090 auto &DoublyIndirectResult =
1091 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1092 auto &IndirectResult = DoublyIndirectResult.IDep;
1093 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1094 return PreservedAnalyses::all();
1095 }));
1096 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1097 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1099 // Create a second CGSCC pass manager. This will cause the module-level
1100 // invalidation to occur, which will force yet another invalidation of the
1101 // indirect SCC-level analysis as the module analysis it depends on gets
1102 // invalidated.
1103 CGSCCPassManager CGPM2;
1104 CGPM2.addPass(
1105 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1106 LazyCallGraph &CG, CGSCCUpdateResult &) {
1107 auto &DoublyIndirectResult =
1108 AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1109 auto &IndirectResult = DoublyIndirectResult.IDep;
1110 FunctionCount += IndirectResult.SCCDep.FunctionCount;
1111 return PreservedAnalyses::all();
1112 }));
1113 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
1114 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1116 // Add a requires pass to populate the module analysis and then our CGSCC
1117 // pass pipeline.
1118 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1119 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1120 // Now require the module analysis again (it will have been invalidated once)
1121 // and then use it again from our second CGSCC pipeline..
1122 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1123 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
1124 MPM.run(*M, MAM);
1126 // There are generally two possible runs for each of the four SCCs. But
1127 // for one SCC, we only invalidate the indirect analysis so the base one
1128 // only gets run seven times.
1129 EXPECT_EQ(7, SCCAnalysisRuns);
1130 // The module analysis pass should be run twice here.
1131 EXPECT_EQ(2, ModuleAnalysisRuns);
1132 // The indirect analysis is invalidated (either directly or indirectly) three
1133 // times for each of four SCCs.
1134 EXPECT_EQ(3 * 4, IndirectSCCAnalysisRuns);
1135 EXPECT_EQ(3 * 4, DoublyIndirectSCCAnalysisRuns);
1137 // We run the indirect function analysis once per function the first time.
1138 // Then we re-run it for every SCC but "(g)". Then we re-run it for every
1139 // function again.
1140 EXPECT_EQ(6 + 5 + 6, IndirectFunctionAnalysisRuns);
1142 // Four passes count each of six functions once (via SCCs).
1143 EXPECT_EQ(4 * 6, FunctionCount);
1146 TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) {
1147 int ModuleAnalysisRuns = 0;
1148 MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
1150 int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
1151 DoublyIndirectSCCAnalysisRuns = 0;
1152 CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
1153 CGAM.registerPass(
1154 [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); });
1155 CGAM.registerPass([&] {
1156 return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
1159 int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
1160 FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
1161 FAM.registerPass([&] {
1162 return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM,
1163 CGAM);
1166 ModulePassManager MPM;
1168 CGSCCPassManager CGPM;
1169 // First just use the analysis to get the function count and preserve
1170 // everything.
1171 using RequireTestIndirectFunctionAnalysisPass =
1172 RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>;
1173 using RequireTestDoublyIndirectSCCAnalysisPass =
1174 RequireAnalysisPass<TestDoublyIndirectSCCAnalysis, LazyCallGraph::SCC,
1175 CGSCCAnalysisManager, LazyCallGraph &,
1176 CGSCCUpdateResult &>;
1177 CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1178 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1179 RequireTestIndirectFunctionAnalysisPass()));
1181 // Next, we inject an SCC pass that invalidates everything for the `(h3, h1,
1182 // h2)` SCC but also deletes the call edge from `h2` to `h3` and updates the
1183 // CG. This should successfully invalidate (and force to be re-run) all the
1184 // analyses for that SCC and for the functions.
1185 CGPM.addPass(
1186 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1187 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1188 (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1189 if (C.getName() != "(h3, h1, h2)")
1190 return PreservedAnalyses::all();
1192 // Build the preserved set.
1193 auto PA = PreservedAnalyses::none();
1194 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1195 PA.preserve<TestIndirectSCCAnalysis>();
1196 PA.preserve<TestDoublyIndirectSCCAnalysis>();
1198 // Delete the call from `h2` to `h3`.
1199 auto &H2N = *llvm::find_if(
1200 C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
1201 auto &H2F = H2N.getFunction();
1202 auto &H3F = *cast<CallInst>(H2F.begin()->begin())->getCalledFunction();
1203 assert(H3F.getName() == "h3" && "Wrong called function!");
1204 H2F.begin()->begin()->eraseFromParent();
1205 // Insert a bitcast of `h3` so that we retain a ref edge to it.
1206 (void)CastInst::CreatePointerCast(
1207 &H3F, PointerType::getUnqual(H2F.getContext()), "dummy",
1208 H2F.begin()->begin());
1210 // Now update the call graph.
1211 auto &NewC =
1212 updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM);
1213 assert(&NewC != &C && "Should get a new SCC due to update!");
1214 (void)&NewC;
1216 return PA;
1217 }));
1218 // Now use the analysis again on each SCC and function, forcing
1219 // re-computation for all of them.
1220 CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1221 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1222 RequireTestIndirectFunctionAnalysisPass()));
1224 // Create another CGSCC pipeline that requires all the analyses again.
1225 CGSCCPassManager CGPM2;
1226 CGPM2.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1227 CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
1228 RequireTestIndirectFunctionAnalysisPass()));
1230 // Next we inject an SCC pass that finds the `(h2)` SCC, adds a call to `h3`
1231 // back to `h2`, and then invalidates everything for what will then be the
1232 // `(h3, h1, h2)` SCC again.
1233 CGSCCPassManager CGPM3;
1234 CGPM3.addPass(
1235 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1236 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1237 (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1238 if (C.getName() != "(h2)")
1239 return PreservedAnalyses::all();
1241 // Build the preserved set.
1242 auto PA = PreservedAnalyses::none();
1243 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1244 PA.preserve<TestIndirectSCCAnalysis>();
1245 PA.preserve<TestDoublyIndirectSCCAnalysis>();
1247 // Delete the bitcast of `h3` that we added earlier.
1248 auto &H2N = *C.begin();
1249 auto &H2F = H2N.getFunction();
1250 auto &H3F = *cast<Function>(cast<BitCastInst>(H2F.begin()->begin())->getOperand(0));
1251 assert(H3F.getName() == "h3" && "Wrong called function!");
1252 H2F.begin()->begin()->eraseFromParent();
1253 // And insert a call to `h3`.
1254 (void)CallInst::Create(&H3F, {}, "", H2F.begin()->begin());
1256 // Now update the call graph.
1257 auto &NewC =
1258 updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM);
1259 assert(&NewC != &C && "Should get a new SCC due to update!");
1260 (void)&NewC;
1262 return PA;
1263 }));
1264 // Now use the analysis again on each SCC and function, forcing
1265 // re-computation for all of them.
1266 CGPM3.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1267 CGPM3.addPass(createCGSCCToFunctionPassAdaptor(
1268 RequireTestIndirectFunctionAnalysisPass()));
1270 // Create a second CGSCC pass manager. This will cause the module-level
1271 // invalidation to occur, which will force yet another invalidation of the
1272 // indirect SCC-level analysis as the module analysis it depends on gets
1273 // invalidated.
1274 CGSCCPassManager CGPM4;
1275 CGPM4.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1276 CGPM4.addPass(createCGSCCToFunctionPassAdaptor(
1277 RequireTestIndirectFunctionAnalysisPass()));
1279 // Add a requires pass to populate the module analysis and then one of our
1280 // CGSCC pipelines. Repeat for all four CGSCC pipelines.
1281 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1282 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1283 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1284 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
1285 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1286 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
1287 MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1288 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM4)));
1289 MPM.run(*M, MAM);
1291 // We run over four SCCs the first time. But then we split an SCC into three.
1292 // And then we merge those three back into one. However, this also
1293 // invalidates all three SCCs further down in the PO walk.
1294 EXPECT_EQ(4 + 3 + 3, SCCAnalysisRuns);
1295 // The module analysis pass should be run three times.
1296 EXPECT_EQ(3, ModuleAnalysisRuns);
1297 // We run over four SCCs the first time. Then over the two new ones. Then the
1298 // entire module is invalidated causing a full run over all seven. Then we
1299 // fold three SCCs back to one, re-compute for it and the two SCCs above it
1300 // in the graph, and then run over the whole module again.
1301 EXPECT_EQ(4 + 2 + 7 + 3 + 4, IndirectSCCAnalysisRuns);
1302 EXPECT_EQ(4 + 2 + 7 + 3 + 4, DoublyIndirectSCCAnalysisRuns);
1304 // First we run over all six functions. Then we re-run it over three when we
1305 // split their SCCs. Then we re-run over the whole module. Then we re-run
1306 // over three functions merged back into a single SCC, then those three
1307 // functions again, the two functions in SCCs above it in the graph, and then
1308 // over the whole module again.
1309 EXPECT_EQ(6 + 3 + 6 + 3 + 2 + 6, FunctionAnalysisRuns);
1311 // Re run the function analysis over the entire module, and then re-run it
1312 // over the `(h3, h1, h2)` SCC due to invalidation. Then we re-run it over
1313 // the entire module, then the three functions merged back into a single SCC,
1314 // those three functions again, then the two functions in SCCs above it in
1315 // the graph, and then over the whole module.
1316 EXPECT_EQ(6 + 3 + 6 + 3 + 2 + 6, IndirectFunctionAnalysisRuns);
1319 // The (negative) tests below check for assertions so we only run them if NDEBUG
1320 // is not defined.
1321 #ifndef NDEBUG
1323 struct LambdaSCCPassNoPreserve : public PassInfoMixin<LambdaSCCPassNoPreserve> {
1324 template <typename T>
1325 LambdaSCCPassNoPreserve(T &&Arg) : Func(std::forward<T>(Arg)) {}
1327 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1328 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1329 Func(C, AM, CG, UR);
1330 PreservedAnalyses PA;
1331 // We update the core CGSCC data structures and so can preserve the proxy to
1332 // the function analysis manager.
1333 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1334 return PA;
1337 std::function<void(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
1338 LazyCallGraph &, CGSCCUpdateResult &)>
1339 Func;
1342 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses0) {
1343 CGSCCPassManager CGPM;
1344 CGPM.addPass(LambdaSCCPassNoPreserve(
1345 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1346 CGSCCUpdateResult &UR) {
1347 if (C.getName() != "(h3, h1, h2)")
1348 return;
1350 auto &FAM =
1351 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1352 Function *FnX = M->getFunction("x");
1353 Function *FnH1 = M->getFunction("h1");
1354 Function *FnH2 = M->getFunction("h2");
1355 Function *FnH3 = M->getFunction("h3");
1356 ASSERT_NE(FnX, nullptr);
1357 ASSERT_NE(FnH1, nullptr);
1358 ASSERT_NE(FnH2, nullptr);
1359 ASSERT_NE(FnH3, nullptr);
1361 // And insert a call to `h1`, `h2`, and `h3`.
1362 BasicBlock::iterator IP = FnH2->getEntryBlock().begin();
1363 (void)CallInst::Create(FnH1, {}, "", IP);
1364 (void)CallInst::Create(FnH2, {}, "", IP);
1365 (void)CallInst::Create(FnH3, {}, "", IP);
1367 auto &H2N = *llvm::find_if(
1368 C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
1369 ASSERT_NO_FATAL_FAILURE(
1370 updateCGAndAnalysisManagerForCGSCCPass(CG, C, H2N, AM, UR, FAM));
1371 }));
1373 ModulePassManager MPM;
1374 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1375 MPM.run(*M, MAM);
1378 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses1) {
1379 CGSCCPassManager CGPM;
1380 CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
1381 CGSCCAnalysisManager &AM,
1382 LazyCallGraph &CG,
1383 CGSCCUpdateResult &UR) {
1384 if (C.getName() != "(h3, h1, h2)")
1385 return;
1387 auto &FAM =
1388 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1389 Function *FnX = M->getFunction("x");
1390 Function *FnH1 = M->getFunction("h1");
1391 Function *FnH2 = M->getFunction("h2");
1392 Function *FnH3 = M->getFunction("h3");
1393 ASSERT_NE(FnX, nullptr);
1394 ASSERT_NE(FnH1, nullptr);
1395 ASSERT_NE(FnH2, nullptr);
1396 ASSERT_NE(FnH3, nullptr);
1398 // And insert a call to `h1`, `h2`, and `h3`.
1399 BasicBlock::iterator IP = FnH2->getEntryBlock().begin();
1400 (void)CallInst::Create(FnH1, {}, "", IP);
1401 (void)CallInst::Create(FnH2, {}, "", IP);
1402 (void)CallInst::Create(FnH3, {}, "", IP);
1404 auto &H2N = *llvm::find_if(
1405 C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
1406 ASSERT_DEATH(
1407 updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM),
1408 "Any new calls should be modeled as");
1409 }));
1411 ModulePassManager MPM;
1412 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1413 MPM.run(*M, MAM);
1416 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses2) {
1417 CGSCCPassManager CGPM;
1418 CGPM.addPass(LambdaSCCPassNoPreserve(
1419 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1420 CGSCCUpdateResult &UR) {
1421 if (C.getName() != "(f)")
1422 return;
1424 auto &FAM =
1425 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1426 Function *FnF = M->getFunction("f");
1427 Function *FnH2 = M->getFunction("h2");
1428 ASSERT_NE(FnF, nullptr);
1429 ASSERT_NE(FnH2, nullptr);
1431 // And insert a call to `h2`
1432 BasicBlock::iterator IP = FnF->getEntryBlock().begin();
1433 (void)CallInst::Create(FnH2, {}, "", IP);
1435 auto &FN = *llvm::find_if(
1436 C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
1437 ASSERT_NO_FATAL_FAILURE(
1438 updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM));
1439 }));
1441 ModulePassManager MPM;
1442 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1443 MPM.run(*M, MAM);
1446 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses3) {
1447 CGSCCPassManager CGPM;
1448 CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
1449 CGSCCAnalysisManager &AM,
1450 LazyCallGraph &CG,
1451 CGSCCUpdateResult &UR) {
1452 if (C.getName() != "(f)")
1453 return;
1455 auto &FAM =
1456 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1457 Function *FnF = M->getFunction("f");
1458 Function *FnH2 = M->getFunction("h2");
1459 ASSERT_NE(FnF, nullptr);
1460 ASSERT_NE(FnH2, nullptr);
1462 // And insert a call to `h2`
1463 BasicBlock::iterator IP = FnF->getEntryBlock().begin();
1464 (void)CallInst::Create(FnH2, {}, "", IP);
1466 auto &FN = *llvm::find_if(
1467 C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
1468 ASSERT_DEATH(
1469 updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR, FAM),
1470 "Any new calls should be modeled as");
1471 }));
1473 ModulePassManager MPM;
1474 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1475 MPM.run(*M, MAM);
1478 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses4) {
1479 CGSCCPassManager CGPM;
1480 CGPM.addPass(LambdaSCCPassNoPreserve(
1481 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1482 CGSCCUpdateResult &UR) {
1483 if (C.getName() != "(f)")
1484 return;
1486 auto &FAM =
1487 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1488 Function *FnF = M->getFunction("f");
1489 Function *FnewF = Function::Create(FnF->getFunctionType(),
1490 FnF->getLinkage(), "newF", *M);
1491 BasicBlock *BB = BasicBlock::Create(FnewF->getContext(), "", FnewF);
1492 ReturnInst::Create(FnewF->getContext(), BB);
1494 // And insert a call to `newF`
1495 BasicBlock::iterator IP = FnF->getEntryBlock().begin();
1496 (void)CallInst::Create(FnewF, {}, "", IP);
1498 // Use the CallGraphUpdater to update the call graph for the new
1499 // function.
1500 CallGraphUpdater CGU;
1501 CGU.initialize(CG, C, AM, UR);
1502 CGU.registerOutlinedFunction(*FnF, *FnewF);
1504 auto &FN = *llvm::find_if(
1505 C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
1507 ASSERT_NO_FATAL_FAILURE(
1508 updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM));
1509 }));
1511 ModulePassManager MPM;
1512 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1513 MPM.run(*M, MAM);
1516 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses5) {
1517 CGSCCPassManager CGPM;
1518 CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
1519 CGSCCAnalysisManager &AM,
1520 LazyCallGraph &CG,
1521 CGSCCUpdateResult &UR) {
1522 if (C.getName() != "(f)")
1523 return;
1525 auto &FAM =
1526 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1527 Function *FnF = M->getFunction("f");
1528 Function *FnewF =
1529 Function::Create(FnF->getFunctionType(), FnF->getLinkage(), "newF", *M);
1530 BasicBlock *BB = BasicBlock::Create(FnewF->getContext(), "", FnewF);
1531 ReturnInst::Create(FnewF->getContext(), BB);
1533 // Use the CallGraphUpdater to update the call graph for the new
1534 // function.
1535 CallGraphUpdater CGU;
1536 CGU.initialize(CG, C, AM, UR);
1538 // And insert a call to `newF`
1539 BasicBlock::iterator IP = FnF->getEntryBlock().begin();
1540 (void)CallInst::Create(FnewF, {}, "", IP);
1542 auto &FN = *llvm::find_if(
1543 C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
1545 ASSERT_DEATH(updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM),
1546 "should already have an associated node");
1547 }));
1549 ModulePassManager MPM;
1550 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1551 MPM.run(*M, MAM);
1554 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses6) {
1555 CGSCCPassManager CGPM;
1556 CGPM.addPass(LambdaSCCPassNoPreserve(
1557 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1558 CGSCCUpdateResult &UR) {
1559 if (C.getName() != "(h3, h1, h2)")
1560 return;
1562 Function *FnX = M->getFunction("x");
1563 Function *FnH1 = M->getFunction("h1");
1564 Function *FnH2 = M->getFunction("h2");
1565 Function *FnH3 = M->getFunction("h3");
1566 ASSERT_NE(FnX, nullptr);
1567 ASSERT_NE(FnH1, nullptr);
1568 ASSERT_NE(FnH2, nullptr);
1569 ASSERT_NE(FnH3, nullptr);
1571 // And insert a call to `h1`, `h2`, and `h3`.
1572 BasicBlock::iterator IP = FnH2->getEntryBlock().begin();
1573 (void)CallInst::Create(FnH1, {}, "", IP);
1574 (void)CallInst::Create(FnH2, {}, "", IP);
1575 (void)CallInst::Create(FnH3, {}, "", IP);
1577 // Use the CallGraphUpdater to update the call graph for the new
1578 // function.
1579 CallGraphUpdater CGU;
1580 CGU.initialize(CG, C, AM, UR);
1581 ASSERT_NO_FATAL_FAILURE(CGU.reanalyzeFunction(*FnH2));
1582 }));
1584 ModulePassManager MPM;
1585 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1586 MPM.run(*M, MAM);
1589 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses7) {
1590 CGSCCPassManager CGPM;
1591 CGPM.addPass(LambdaSCCPassNoPreserve(
1592 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1593 CGSCCUpdateResult &UR) {
1594 if (C.getName() != "(f)")
1595 return;
1597 Function *FnF = M->getFunction("f");
1598 Function *FnH2 = M->getFunction("h2");
1599 ASSERT_NE(FnF, nullptr);
1600 ASSERT_NE(FnH2, nullptr);
1602 // And insert a call to `h2`
1603 BasicBlock::iterator IP = FnF->getEntryBlock().begin();
1604 (void)CallInst::Create(FnH2, {}, "", IP);
1606 // Use the CallGraphUpdater to update the call graph for the new
1607 // function.
1608 CallGraphUpdater CGU;
1609 CGU.initialize(CG, C, AM, UR);
1610 ASSERT_NO_FATAL_FAILURE(CGU.reanalyzeFunction(*FnF));
1611 }));
1613 ModulePassManager MPM;
1614 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1615 MPM.run(*M, MAM);
1618 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses8) {
1619 CGSCCPassManager CGPM;
1620 CGPM.addPass(LambdaSCCPassNoPreserve(
1621 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1622 CGSCCUpdateResult &UR) {
1623 if (C.getName() != "(f)")
1624 return;
1626 Function *FnF = M->getFunction("f");
1627 Function *FnewF = Function::Create(FnF->getFunctionType(),
1628 FnF->getLinkage(), "newF", *M);
1629 BasicBlock *BB = BasicBlock::Create(FnewF->getContext(), "", FnewF);
1630 auto *RI = ReturnInst::Create(FnewF->getContext(), BB);
1631 while (FnF->getEntryBlock().size() > 1)
1632 FnF->getEntryBlock().front().moveBefore(RI);
1633 ASSERT_NE(FnF, nullptr);
1635 // Create an unused constant that is referencing the old (=replaced)
1636 // function.
1637 ConstantExpr::getPtrToInt(FnF, Type::getInt64Ty(FnF->getContext()));
1639 // Use the CallGraphUpdater to update the call graph.
1640 CallGraphUpdater CGU;
1641 CGU.initialize(CG, C, AM, UR);
1642 ASSERT_NO_FATAL_FAILURE(CGU.replaceFunctionWith(*FnF, *FnewF));
1643 ASSERT_TRUE(FnF->isDeclaration());
1644 ASSERT_EQ(FnF->getNumUses(), 0U);
1645 }));
1647 ModulePassManager MPM;
1648 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1649 MPM.run(*M, MAM);
1652 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses9) {
1653 CGSCCPassManager CGPM;
1654 CGPM.addPass(LambdaSCCPassNoPreserve(
1655 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1656 CGSCCUpdateResult &UR) {
1657 if (C.getName() != "(f)")
1658 return;
1660 Function *FnF = M->getFunction("f");
1662 // Use the CallGraphUpdater to update the call graph.
1663 CallGraphUpdater CGU;
1664 CGU.initialize(CG, C, AM, UR);
1665 ASSERT_NO_FATAL_FAILURE(CGU.removeFunction(*FnF));
1666 ASSERT_EQ(M->getFunctionList().size(), 6U);
1667 }));
1669 ModulePassManager MPM;
1670 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1671 MPM.run(*M, MAM);
1672 ASSERT_EQ(M->getFunctionList().size(), 5U);
1675 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses10) {
1676 CGSCCPassManager CGPM;
1677 CGPM.addPass(LambdaSCCPassNoPreserve(
1678 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1679 CGSCCUpdateResult &UR) {
1680 if (C.getName() != "(h3, h1, h2)")
1681 return;
1683 Function *FnX = M->getFunction("x");
1684 Function *FnH1 = M->getFunction("h1");
1685 Function *FnH2 = M->getFunction("h2");
1686 Function *FnH3 = M->getFunction("h3");
1687 ASSERT_NE(FnX, nullptr);
1688 ASSERT_NE(FnH1, nullptr);
1689 ASSERT_NE(FnH2, nullptr);
1690 ASSERT_NE(FnH3, nullptr);
1692 // And insert a call to `h1`, and `h3`.
1693 BasicBlock::iterator IP = FnH1->getEntryBlock().begin();
1694 (void)CallInst::Create(FnH1, {}, "", IP);
1695 (void)CallInst::Create(FnH3, {}, "", IP);
1697 // Remove the `h2` call.
1698 ASSERT_TRUE(isa<CallBase>(IP));
1699 ASSERT_EQ(cast<CallBase>(IP)->getCalledFunction(), FnH2);
1700 IP->eraseFromParent();
1702 // Use the CallGraphUpdater to update the call graph.
1703 CallGraphUpdater CGU;
1704 CGU.initialize(CG, C, AM, UR);
1705 ASSERT_NO_FATAL_FAILURE(CGU.reanalyzeFunction(*FnH1));
1706 ASSERT_NO_FATAL_FAILURE(CGU.removeFunction(*FnH2));
1707 }));
1709 ModulePassManager MPM;
1710 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1711 MPM.run(*M, MAM);
1714 // Returns a vector containing the SCC's nodes. Useful for not iterating over an
1715 // SCC while mutating it.
1716 static SmallVector<LazyCallGraph::Node *> SCCNodes(LazyCallGraph::SCC &C) {
1717 SmallVector<LazyCallGraph::Node *> Nodes;
1718 for (auto &N : C)
1719 Nodes.push_back(&N);
1721 return Nodes;
1724 // Start with call recursive f, create f -> g and ref recursive f.
1725 TEST_F(CGSCCPassManagerTest, TestInsertionOfNewFunctions1) {
1726 std::unique_ptr<Module> M = parseIR("define void @f() {\n"
1727 "entry:\n"
1728 " call void @f()\n"
1729 " ret void\n"
1730 "}\n");
1732 bool Ran = false;
1734 CGSCCPassManager CGPM;
1735 CGPM.addPass(LambdaSCCPassNoPreserve(
1736 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1737 CGSCCUpdateResult &UR) {
1738 if (Ran)
1739 return;
1741 auto &FAM =
1742 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1744 for (LazyCallGraph::Node *N : SCCNodes(C)) {
1745 Function &F = N->getFunction();
1746 if (F.getName() != "f")
1747 continue;
1749 // Create a new function 'g'.
1750 auto *G = Function::Create(F.getFunctionType(), F.getLinkage(),
1751 F.getAddressSpace(), "g", F.getParent());
1752 auto *GBB =
1753 BasicBlock::Create(F.getParent()->getContext(), "entry", G);
1754 (void)ReturnInst::Create(G->getContext(), GBB);
1755 // Instruct the LazyCallGraph to create a new node for 'g', as the
1756 // single node in a new SCC, into the call graph. As a result
1757 // the call graph is composed of a single RefSCC with two SCCs:
1758 // [(f), (g)].
1760 // "Demote" the 'f -> f' call edge to a ref edge.
1761 // 1. Erase the call edge from 'f' to 'f'.
1762 F.getEntryBlock().front().eraseFromParent();
1763 // 2. Insert a ref edge from 'f' to 'f'.
1764 (void)CastInst::CreatePointerCast(
1765 &F, PointerType::getUnqual(F.getContext()), "f.ref",
1766 F.getEntryBlock().begin());
1767 // 3. Insert a ref edge from 'f' to 'g'.
1768 (void)CastInst::CreatePointerCast(
1769 G, PointerType::getUnqual(F.getContext()), "g.ref",
1770 F.getEntryBlock().begin());
1772 CG.addSplitFunction(F, *G);
1774 ASSERT_FALSE(verifyModule(*F.getParent(), &errs()));
1776 ASSERT_NO_FATAL_FAILURE(
1777 updateCGAndAnalysisManagerForCGSCCPass(CG, C, *N, AM, UR, FAM))
1778 << "Updating the call graph with a demoted, self-referential "
1779 "call edge 'f -> f', and a newly inserted ref edge 'f -> g', "
1780 "caused a fatal failure";
1782 Ran = true;
1784 }));
1786 ModulePassManager MPM;
1787 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1788 MPM.run(*M, MAM);
1789 ASSERT_TRUE(Ran);
1792 // Start with f, end with f -> g1, f -> g2, and f -ref-> (h1 <-ref-> h2).
1793 TEST_F(CGSCCPassManagerTest, TestInsertionOfNewFunctions2) {
1794 std::unique_ptr<Module> M = parseIR("define void @f() {\n"
1795 "entry:\n"
1796 " ret void\n"
1797 "}\n");
1799 bool Ran = false;
1801 CGSCCPassManager CGPM;
1802 CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
1803 CGSCCAnalysisManager &AM,
1804 LazyCallGraph &CG,
1805 CGSCCUpdateResult &UR) {
1806 if (Ran)
1807 return;
1809 auto &FAM =
1810 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1812 for (LazyCallGraph::Node *N : SCCNodes(C)) {
1813 Function &F = N->getFunction();
1814 if (F.getName() != "f")
1815 continue;
1817 // Create g1 and g2.
1818 auto *G1 = Function::Create(F.getFunctionType(), F.getLinkage(),
1819 F.getAddressSpace(), "g1", F.getParent());
1820 auto *G2 = Function::Create(F.getFunctionType(), F.getLinkage(),
1821 F.getAddressSpace(), "g2", F.getParent());
1822 BasicBlock *G1BB =
1823 BasicBlock::Create(F.getParent()->getContext(), "entry", G1);
1824 BasicBlock *G2BB =
1825 BasicBlock::Create(F.getParent()->getContext(), "entry", G2);
1826 (void)ReturnInst::Create(G1->getContext(), G1BB);
1827 (void)ReturnInst::Create(G2->getContext(), G2BB);
1829 // Add 'f -> g1' call edge.
1830 (void)CallInst::Create(G1, {}, "", F.getEntryBlock().begin());
1831 // Add 'f -> g2' call edge.
1832 (void)CallInst::Create(G2, {}, "", F.getEntryBlock().begin());
1834 CG.addSplitFunction(F, *G1);
1835 CG.addSplitFunction(F, *G2);
1837 // Create mutually recursive functions (ref only) 'h1' and 'h2'.
1838 auto *H1 = Function::Create(F.getFunctionType(), F.getLinkage(),
1839 F.getAddressSpace(), "h1", F.getParent());
1840 auto *H2 = Function::Create(F.getFunctionType(), F.getLinkage(),
1841 F.getAddressSpace(), "h2", F.getParent());
1842 BasicBlock *H1BB =
1843 BasicBlock::Create(F.getParent()->getContext(), "entry", H1);
1844 BasicBlock *H2BB =
1845 BasicBlock::Create(F.getParent()->getContext(), "entry", H2);
1846 (void)CastInst::CreatePointerCast(
1847 H2, PointerType::getUnqual(F.getContext()), "h2.ref", H1BB);
1848 (void)ReturnInst::Create(H1->getContext(), H1BB);
1849 (void)CastInst::CreatePointerCast(
1850 H1, PointerType::getUnqual(F.getContext()), "h1.ref", H2BB);
1851 (void)ReturnInst::Create(H2->getContext(), H2BB);
1853 // Add 'f -> h1' ref edge.
1854 (void)CastInst::CreatePointerCast(H1,
1855 PointerType::getUnqual(F.getContext()),
1856 "h1.ref", F.getEntryBlock().begin());
1857 // Add 'f -> h2' ref edge.
1858 (void)CastInst::CreatePointerCast(H2,
1859 PointerType::getUnqual(F.getContext()),
1860 "h2.ref", F.getEntryBlock().begin());
1862 CG.addSplitRefRecursiveFunctions(F, SmallVector<Function *, 2>({H1, H2}));
1864 ASSERT_FALSE(verifyModule(*F.getParent(), &errs()));
1866 ASSERT_NO_FATAL_FAILURE(
1867 updateCGAndAnalysisManagerForCGSCCPass(CG, C, *N, AM, UR, FAM))
1868 << "Updating the call graph with mutually recursive g1 <-> g2, h1 "
1869 "<-> h2 caused a fatal failure";
1871 Ran = true;
1873 }));
1875 ModulePassManager MPM;
1876 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1877 MPM.run(*M, MAM);
1878 ASSERT_TRUE(Ran);
1881 TEST_F(CGSCCPassManagerTest, TestDeletionOfFunctionInNonTrivialRefSCC) {
1882 std::unique_ptr<Module> M = parseIR("define void @f1() {\n"
1883 "entry:\n"
1884 " call void @f2()\n"
1885 " ret void\n"
1886 "}\n"
1887 "define void @f2() {\n"
1888 "entry:\n"
1889 " call void @f1()\n"
1890 " ret void\n"
1891 "}\n");
1893 bool Ran = false;
1894 CGSCCPassManager CGPM;
1895 CGPM.addPass(LambdaSCCPassNoPreserve(
1896 [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1897 CGSCCUpdateResult &UR) {
1898 if (Ran)
1899 return;
1901 LazyCallGraph::Node *N1 = nullptr;
1903 for (LazyCallGraph::Node *N : SCCNodes(C)) {
1904 Function &F = N->getFunction();
1905 if (F.getName() != "f1")
1906 continue;
1907 N1 = N;
1909 Function &F2 = *F.getParent()->getFunction("f2");
1911 // Remove f1 <-> f2 references
1912 F.getEntryBlock().front().eraseFromParent();
1913 F2.getEntryBlock().front().eraseFromParent();
1915 CallGraphUpdater CGU;
1916 CGU.initialize(CG, C, AM, UR);
1917 CGU.removeFunction(F2);
1918 CGU.reanalyzeFunction(F);
1920 Ran = true;
1923 // Check that updateCGAndAnalysisManagerForCGSCCPass() after
1924 // CallGraphUpdater::removeFunction() succeeds.
1925 updateCGAndAnalysisManagerForCGSCCPass(CG, *CG.lookupSCC(*N1), *N1, AM,
1926 UR, FAM);
1927 }));
1929 ModulePassManager MPM;
1930 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1931 MPM.run(*M, MAM);
1933 ASSERT_TRUE(Ran);
1936 TEST_F(CGSCCPassManagerTest, TestInsertionOfNewNonTrivialCallEdge) {
1937 std::unique_ptr<Module> M = parseIR("define void @f1() {\n"
1938 "entry:\n"
1939 " %a = bitcast void ()* @f4 to i8*\n"
1940 " %b = bitcast void ()* @f2 to i8*\n"
1941 " ret void\n"
1942 "}\n"
1943 "define void @f2() {\n"
1944 "entry:\n"
1945 " %a = bitcast void ()* @f1 to i8*\n"
1946 " %b = bitcast void ()* @f3 to i8*\n"
1947 " ret void\n"
1948 "}\n"
1949 "define void @f3() {\n"
1950 "entry:\n"
1951 " %a = bitcast void ()* @f2 to i8*\n"
1952 " %b = bitcast void ()* @f4 to i8*\n"
1953 " ret void\n"
1954 "}\n"
1955 "define void @f4() {\n"
1956 "entry:\n"
1957 " %a = bitcast void ()* @f3 to i8*\n"
1958 " %b = bitcast void ()* @f1 to i8*\n"
1959 " ret void\n"
1960 "}\n");
1962 bool Ran = false;
1963 CGSCCPassManager CGPM;
1964 CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
1965 CGSCCAnalysisManager &AM,
1966 LazyCallGraph &CG,
1967 CGSCCUpdateResult &UR) {
1968 if (Ran)
1969 return;
1971 auto &FAM =
1972 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1974 for (LazyCallGraph::Node *N : SCCNodes(C)) {
1975 Function &F = N->getFunction();
1976 if (F.getName() != "f1")
1977 continue;
1979 Function *F3 = F.getParent()->getFunction("f3");
1980 ASSERT_TRUE(F3 != nullptr);
1982 // Create call from f1 to f3.
1983 (void)CallInst::Create(F3, {}, "",
1984 F.getEntryBlock().getTerminator()->getIterator());
1986 ASSERT_NO_FATAL_FAILURE(
1987 updateCGAndAnalysisManagerForCGSCCPass(CG, C, *N, AM, UR, FAM))
1988 << "Updating the call graph with mutually recursive g1 <-> g2, h1 "
1989 "<-> h2 caused a fatal failure";
1991 Ran = true;
1993 }));
1995 ModulePassManager MPM;
1996 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1997 MPM.run(*M, MAM);
1999 ASSERT_TRUE(Ran);
2002 TEST_F(CGSCCPassManagerTest, TestFunctionPassesAreQueriedForInvalidation) {
2003 std::unique_ptr<Module> M = parseIR("define void @f() { ret void }");
2004 CGSCCPassManager CGPM;
2005 bool SCCCalled = false;
2006 FunctionPassManager FPM;
2007 int ImmRuns = 0;
2008 FAM.registerPass([&] { return TestImmutableFunctionAnalysis(ImmRuns); });
2009 FPM.addPass(RequireAnalysisPass<TestImmutableFunctionAnalysis, Function>());
2010 CGPM.addPass(
2011 LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
2012 LazyCallGraph &CG, CGSCCUpdateResult &UR) {
2013 SCCCalled = true;
2014 return PreservedAnalyses::none();
2015 }));
2016 CGPM.addPass(createCGSCCToFunctionPassAdaptor(
2017 RequireAnalysisPass<TestImmutableFunctionAnalysis, Function>()));
2018 ModulePassManager MPM;
2020 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
2021 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
2022 MPM.run(*M, MAM);
2023 ASSERT_EQ(ImmRuns, 1);
2024 ASSERT_TRUE(SCCCalled);
2027 #endif
2028 } // namespace