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 //===----------------------------------------------------------------------===//
8 
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/Function.h"
14 #include "llvm/IR/InstIterator.h"
15 #include "llvm/IR/Instructions.h"
16 #include "llvm/IR/LLVMContext.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/IR/PassManager.h"
19 #include "llvm/IR/Verifier.h"
20 #include "llvm/Support/SourceMgr.h"
21 #include "llvm/Transforms/Utils/CallGraphUpdater.h"
22 #include "gtest/gtest.h"
23 
24 using namespace llvm;
25 
26 namespace {
27 
28 class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
29 public:
30   struct Result {
Result__anon7444d0500111::TestModuleAnalysis::Result31     Result(int Count) : FunctionCount(Count) {}
32     int FunctionCount;
invalidate__anon7444d0500111::TestModuleAnalysis::Result33     bool invalidate(Module &, const PreservedAnalyses &PA,
34                     ModuleAnalysisManager::Invalidator &) {
35       // Check whether the analysis or all analyses on modules have been
36       // preserved.
37       auto PAC = PA.getChecker<TestModuleAnalysis>();
38       return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>());
39     }
40   };
41 
TestModuleAnalysis(int & Runs)42   TestModuleAnalysis(int &Runs) : Runs(Runs) {}
43 
run(Module & M,ModuleAnalysisManager & AM)44   Result run(Module &M, ModuleAnalysisManager &AM) {
45     ++Runs;
46     return Result(M.size());
47   }
48 
49 private:
50   friend AnalysisInfoMixin<TestModuleAnalysis>;
51   static AnalysisKey Key;
52 
53   int &Runs;
54 };
55 
56 AnalysisKey TestModuleAnalysis::Key;
57 
58 class TestSCCAnalysis : public AnalysisInfoMixin<TestSCCAnalysis> {
59 public:
60   struct Result {
Result__anon7444d0500111::TestSCCAnalysis::Result61     Result(int Count) : FunctionCount(Count) {}
62     int FunctionCount;
invalidate__anon7444d0500111::TestSCCAnalysis::Result63     bool invalidate(LazyCallGraph::SCC &, const PreservedAnalyses &PA,
64                     CGSCCAnalysisManager::Invalidator &) {
65       // Check whether the analysis or all analyses on SCCs have been
66       // preserved.
67       auto PAC = PA.getChecker<TestSCCAnalysis>();
68       return !(PAC.preserved() ||
69                PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>());
70     }
71   };
72 
TestSCCAnalysis(int & Runs)73   TestSCCAnalysis(int &Runs) : Runs(Runs) {}
74 
run(LazyCallGraph::SCC & C,CGSCCAnalysisManager & AM,LazyCallGraph &)75   Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &) {
76     ++Runs;
77     return Result(C.size());
78   }
79 
80 private:
81   friend AnalysisInfoMixin<TestSCCAnalysis>;
82   static AnalysisKey Key;
83 
84   int &Runs;
85 };
86 
87 AnalysisKey TestSCCAnalysis::Key;
88 
89 class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
90 public:
91   struct Result {
Result__anon7444d0500111::TestFunctionAnalysis::Result92     Result(int Count) : InstructionCount(Count) {}
93     int InstructionCount;
invalidate__anon7444d0500111::TestFunctionAnalysis::Result94     bool invalidate(Function &, const PreservedAnalyses &PA,
95                     FunctionAnalysisManager::Invalidator &) {
96       // Check whether the analysis or all analyses on functions have been
97       // preserved.
98       auto PAC = PA.getChecker<TestFunctionAnalysis>();
99       return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>());
100     }
101   };
102 
TestFunctionAnalysis(int & Runs)103   TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
104 
run(Function & F,FunctionAnalysisManager & AM)105   Result run(Function &F, FunctionAnalysisManager &AM) {
106     ++Runs;
107     int Count = 0;
108     for (Instruction &I : instructions(F)) {
109       (void)I;
110       ++Count;
111     }
112     return Result(Count);
113   }
114 
115 private:
116   friend AnalysisInfoMixin<TestFunctionAnalysis>;
117   static AnalysisKey Key;
118 
119   int &Runs;
120 };
121 
122 AnalysisKey TestFunctionAnalysis::Key;
123 
124 class TestImmutableFunctionAnalysis
125     : public AnalysisInfoMixin<TestImmutableFunctionAnalysis> {
126 public:
127   struct Result {
invalidate__anon7444d0500111::TestImmutableFunctionAnalysis::Result128     bool invalidate(Function &, const PreservedAnalyses &,
129                     FunctionAnalysisManager::Invalidator &) {
130       return false;
131     }
132   };
133 
TestImmutableFunctionAnalysis(int & Runs)134   TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {}
135 
run(Function & F,FunctionAnalysisManager & AM)136   Result run(Function &F, FunctionAnalysisManager &AM) {
137     ++Runs;
138     return Result();
139   }
140 
141 private:
142   friend AnalysisInfoMixin<TestImmutableFunctionAnalysis>;
143   static AnalysisKey Key;
144 
145   int &Runs;
146 };
147 
148 AnalysisKey TestImmutableFunctionAnalysis::Key;
149 
150 struct LambdaModulePass : public PassInfoMixin<LambdaModulePass> {
151   template <typename T>
LambdaModulePass__anon7444d0500111::LambdaModulePass152   LambdaModulePass(T &&Arg) : Func(std::forward<T>(Arg)) {}
153 
run__anon7444d0500111::LambdaModulePass154   PreservedAnalyses run(Module &F, ModuleAnalysisManager &AM) {
155     return Func(F, AM);
156   }
157 
158   std::function<PreservedAnalyses(Module &, ModuleAnalysisManager &)> Func;
159 };
160 
161 struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> {
LambdaSCCPass__anon7444d0500111::LambdaSCCPass162   template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
163 
run__anon7444d0500111::LambdaSCCPass164   PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
165                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
166     return Func(C, AM, CG, UR);
167   }
168 
169   std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
170                                   LazyCallGraph &, CGSCCUpdateResult &)>
171       Func;
172 };
173 
174 struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> {
175   template <typename T>
LambdaFunctionPass__anon7444d0500111::LambdaFunctionPass176   LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
177 
run__anon7444d0500111::LambdaFunctionPass178   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
179     return Func(F, AM);
180   }
181 
182   std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func;
183 };
184 
parseIR(const char * IR)185 std::unique_ptr<Module> parseIR(const char *IR) {
186   // We just use a static context here. This is never called from multiple
187   // threads so it is harmless no matter how it is implemented. We just need
188   // the context to outlive the module which it does.
189   static LLVMContext C;
190   SMDiagnostic Err;
191   return parseAssemblyString(IR, Err, C);
192 }
193 
194 class CGSCCPassManagerTest : public ::testing::Test {
195 protected:
196   LLVMContext Context;
197   FunctionAnalysisManager FAM;
198   CGSCCAnalysisManager CGAM;
199   ModuleAnalysisManager MAM;
200 
201   std::unique_ptr<Module> M;
202 
203 public:
CGSCCPassManagerTest()204   CGSCCPassManagerTest()
205       : FAM(), CGAM(), MAM(),
206         M(parseIR(
207             // Define a module with the following call graph, where calls go
208             // out the bottom of nodes and enter the top:
209             //
210             // f
211             // |\   _
212             // | \ / |
213             // g  h1 |
214             // |  |  |
215             // |  h2 |
216             // |  |  |
217             // |  h3 |
218             // | / \_/
219             // |/
220             // x
221             //
222             "define void @x() {\n"
223             "entry:\n"
224             "  ret void\n"
225             "}\n"
226             "define void @h3() {\n"
227             "entry:\n"
228             "  call void @h1()\n"
229             "  ret void\n"
230             "}\n"
231             "define void @h2() {\n"
232             "entry:\n"
233             "  call void @h3()\n"
234             "  call void @x()\n"
235             "  ret void\n"
236             "}\n"
237             "define void @h1() {\n"
238             "entry:\n"
239             "  call void @h2()\n"
240             "  ret void\n"
241             "}\n"
242             "define void @g() {\n"
243             "entry:\n"
244             "  call void @g()\n"
245             "  call void @x()\n"
246             "  ret void\n"
247             "}\n"
248             "define void @f() {\n"
249             "entry:\n"
250             "  call void @g()\n"
251             "  call void @h1()\n"
252             "  ret void\n"
253             "}\n")) {
254     FAM.registerPass([&] { return TargetLibraryAnalysis(); });
255     MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
256     MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
257 
258     // Register required pass instrumentation analysis.
259     MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
260     CGAM.registerPass([&] { return PassInstrumentationAnalysis(); });
261     FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
262 
263     // Cross-register proxies.
264     MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
265     CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); });
266     CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
267     FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
268     FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
269   }
270 };
271 
TEST_F(CGSCCPassManagerTest,Basic)272 TEST_F(CGSCCPassManagerTest, Basic) {
273   int FunctionAnalysisRuns = 0;
274   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
275   int ImmutableFunctionAnalysisRuns = 0;
276   FAM.registerPass([&] {
277     return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns);
278   });
279 
280   int SCCAnalysisRuns = 0;
281   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
282 
283   int ModuleAnalysisRuns = 0;
284   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
285 
286   ModulePassManager MPM;
287   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
288 
289   CGSCCPassManager CGPM1;
290   FunctionPassManager FPM1;
291   int FunctionPassRunCount1 = 0;
292   FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
293     ++FunctionPassRunCount1;
294     return PreservedAnalyses::none();
295   }));
296   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
297 
298   int SCCPassRunCount1 = 0;
299   int AnalyzedInstrCount1 = 0;
300   int AnalyzedSCCFunctionCount1 = 0;
301   int AnalyzedModuleFunctionCount1 = 0;
302   CGPM1.addPass(
303       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
304                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
305         ++SCCPassRunCount1;
306 
307         // Note: The proper way to get to a module pass from a CGSCC pass is
308         // through the ModuleAnalysisManagerCGSCCProxy:
309         // ```
310         // const auto &MAMProxy =
311         //    AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
312         // ```
313         // However getting a stateful analysis is incorrect usage, and the call
314         // to getCachedResult below asserts:
315         // ```
316         // if (TestModuleAnalysis::Result *TMA =
317         //        MAMProxy.getCachedResult<TestModuleAnalysis>(
318         //            *C.begin()->getFunction().getParent()))
319         //   AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
320         // ```
321         // For the purposes of this unittest, use the above MAM directly.
322         if (TestModuleAnalysis::Result *TMA =
323                 MAM.getCachedResult<TestModuleAnalysis>(
324                     *C.begin()->getFunction().getParent()))
325           AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
326 
327         FunctionAnalysisManager &FAM =
328             AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
329         TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
330         AnalyzedSCCFunctionCount1 += AR.FunctionCount;
331         for (LazyCallGraph::Node &N : C) {
332           TestFunctionAnalysis::Result &FAR =
333               FAM.getResult<TestFunctionAnalysis>(N.getFunction());
334           AnalyzedInstrCount1 += FAR.InstructionCount;
335 
336           // Just ensure we get the immutable results.
337           (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction());
338         }
339 
340         return PreservedAnalyses::all();
341       }));
342 
343   FunctionPassManager FPM2;
344   int FunctionPassRunCount2 = 0;
345   FPM2.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
346     ++FunctionPassRunCount2;
347     return PreservedAnalyses::none();
348   }));
349   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
350 
351   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
352 
353   FunctionPassManager FPM3;
354   int FunctionPassRunCount3 = 0;
355   FPM3.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
356     ++FunctionPassRunCount3;
357     return PreservedAnalyses::none();
358   }));
359   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM3)));
360 
361   MPM.run(*M, MAM);
362 
363   EXPECT_EQ(4, SCCPassRunCount1);
364   EXPECT_EQ(6, FunctionPassRunCount1);
365   EXPECT_EQ(6, FunctionPassRunCount2);
366   EXPECT_EQ(6, FunctionPassRunCount3);
367 
368   EXPECT_EQ(1, ModuleAnalysisRuns);
369   EXPECT_EQ(4, SCCAnalysisRuns);
370   EXPECT_EQ(6, FunctionAnalysisRuns);
371   EXPECT_EQ(6, ImmutableFunctionAnalysisRuns);
372 
373   EXPECT_EQ(14, AnalyzedInstrCount1);
374   EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
375   EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
376 }
377 
378 // Test that an SCC pass which fails to preserve a module analysis does in fact
379 // invalidate that module analysis.
TEST_F(CGSCCPassManagerTest,TestSCCPassInvalidatesModuleAnalysis)380 TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
381   int ModuleAnalysisRuns = 0;
382   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
383 
384   ModulePassManager MPM;
385   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
386 
387   // The first CGSCC run we preserve everything and make sure that works and
388   // the module analysis is available in the second CGSCC run from the one
389   // required module pass above.
390   CGSCCPassManager CGPM1;
391   int CountFoundModuleAnalysis1 = 0;
392   CGPM1.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C,
393                                   CGSCCAnalysisManager &AM, LazyCallGraph &CG,
394                                   CGSCCUpdateResult &UR) {
395     const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
396     if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
397             *C.begin()->getFunction().getParent()))
398       ++CountFoundModuleAnalysis1;
399 
400     return PreservedAnalyses::all();
401   }));
402   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
403 
404   // The second CGSCC run checks that the module analysis got preserved the
405   // previous time and in one SCC fails to preserve it.
406   CGSCCPassManager CGPM2;
407   int CountFoundModuleAnalysis2 = 0;
408   CGPM2.addPass(
409       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
410                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
411         const auto &MAMProxy =
412             AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
413         if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
414                 *C.begin()->getFunction().getParent()))
415           ++CountFoundModuleAnalysis2;
416 
417         // Only fail to preserve analyses on one SCC and make sure that gets
418         // propagated.
419         return C.getName() == "(g)" ? PreservedAnalyses::none()
420                                   : PreservedAnalyses::all();
421       }));
422   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
423 
424   // The third CGSCC run should fail to find a cached module analysis as it
425   // should have been invalidated by the above CGSCC run.
426   CGSCCPassManager CGPM3;
427   int CountFoundModuleAnalysis3 = 0;
428   CGPM3.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C,
429                                   CGSCCAnalysisManager &AM, LazyCallGraph &CG,
430                                   CGSCCUpdateResult &UR) {
431     const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
432     if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
433             *C.begin()->getFunction().getParent()))
434       ++CountFoundModuleAnalysis3;
435 
436     return PreservedAnalyses::none();
437   }));
438   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
439 
440   MPM.run(*M, MAM);
441 
442   EXPECT_EQ(1, ModuleAnalysisRuns);
443   EXPECT_EQ(4, CountFoundModuleAnalysis1);
444   EXPECT_EQ(4, CountFoundModuleAnalysis2);
445   EXPECT_EQ(0, CountFoundModuleAnalysis3);
446 }
447 
448 // Similar to the above, but test that this works for function passes embedded
449 // *within* a CGSCC layer.
TEST_F(CGSCCPassManagerTest,TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis)450 TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) {
451   int ModuleAnalysisRuns = 0;
452   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
453 
454   ModulePassManager MPM;
455   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
456 
457   // The first run we preserve everything and make sure that works and the
458   // module analysis is available in the second run from the one required
459   // module pass above.
460   FunctionPassManager FPM1;
461   // Start true and mark false if we ever failed to find a module analysis
462   // because we expect this to succeed for each SCC.
463   bool FoundModuleAnalysis1 = true;
464   FPM1.addPass(LambdaFunctionPass([&](Function &F,
465                                       FunctionAnalysisManager &AM) {
466     const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
467     if (!MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
468       FoundModuleAnalysis1 = false;
469 
470     return PreservedAnalyses::all();
471   }));
472   CGSCCPassManager CGPM1;
473   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
474   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
475 
476   // The second run checks that the module analysis got preserved the previous
477   // time and in one function fails to preserve it.
478   FunctionPassManager FPM2;
479   // Again, start true and mark false if we ever failed to find a module analysis
480   // because we expect this to succeed for each SCC.
481   bool FoundModuleAnalysis2 = true;
482   FPM2.addPass(LambdaFunctionPass([&](Function &F,
483                                       FunctionAnalysisManager &AM) {
484     const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
485     if (!MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
486       FoundModuleAnalysis2 = false;
487 
488     // Only fail to preserve analyses on one SCC and make sure that gets
489     // propagated.
490     return F.getName() == "h2" ? PreservedAnalyses::none()
491                                : PreservedAnalyses::all();
492   }));
493   CGSCCPassManager CGPM2;
494   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
495   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
496 
497   // The third run should fail to find a cached module analysis as it should
498   // have been invalidated by the above run.
499   FunctionPassManager FPM3;
500   // Start false and mark true if we ever *succeeded* to find a module
501   // analysis, as we expect this to fail for every function.
502   bool FoundModuleAnalysis3 = false;
503   FPM3.addPass(LambdaFunctionPass([&](Function &F,
504                                       FunctionAnalysisManager &AM) {
505     const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
506     if (MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
507       FoundModuleAnalysis3 = true;
508 
509     return PreservedAnalyses::none();
510   }));
511   CGSCCPassManager CGPM3;
512   CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3)));
513   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
514 
515   MPM.run(*M, MAM);
516 
517   EXPECT_EQ(1, ModuleAnalysisRuns);
518   EXPECT_TRUE(FoundModuleAnalysis1);
519   EXPECT_TRUE(FoundModuleAnalysis2);
520   EXPECT_FALSE(FoundModuleAnalysis3);
521 }
522 
523 // Test that a Module pass which fails to preserve an SCC analysis in fact
524 // invalidates that analysis.
TEST_F(CGSCCPassManagerTest,TestModulePassInvalidatesSCCAnalysis)525 TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysis) {
526   int SCCAnalysisRuns = 0;
527   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
528 
529   ModulePassManager MPM;
530 
531   // First force the analysis to be run.
532   CGSCCPassManager CGPM1;
533   CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
534                                     CGSCCAnalysisManager, LazyCallGraph &,
535                                     CGSCCUpdateResult &>());
536   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
537 
538   // Now run a module pass that preserves the LazyCallGraph and the proxy but
539   // not the SCC analysis.
540   MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
541     PreservedAnalyses PA;
542     PA.preserve<LazyCallGraphAnalysis>();
543     PA.preserve<CGSCCAnalysisManagerModuleProxy>();
544     PA.preserve<FunctionAnalysisManagerModuleProxy>();
545     return PA;
546   }));
547 
548   // And now a second CGSCC run which requires the SCC analysis again. This
549   // will trigger re-running it.
550   CGSCCPassManager CGPM2;
551   CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
552                                     CGSCCAnalysisManager, LazyCallGraph &,
553                                     CGSCCUpdateResult &>());
554   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
555 
556   MPM.run(*M, MAM);
557   // Two runs and four SCCs.
558   EXPECT_EQ(2 * 4, SCCAnalysisRuns);
559 }
560 
561 // Check that marking the SCC analysis preserved is sufficient to avoid
562 // invaliadtion. This should only run the analysis once for each SCC.
TEST_F(CGSCCPassManagerTest,TestModulePassCanPreserveSCCAnalysis)563 TEST_F(CGSCCPassManagerTest, TestModulePassCanPreserveSCCAnalysis) {
564   int SCCAnalysisRuns = 0;
565   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
566 
567   ModulePassManager MPM;
568 
569   // First force the analysis to be run.
570   CGSCCPassManager CGPM1;
571   CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
572                                     CGSCCAnalysisManager, LazyCallGraph &,
573                                     CGSCCUpdateResult &>());
574   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
575 
576   // Now run a module pass that preserves each of the necessary components
577   // (but not everything).
578   MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
579     PreservedAnalyses PA;
580     PA.preserve<LazyCallGraphAnalysis>();
581     PA.preserve<CGSCCAnalysisManagerModuleProxy>();
582     PA.preserve<FunctionAnalysisManagerModuleProxy>();
583     PA.preserve<TestSCCAnalysis>();
584     return PA;
585   }));
586 
587   // And now a second CGSCC run which requires the SCC analysis again but find
588   // it in the cache.
589   CGSCCPassManager CGPM2;
590   CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
591                                     CGSCCAnalysisManager, LazyCallGraph &,
592                                     CGSCCUpdateResult &>());
593   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
594 
595   MPM.run(*M, MAM);
596   // Four SCCs
597   EXPECT_EQ(4, SCCAnalysisRuns);
598 }
599 
600 // Check that even when the analysis is preserved, if the SCC information isn't
601 // we still nuke things because the SCC keys could change.
TEST_F(CGSCCPassManagerTest,TestModulePassInvalidatesSCCAnalysisOnCGChange)602 TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysisOnCGChange) {
603   int SCCAnalysisRuns = 0;
604   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
605 
606   ModulePassManager MPM;
607 
608   // First force the analysis to be run.
609   CGSCCPassManager CGPM1;
610   CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
611                                     CGSCCAnalysisManager, LazyCallGraph &,
612                                     CGSCCUpdateResult &>());
613   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
614 
615   // Now run a module pass that preserves the analysis but not the call
616   // graph or proxy.
617   MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
618     PreservedAnalyses PA;
619     PA.preserve<TestSCCAnalysis>();
620     return PA;
621   }));
622 
623   // And now a second CGSCC run which requires the SCC analysis again.
624   CGSCCPassManager CGPM2;
625   CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
626                                     CGSCCAnalysisManager, LazyCallGraph &,
627                                     CGSCCUpdateResult &>());
628   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
629 
630   MPM.run(*M, MAM);
631   // Two runs and four SCCs.
632   EXPECT_EQ(2 * 4, SCCAnalysisRuns);
633 }
634 
635 // Test that an SCC pass which fails to preserve a Function analysis in fact
636 // invalidates that analysis.
TEST_F(CGSCCPassManagerTest,TestSCCPassInvalidatesFunctionAnalysis)637 TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesFunctionAnalysis) {
638   int FunctionAnalysisRuns = 0;
639   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
640 
641   // Create a very simple module with a single function and SCC to make testing
642   // these issues much easier.
643   std::unique_ptr<Module> M = parseIR("declare void @g()\n"
644                                       "declare void @h()\n"
645                                       "define void @f() {\n"
646                                       "entry:\n"
647                                       "  call void @g()\n"
648                                       "  call void @h()\n"
649                                       "  ret void\n"
650                                       "}\n");
651 
652   CGSCCPassManager CGPM;
653 
654   // First force the analysis to be run.
655   FunctionPassManager FPM1;
656   FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
657   CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
658 
659   // Now run a module pass that preserves the LazyCallGraph and proxy but not
660   // the SCC analysis.
661   CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
662                                  LazyCallGraph &, CGSCCUpdateResult &) {
663     PreservedAnalyses PA;
664     PA.preserve<LazyCallGraphAnalysis>();
665     return PA;
666   }));
667 
668   // And now a second CGSCC run which requires the SCC analysis again. This
669   // will trigger re-running it.
670   FunctionPassManager FPM2;
671   FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
672   CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
673 
674   ModulePassManager MPM;
675   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
676   MPM.run(*M, MAM);
677   EXPECT_EQ(2, FunctionAnalysisRuns);
678 }
679 
680 // Check that marking the SCC analysis preserved is sufficient. This should
681 // only run the analysis once the SCC.
TEST_F(CGSCCPassManagerTest,TestSCCPassCanPreserveFunctionAnalysis)682 TEST_F(CGSCCPassManagerTest, TestSCCPassCanPreserveFunctionAnalysis) {
683   int FunctionAnalysisRuns = 0;
684   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
685 
686   // Create a very simple module with a single function and SCC to make testing
687   // these issues much easier.
688   std::unique_ptr<Module> M = parseIR("declare void @g()\n"
689                                       "declare void @h()\n"
690                                       "define void @f() {\n"
691                                       "entry:\n"
692                                       "  call void @g()\n"
693                                       "  call void @h()\n"
694                                       "  ret void\n"
695                                       "}\n");
696 
697   CGSCCPassManager CGPM;
698 
699   // First force the analysis to be run.
700   FunctionPassManager FPM1;
701   FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
702   CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
703 
704   // Now run a module pass that preserves each of the necessary components
705   // (but
706   // not everything).
707   CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
708                                  LazyCallGraph &, CGSCCUpdateResult &) {
709     PreservedAnalyses PA;
710     PA.preserve<LazyCallGraphAnalysis>();
711     PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
712     PA.preserve<TestFunctionAnalysis>();
713     return PA;
714   }));
715 
716   // And now a second CGSCC run which requires the SCC analysis again but find
717   // it in the cache.
718   FunctionPassManager FPM2;
719   FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
720   CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
721 
722   ModulePassManager MPM;
723   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
724   MPM.run(*M, MAM);
725   EXPECT_EQ(1, FunctionAnalysisRuns);
726 }
727 
728 // Note that there is no test for invalidating the call graph or other
729 // structure with an SCC pass because there is no mechanism to do that from
730 // withinsuch a pass. Instead, such a pass has to directly update the call
731 // graph structure.
732 
733 // Test that a madule pass invalidates function analyses when the CGSCC proxies
734 // and pass manager.
TEST_F(CGSCCPassManagerTest,TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC)735 TEST_F(CGSCCPassManagerTest,
736        TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC) {
737   MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
738 
739   int FunctionAnalysisRuns = 0;
740   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
741 
742   ModulePassManager MPM;
743 
744   // First force the analysis to be run.
745   FunctionPassManager FPM1;
746   FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
747   CGSCCPassManager CGPM1;
748   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
749   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
750 
751   // Now run a module pass that preserves the LazyCallGraph and proxies but not
752   // the Function analysis.
753   MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
754     PreservedAnalyses PA;
755     PA.preserve<LazyCallGraphAnalysis>();
756     PA.preserve<CGSCCAnalysisManagerModuleProxy>();
757     PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
758     PA.preserve<FunctionAnalysisManagerModuleProxy>();
759     return PA;
760   }));
761 
762   // And now a second CGSCC run which requires the SCC analysis again. This
763   // will trigger re-running it.
764   FunctionPassManager FPM2;
765   FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
766   CGSCCPassManager CGPM2;
767   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
768   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
769 
770   MPM.run(*M, MAM);
771   // Two runs and 6 functions.
772   EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
773 }
774 
775 // Check that by marking the function pass and proxies as preserved, this
776 // propagates all the way through.
TEST_F(CGSCCPassManagerTest,TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC)777 TEST_F(CGSCCPassManagerTest,
778        TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC) {
779   MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
780 
781   int FunctionAnalysisRuns = 0;
782   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
783 
784   ModulePassManager MPM;
785 
786   // First force the analysis to be run.
787   FunctionPassManager FPM1;
788   FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
789   CGSCCPassManager CGPM1;
790   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
791   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
792 
793   // Now run a module pass that preserves the LazyCallGraph, the proxy, and
794   // the Function analysis.
795   MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
796     PreservedAnalyses PA;
797     PA.preserve<LazyCallGraphAnalysis>();
798     PA.preserve<CGSCCAnalysisManagerModuleProxy>();
799     PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
800     PA.preserve<FunctionAnalysisManagerModuleProxy>();
801     PA.preserve<TestFunctionAnalysis>();
802     return PA;
803   }));
804 
805   // And now a second CGSCC run which requires the SCC analysis again. This
806   // will trigger re-running it.
807   FunctionPassManager FPM2;
808   FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
809   CGSCCPassManager CGPM2;
810   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
811   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
812 
813   MPM.run(*M, MAM);
814   // One run and 6 functions.
815   EXPECT_EQ(6, FunctionAnalysisRuns);
816 }
817 
818 // Check that if the lazy call graph itself isn't preserved we still manage to
819 // invalidate everything.
TEST_F(CGSCCPassManagerTest,TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange)820 TEST_F(CGSCCPassManagerTest,
821        TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange) {
822   MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
823 
824   int FunctionAnalysisRuns = 0;
825   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
826 
827   ModulePassManager MPM;
828 
829   // First force the analysis to be run.
830   FunctionPassManager FPM1;
831   FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
832   CGSCCPassManager CGPM1;
833   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
834   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
835 
836   // Now run a module pass that preserves the LazyCallGraph but not the
837   // Function analysis.
838   MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
839     PreservedAnalyses PA;
840     return PA;
841   }));
842 
843   // And now a second CGSCC run which requires the SCC analysis again. This
844   // will trigger re-running it.
845   FunctionPassManager FPM2;
846   FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
847   CGSCCPassManager CGPM2;
848   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
849   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
850 
851   MPM.run(*M, MAM);
852   // Two runs and 6 functions.
853   EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
854 }
855 
856 /// A test CGSCC-level analysis pass which caches in its result another
857 /// analysis pass and uses it to serve queries. This requires the result to
858 /// invalidate itself when its dependency is invalidated.
859 ///
860 /// FIXME: Currently this doesn't also depend on a function analysis, and if it
861 /// did we would fail to invalidate it correctly.
862 struct TestIndirectSCCAnalysis
863     : public AnalysisInfoMixin<TestIndirectSCCAnalysis> {
864   struct Result {
Result__anon7444d0500111::TestIndirectSCCAnalysis::Result865     Result(TestSCCAnalysis::Result &SCCDep, TestModuleAnalysis::Result &MDep)
866         : SCCDep(SCCDep), MDep(MDep) {}
867     TestSCCAnalysis::Result &SCCDep;
868     TestModuleAnalysis::Result &MDep;
869 
invalidate__anon7444d0500111::TestIndirectSCCAnalysis::Result870     bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
871                     CGSCCAnalysisManager::Invalidator &Inv) {
872       auto PAC = PA.getChecker<TestIndirectSCCAnalysis>();
873       return !(PAC.preserved() ||
874                PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
875              Inv.invalidate<TestSCCAnalysis>(C, PA);
876     }
877   };
878 
TestIndirectSCCAnalysis__anon7444d0500111::TestIndirectSCCAnalysis879   TestIndirectSCCAnalysis(int &Runs, ModuleAnalysisManager &MAM)
880       : Runs(Runs), MAM(MAM) {}
881 
882   /// Run the analysis pass over the function and return a result.
run__anon7444d0500111::TestIndirectSCCAnalysis883   Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
884              LazyCallGraph &CG) {
885     ++Runs;
886     auto &SCCDep = AM.getResult<TestSCCAnalysis>(C, CG);
887 
888     auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
889     // For the test, we insist that the module analysis starts off in the
890     // cache. Getting a cached result that isn't stateless triggers an assert.
891     // auto &MDep = *ModuleProxy.getCachedResult<TestModuleAnalysis>(
892     //  *C.begin()->getFunction().getParent());
893     // Use MAM, for the purposes of this unittest.
894     auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(
895         *C.begin()->getFunction().getParent());
896     // Register the dependency as module analysis dependencies have to be
897     // pre-registered on the proxy.
898     ModuleProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
899                                                   TestIndirectSCCAnalysis>();
900 
901     return Result(SCCDep, MDep);
902   }
903 
904 private:
905   friend AnalysisInfoMixin<TestIndirectSCCAnalysis>;
906   static AnalysisKey Key;
907 
908   int &Runs;
909   ModuleAnalysisManager &MAM;
910 };
911 
912 AnalysisKey TestIndirectSCCAnalysis::Key;
913 
914 /// A test analysis pass which caches in its result the result from the above
915 /// indirect analysis pass.
916 ///
917 /// This allows us to ensure that whenever an analysis pass is invalidated due
918 /// to dependencies (especially dependencies across IR units that trigger
919 /// asynchronous invalidation) we correctly detect that this may in turn cause
920 /// other analysis to be invalidated.
921 struct TestDoublyIndirectSCCAnalysis
922     : public AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis> {
923   struct Result {
Result__anon7444d0500111::TestDoublyIndirectSCCAnalysis::Result924     Result(TestIndirectSCCAnalysis::Result &IDep) : IDep(IDep) {}
925     TestIndirectSCCAnalysis::Result &IDep;
926 
invalidate__anon7444d0500111::TestDoublyIndirectSCCAnalysis::Result927     bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
928                     CGSCCAnalysisManager::Invalidator &Inv) {
929       auto PAC = PA.getChecker<TestDoublyIndirectSCCAnalysis>();
930       return !(PAC.preserved() ||
931                PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
932              Inv.invalidate<TestIndirectSCCAnalysis>(C, PA);
933     }
934   };
935 
TestDoublyIndirectSCCAnalysis__anon7444d0500111::TestDoublyIndirectSCCAnalysis936   TestDoublyIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
937 
938   /// Run the analysis pass over the function and return a result.
run__anon7444d0500111::TestDoublyIndirectSCCAnalysis939   Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
940              LazyCallGraph &CG) {
941     ++Runs;
942     auto &IDep = AM.getResult<TestIndirectSCCAnalysis>(C, CG);
943     return Result(IDep);
944   }
945 
946 private:
947   friend AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis>;
948   static AnalysisKey Key;
949 
950   int &Runs;
951 };
952 
953 AnalysisKey TestDoublyIndirectSCCAnalysis::Key;
954 
955 /// A test analysis pass which caches results from three different IR unit
956 /// layers and requires intermediate layers to correctly propagate the entire
957 /// distance.
958 struct TestIndirectFunctionAnalysis
959     : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
960   struct Result {
Result__anon7444d0500111::TestIndirectFunctionAnalysis::Result961     Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep,
962            TestSCCAnalysis::Result &SCCDep)
963         : FDep(FDep), MDep(MDep), SCCDep(SCCDep) {}
964     TestFunctionAnalysis::Result &FDep;
965     TestModuleAnalysis::Result &MDep;
966     TestSCCAnalysis::Result &SCCDep;
967 
invalidate__anon7444d0500111::TestIndirectFunctionAnalysis::Result968     bool invalidate(Function &F, const PreservedAnalyses &PA,
969                     FunctionAnalysisManager::Invalidator &Inv) {
970       auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
971       return !(PAC.preserved() ||
972                PAC.preservedSet<AllAnalysesOn<Function>>()) ||
973              Inv.invalidate<TestFunctionAnalysis>(F, PA);
974     }
975   };
976 
TestIndirectFunctionAnalysis__anon7444d0500111::TestIndirectFunctionAnalysis977   TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM,
978                                CGSCCAnalysisManager &CGAM)
979       : Runs(Runs), MAM(MAM), CGAM(CGAM) {}
980 
981   /// Run the analysis pass over the function and return a result.
run__anon7444d0500111::TestIndirectFunctionAnalysis982   Result run(Function &F, FunctionAnalysisManager &AM) {
983     ++Runs;
984     auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
985 
986     auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
987     // For the test, we insist that the module analysis starts off in the
988     // cache. Getting a cached result that isn't stateless triggers an assert.
989     // Use MAM, for the purposes of this unittest.
990     auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
991     // Register the dependency as module analysis dependencies have to be
992     // pre-registered on the proxy.
993     ModuleProxy.registerOuterAnalysisInvalidation<
994         TestModuleAnalysis, TestIndirectFunctionAnalysis>();
995 
996     // For the test we assume this is run inside a CGSCC pass manager.
997     // Use MAM, for the purposes of this unittest.
998     const LazyCallGraph &CG =
999         *MAM.getCachedResult<LazyCallGraphAnalysis>(*F.getParent());
1000     auto &CGSCCProxy = AM.getResult<CGSCCAnalysisManagerFunctionProxy>(F);
1001     // For the test, we insist that the CGSCC analysis starts off in the cache.
1002     // Getting a cached result that isn't stateless triggers an assert.
1003     // Use CGAM, for the purposes of this unittest.
1004     auto &SCCDep =
1005         *CGAM.getCachedResult<TestSCCAnalysis>(*CG.lookupSCC(*CG.lookup(F)));
1006     // Register the dependency as CGSCC analysis dependencies have to be
1007     // pre-registered on the proxy.
1008     CGSCCProxy.registerOuterAnalysisInvalidation<
1009         TestSCCAnalysis, TestIndirectFunctionAnalysis>();
1010 
1011     return Result(FDep, MDep, SCCDep);
1012   }
1013 
1014 private:
1015   friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
1016   static AnalysisKey Key;
1017 
1018   int &Runs;
1019   ModuleAnalysisManager &MAM;
1020   CGSCCAnalysisManager &CGAM;
1021 };
1022 
1023 AnalysisKey TestIndirectFunctionAnalysis::Key;
1024 
TEST_F(CGSCCPassManagerTest,TestIndirectAnalysisInvalidation)1025 TEST_F(CGSCCPassManagerTest, TestIndirectAnalysisInvalidation) {
1026   int ModuleAnalysisRuns = 0;
1027   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
1028 
1029   int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
1030       DoublyIndirectSCCAnalysisRuns = 0;
1031   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
1032   CGAM.registerPass(
1033       [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); });
1034   CGAM.registerPass([&] {
1035     return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
1036   });
1037 
1038   int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
1039   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
1040   FAM.registerPass([&] {
1041     return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM,
1042                                         CGAM);
1043   });
1044 
1045   ModulePassManager MPM;
1046 
1047   int FunctionCount = 0;
1048   CGSCCPassManager CGPM;
1049   // First just use the analysis to get the function count and preserve
1050   // everything.
1051   CGPM.addPass(
1052       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1053                         LazyCallGraph &CG, CGSCCUpdateResult &) {
1054         auto &DoublyIndirectResult =
1055             AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1056         auto &IndirectResult = DoublyIndirectResult.IDep;
1057         FunctionCount += IndirectResult.SCCDep.FunctionCount;
1058         return PreservedAnalyses::all();
1059       }));
1060   CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1061       RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1062 
1063   // Next, invalidate
1064   //   - both analyses for the (f) and (x) SCCs,
1065   //   - just the underlying (indirect) analysis for (g) SCC, and
1066   //   - just the direct analysis for (h1,h2,h3) SCC.
1067   CGPM.addPass(
1068       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1069                         LazyCallGraph &CG, CGSCCUpdateResult &) {
1070         auto &DoublyIndirectResult =
1071             AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1072         auto &IndirectResult = DoublyIndirectResult.IDep;
1073         FunctionCount += IndirectResult.SCCDep.FunctionCount;
1074         auto PA = PreservedAnalyses::none();
1075         PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1076         PA.preserveSet<AllAnalysesOn<Function>>();
1077         if (C.getName() == "(g)")
1078           PA.preserve<TestSCCAnalysis>();
1079         else if (C.getName() == "(h3, h1, h2)")
1080           PA.preserve<TestIndirectSCCAnalysis>();
1081         return PA;
1082       }));
1083   // Finally, use the analysis again on each SCC (and function), forcing
1084   // re-computation for all of them.
1085   CGPM.addPass(
1086       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1087                         LazyCallGraph &CG, CGSCCUpdateResult &) {
1088         auto &DoublyIndirectResult =
1089             AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1090         auto &IndirectResult = DoublyIndirectResult.IDep;
1091         FunctionCount += IndirectResult.SCCDep.FunctionCount;
1092         return PreservedAnalyses::all();
1093       }));
1094   CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1095       RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1096 
1097   // Create a second CGSCC pass manager. This will cause the module-level
1098   // invalidation to occur, which will force yet another invalidation of the
1099   // indirect SCC-level analysis as the module analysis it depends on gets
1100   // invalidated.
1101   CGSCCPassManager CGPM2;
1102   CGPM2.addPass(
1103       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1104                         LazyCallGraph &CG, CGSCCUpdateResult &) {
1105         auto &DoublyIndirectResult =
1106             AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1107         auto &IndirectResult = DoublyIndirectResult.IDep;
1108         FunctionCount += IndirectResult.SCCDep.FunctionCount;
1109         return PreservedAnalyses::all();
1110       }));
1111   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
1112       RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1113 
1114   // Add a requires pass to populate the module analysis and then our CGSCC
1115   // pass pipeline.
1116   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1117   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1118   // Now require the module analysis again (it will have been invalidated once)
1119   // and then use it again from our second CGSCC pipeline..
1120   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1121   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
1122   MPM.run(*M, MAM);
1123 
1124   // There are generally two possible runs for each of the four SCCs. But
1125   // for one SCC, we only invalidate the indirect analysis so the base one
1126   // only gets run seven times.
1127   EXPECT_EQ(7, SCCAnalysisRuns);
1128   // The module analysis pass should be run twice here.
1129   EXPECT_EQ(2, ModuleAnalysisRuns);
1130   // The indirect analysis is invalidated (either directly or indirectly) three
1131   // times for each of four SCCs.
1132   EXPECT_EQ(3 * 4, IndirectSCCAnalysisRuns);
1133   EXPECT_EQ(3 * 4, DoublyIndirectSCCAnalysisRuns);
1134 
1135   // We run the indirect function analysis once per function the first time.
1136   // Then we re-run it for every SCC but "(g)". Then we re-run it for every
1137   // function again.
1138   EXPECT_EQ(6 + 5 + 6, IndirectFunctionAnalysisRuns);
1139 
1140   // Four passes count each of six functions once (via SCCs).
1141   EXPECT_EQ(4 * 6, FunctionCount);
1142 }
1143 
TEST_F(CGSCCPassManagerTest,TestAnalysisInvalidationCGSCCUpdate)1144 TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) {
1145   int ModuleAnalysisRuns = 0;
1146   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
1147 
1148   int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
1149       DoublyIndirectSCCAnalysisRuns = 0;
1150   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
1151   CGAM.registerPass(
1152       [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); });
1153   CGAM.registerPass([&] {
1154     return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
1155   });
1156 
1157   int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
1158   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
1159   FAM.registerPass([&] {
1160     return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM,
1161                                         CGAM);
1162   });
1163 
1164   ModulePassManager MPM;
1165 
1166   CGSCCPassManager CGPM;
1167   // First just use the analysis to get the function count and preserve
1168   // everything.
1169   using RequireTestIndirectFunctionAnalysisPass =
1170       RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>;
1171   using RequireTestDoublyIndirectSCCAnalysisPass =
1172       RequireAnalysisPass<TestDoublyIndirectSCCAnalysis, LazyCallGraph::SCC,
1173                           CGSCCAnalysisManager, LazyCallGraph &,
1174                           CGSCCUpdateResult &>;
1175   CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1176   CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1177       RequireTestIndirectFunctionAnalysisPass()));
1178 
1179   // Next, we inject an SCC pass that invalidates everything for the `(h3, h1,
1180   // h2)` SCC but also deletes the call edge from `h2` to `h3` and updates the
1181   // CG. This should successfully invalidate (and force to be re-run) all the
1182   // analyses for that SCC and for the functions.
1183   CGPM.addPass(
1184       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1185                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1186         (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1187         if (C.getName() != "(h3, h1, h2)")
1188           return PreservedAnalyses::all();
1189 
1190         // Build the preserved set.
1191         auto PA = PreservedAnalyses::none();
1192         PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1193         PA.preserve<TestIndirectSCCAnalysis>();
1194         PA.preserve<TestDoublyIndirectSCCAnalysis>();
1195 
1196         // Delete the call from `h2` to `h3`.
1197         auto &H2N = *llvm::find_if(
1198             C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
1199         auto &H2F = H2N.getFunction();
1200         auto &H3F = *cast<CallInst>(H2F.begin()->begin())->getCalledFunction();
1201         assert(H3F.getName() == "h3" && "Wrong called function!");
1202         H2F.begin()->begin()->eraseFromParent();
1203         // Insert a bitcast of `h3` so that we retain a ref edge to it.
1204         (void)CastInst::CreatePointerCast(&H3F,
1205                                           Type::getInt8PtrTy(H2F.getContext()),
1206                                           "dummy", &*H2F.begin()->begin());
1207 
1208         // Now update the call graph.
1209         auto &NewC =
1210             updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM);
1211         assert(&NewC != &C && "Should get a new SCC due to update!");
1212         (void)&NewC;
1213 
1214         return PA;
1215       }));
1216   // Now use the analysis again on each SCC and function, forcing
1217   // re-computation for all of them.
1218   CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1219   CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1220       RequireTestIndirectFunctionAnalysisPass()));
1221 
1222   // Create another CGSCC pipeline that requires all the analyses again.
1223   CGSCCPassManager CGPM2;
1224   CGPM2.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1225   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
1226       RequireTestIndirectFunctionAnalysisPass()));
1227 
1228   // Next we inject an SCC pass that finds the `(h2)` SCC, adds a call to `h3`
1229   // back to `h2`, and then invalidates everything for what will then be the
1230   // `(h3, h1, h2)` SCC again.
1231   CGSCCPassManager CGPM3;
1232   CGPM3.addPass(
1233       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1234                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1235         (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1236         if (C.getName() != "(h2)")
1237           return PreservedAnalyses::all();
1238 
1239         // Build the preserved set.
1240         auto PA = PreservedAnalyses::none();
1241         PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1242         PA.preserve<TestIndirectSCCAnalysis>();
1243         PA.preserve<TestDoublyIndirectSCCAnalysis>();
1244 
1245         // Delete the bitcast of `h3` that we added earlier.
1246         auto &H2N = *C.begin();
1247         auto &H2F = H2N.getFunction();
1248         auto &H3F = *cast<Function>(cast<BitCastInst>(H2F.begin()->begin())->getOperand(0));
1249         assert(H3F.getName() == "h3" && "Wrong called function!");
1250         H2F.begin()->begin()->eraseFromParent();
1251         // And insert a call to `h3`.
1252         (void)CallInst::Create(&H3F, {}, "", &*H2F.begin()->begin());
1253 
1254         // Now update the call graph.
1255         auto &NewC =
1256             updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM);
1257         assert(&NewC != &C && "Should get a new SCC due to update!");
1258         (void)&NewC;
1259 
1260         return PA;
1261       }));
1262   // Now use the analysis again on each SCC and function, forcing
1263   // re-computation for all of them.
1264   CGPM3.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1265   CGPM3.addPass(createCGSCCToFunctionPassAdaptor(
1266       RequireTestIndirectFunctionAnalysisPass()));
1267 
1268   // Create a second CGSCC pass manager. This will cause the module-level
1269   // invalidation to occur, which will force yet another invalidation of the
1270   // indirect SCC-level analysis as the module analysis it depends on gets
1271   // invalidated.
1272   CGSCCPassManager CGPM4;
1273   CGPM4.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
1274   CGPM4.addPass(createCGSCCToFunctionPassAdaptor(
1275       RequireTestIndirectFunctionAnalysisPass()));
1276 
1277   // Add a requires pass to populate the module analysis and then one of our
1278   // CGSCC pipelines. Repeat for all four CGSCC pipelines.
1279   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1280   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1281   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1282   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
1283   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1284   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
1285   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1286   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM4)));
1287   MPM.run(*M, MAM);
1288 
1289   // We run over four SCCs the first time. But then we split an SCC into three.
1290   // And then we merge those three back into one. However, this also
1291   // invalidates all three SCCs further down in the PO walk.
1292   EXPECT_EQ(4 + 3 + 3, SCCAnalysisRuns);
1293   // The module analysis pass should be run three times.
1294   EXPECT_EQ(3, ModuleAnalysisRuns);
1295   // We run over four SCCs the first time. Then over the two new ones. Then the
1296   // entire module is invalidated causing a full run over all seven. Then we
1297   // fold three SCCs back to one, re-compute for it and the two SCCs above it
1298   // in the graph, and then run over the whole module again.
1299   EXPECT_EQ(4 + 2 + 7 + 3 + 4, IndirectSCCAnalysisRuns);
1300   EXPECT_EQ(4 + 2 + 7 + 3 + 4, DoublyIndirectSCCAnalysisRuns);
1301 
1302   // First we run over all six functions. Then we re-run it over three when we
1303   // split their SCCs. Then we re-run over the whole module. Then we re-run
1304   // over three functions merged back into a single SCC, then those three
1305   // functions again, the two functions in SCCs above it in the graph, and then
1306   // over the whole module again.
1307   EXPECT_EQ(6 + 3 + 6 + 3 + 2 + 6, FunctionAnalysisRuns);
1308 
1309   // Re run the function analysis over the entire module, and then re-run it
1310   // over the `(h3, h1, h2)` SCC due to invalidation. Then we re-run it over
1311   // the entire module, then the three functions merged back into a single SCC,
1312   // those three functions again, then the two functions in SCCs above it in
1313   // the graph, and then over the whole module.
1314   EXPECT_EQ(6 + 3 + 6 + 3 + 2 + 6, IndirectFunctionAnalysisRuns);
1315 }
1316 
1317 // The (negative) tests below check for assertions so we only run them if NDEBUG
1318 // is not defined.
1319 #ifndef NDEBUG
1320 
1321 struct LambdaSCCPassNoPreserve : public PassInfoMixin<LambdaSCCPassNoPreserve> {
1322   template <typename T>
LambdaSCCPassNoPreserve__anon7444d0500111::LambdaSCCPassNoPreserve1323   LambdaSCCPassNoPreserve(T &&Arg) : Func(std::forward<T>(Arg)) {}
1324 
run__anon7444d0500111::LambdaSCCPassNoPreserve1325   PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1326                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1327     Func(C, AM, CG, UR);
1328     PreservedAnalyses PA;
1329     // We update the core CGSCC data structures and so can preserve the proxy to
1330     // the function analysis manager.
1331     PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1332     return PA;
1333   }
1334 
1335   std::function<void(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
1336                      LazyCallGraph &, CGSCCUpdateResult &)>
1337       Func;
1338 };
1339 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses0)1340 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses0) {
1341   CGSCCPassManager CGPM;
1342   CGPM.addPass(LambdaSCCPassNoPreserve(
1343       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1344           CGSCCUpdateResult &UR) {
1345         if (C.getName() != "(h3, h1, h2)")
1346           return;
1347 
1348         auto &FAM =
1349             AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1350         Function *FnX = M->getFunction("x");
1351         Function *FnH1 = M->getFunction("h1");
1352         Function *FnH2 = M->getFunction("h2");
1353         Function *FnH3 = M->getFunction("h3");
1354         ASSERT_NE(FnX, nullptr);
1355         ASSERT_NE(FnH1, nullptr);
1356         ASSERT_NE(FnH2, nullptr);
1357         ASSERT_NE(FnH3, nullptr);
1358 
1359         // And insert a call to `h1`, `h2`, and `h3`.
1360         Instruction *IP = &FnH2->getEntryBlock().front();
1361         (void)CallInst::Create(FnH1, {}, "", IP);
1362         (void)CallInst::Create(FnH2, {}, "", IP);
1363         (void)CallInst::Create(FnH3, {}, "", IP);
1364 
1365         auto &H2N = *llvm::find_if(
1366             C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
1367         ASSERT_NO_FATAL_FAILURE(
1368             updateCGAndAnalysisManagerForCGSCCPass(CG, C, H2N, AM, UR, FAM));
1369       }));
1370 
1371   ModulePassManager MPM;
1372   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1373   MPM.run(*M, MAM);
1374 }
1375 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses1)1376 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses1) {
1377   CGSCCPassManager CGPM;
1378   CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
1379                                            CGSCCAnalysisManager &AM,
1380                                            LazyCallGraph &CG,
1381                                            CGSCCUpdateResult &UR) {
1382     if (C.getName() != "(h3, h1, h2)")
1383       return;
1384 
1385     auto &FAM =
1386         AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1387     Function *FnX = M->getFunction("x");
1388     Function *FnH1 = M->getFunction("h1");
1389     Function *FnH2 = M->getFunction("h2");
1390     Function *FnH3 = M->getFunction("h3");
1391     ASSERT_NE(FnX, nullptr);
1392     ASSERT_NE(FnH1, nullptr);
1393     ASSERT_NE(FnH2, nullptr);
1394     ASSERT_NE(FnH3, nullptr);
1395 
1396     // And insert a call to `h1`, `h2`, and `h3`.
1397     Instruction *IP = &FnH2->getEntryBlock().front();
1398     (void)CallInst::Create(FnH1, {}, "", IP);
1399     (void)CallInst::Create(FnH2, {}, "", IP);
1400     (void)CallInst::Create(FnH3, {}, "", IP);
1401 
1402     auto &H2N = *llvm::find_if(
1403         C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
1404     ASSERT_DEATH(
1405         updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM),
1406         "Any new calls should be modeled as");
1407   }));
1408 
1409   ModulePassManager MPM;
1410   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1411   MPM.run(*M, MAM);
1412 }
1413 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses2)1414 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses2) {
1415   CGSCCPassManager CGPM;
1416   CGPM.addPass(LambdaSCCPassNoPreserve(
1417       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1418           CGSCCUpdateResult &UR) {
1419         if (C.getName() != "(f)")
1420           return;
1421 
1422         auto &FAM =
1423             AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1424         Function *FnF = M->getFunction("f");
1425         Function *FnH2 = M->getFunction("h2");
1426         ASSERT_NE(FnF, nullptr);
1427         ASSERT_NE(FnH2, nullptr);
1428 
1429         // And insert a call to `h2`
1430         Instruction *IP = &FnF->getEntryBlock().front();
1431         (void)CallInst::Create(FnH2, {}, "", IP);
1432 
1433         auto &FN = *llvm::find_if(
1434             C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
1435         ASSERT_NO_FATAL_FAILURE(
1436             updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM));
1437       }));
1438 
1439   ModulePassManager MPM;
1440   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1441   MPM.run(*M, MAM);
1442 }
1443 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses3)1444 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses3) {
1445   CGSCCPassManager CGPM;
1446   CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
1447                                            CGSCCAnalysisManager &AM,
1448                                            LazyCallGraph &CG,
1449                                            CGSCCUpdateResult &UR) {
1450     if (C.getName() != "(f)")
1451       return;
1452 
1453     auto &FAM =
1454         AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1455     Function *FnF = M->getFunction("f");
1456     Function *FnH2 = M->getFunction("h2");
1457     ASSERT_NE(FnF, nullptr);
1458     ASSERT_NE(FnH2, nullptr);
1459 
1460     // And insert a call to `h2`
1461     Instruction *IP = &FnF->getEntryBlock().front();
1462     (void)CallInst::Create(FnH2, {}, "", IP);
1463 
1464     auto &FN = *llvm::find_if(
1465         C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
1466     ASSERT_DEATH(
1467         updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR, FAM),
1468         "Any new calls should be modeled as");
1469   }));
1470 
1471   ModulePassManager MPM;
1472   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1473   MPM.run(*M, MAM);
1474 }
1475 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses4)1476 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses4) {
1477   CGSCCPassManager CGPM;
1478   CGPM.addPass(LambdaSCCPassNoPreserve(
1479       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1480           CGSCCUpdateResult &UR) {
1481         if (C.getName() != "(f)")
1482           return;
1483 
1484         auto &FAM =
1485             AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1486         Function *FnF = M->getFunction("f");
1487         Function *FnewF = Function::Create(FnF->getFunctionType(),
1488                                            FnF->getLinkage(), "newF", *M);
1489         BasicBlock *BB = BasicBlock::Create(FnewF->getContext(), "", FnewF);
1490         ReturnInst::Create(FnewF->getContext(), BB);
1491 
1492         // And insert a call to `newF`
1493         Instruction *IP = &FnF->getEntryBlock().front();
1494         (void)CallInst::Create(FnewF, {}, "", IP);
1495 
1496         // Use the CallGraphUpdater to update the call graph for the new
1497         // function.
1498         CallGraphUpdater CGU;
1499         CGU.initialize(CG, C, AM, UR);
1500         CGU.registerOutlinedFunction(*FnF, *FnewF);
1501 
1502         auto &FN = *llvm::find_if(
1503             C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
1504 
1505         ASSERT_NO_FATAL_FAILURE(
1506             updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM));
1507       }));
1508 
1509   ModulePassManager MPM;
1510   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1511   MPM.run(*M, MAM);
1512 }
1513 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses5)1514 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses5) {
1515   CGSCCPassManager CGPM;
1516   CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
1517                                            CGSCCAnalysisManager &AM,
1518                                            LazyCallGraph &CG,
1519                                            CGSCCUpdateResult &UR) {
1520     if (C.getName() != "(f)")
1521       return;
1522 
1523     auto &FAM =
1524         AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1525     Function *FnF = M->getFunction("f");
1526     Function *FnewF =
1527         Function::Create(FnF->getFunctionType(), FnF->getLinkage(), "newF", *M);
1528     BasicBlock *BB = BasicBlock::Create(FnewF->getContext(), "", FnewF);
1529     ReturnInst::Create(FnewF->getContext(), BB);
1530 
1531     // Use the CallGraphUpdater to update the call graph for the new
1532     // function.
1533     CallGraphUpdater CGU;
1534     CGU.initialize(CG, C, AM, UR);
1535 
1536     // And insert a call to `newF`
1537     Instruction *IP = &FnF->getEntryBlock().front();
1538     (void)CallInst::Create(FnewF, {}, "", IP);
1539 
1540     auto &FN = *llvm::find_if(
1541         C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
1542 
1543     ASSERT_DEATH(updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM),
1544                  "should already have an associated node");
1545   }));
1546 
1547   ModulePassManager MPM;
1548   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1549   MPM.run(*M, MAM);
1550 }
1551 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses6)1552 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses6) {
1553   CGSCCPassManager CGPM;
1554   CGPM.addPass(LambdaSCCPassNoPreserve(
1555       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1556           CGSCCUpdateResult &UR) {
1557         if (C.getName() != "(h3, h1, h2)")
1558           return;
1559 
1560         Function *FnX = M->getFunction("x");
1561         Function *FnH1 = M->getFunction("h1");
1562         Function *FnH2 = M->getFunction("h2");
1563         Function *FnH3 = M->getFunction("h3");
1564         ASSERT_NE(FnX, nullptr);
1565         ASSERT_NE(FnH1, nullptr);
1566         ASSERT_NE(FnH2, nullptr);
1567         ASSERT_NE(FnH3, nullptr);
1568 
1569         // And insert a call to `h1`, `h2`, and `h3`.
1570         Instruction *IP = &FnH2->getEntryBlock().front();
1571         (void)CallInst::Create(FnH1, {}, "", IP);
1572         (void)CallInst::Create(FnH2, {}, "", IP);
1573         (void)CallInst::Create(FnH3, {}, "", IP);
1574 
1575         // Use the CallGraphUpdater to update the call graph for the new
1576         // function.
1577         CallGraphUpdater CGU;
1578         CGU.initialize(CG, C, AM, UR);
1579         ASSERT_NO_FATAL_FAILURE(CGU.reanalyzeFunction(*FnH2));
1580       }));
1581 
1582   ModulePassManager MPM;
1583   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1584   MPM.run(*M, MAM);
1585 }
1586 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses7)1587 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses7) {
1588   CGSCCPassManager CGPM;
1589   CGPM.addPass(LambdaSCCPassNoPreserve(
1590       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1591           CGSCCUpdateResult &UR) {
1592         if (C.getName() != "(f)")
1593           return;
1594 
1595         Function *FnF = M->getFunction("f");
1596         Function *FnH2 = M->getFunction("h2");
1597         ASSERT_NE(FnF, nullptr);
1598         ASSERT_NE(FnH2, nullptr);
1599 
1600         // And insert a call to `h2`
1601         Instruction *IP = &FnF->getEntryBlock().front();
1602         (void)CallInst::Create(FnH2, {}, "", IP);
1603 
1604         // Use the CallGraphUpdater to update the call graph for the new
1605         // function.
1606         CallGraphUpdater CGU;
1607         CGU.initialize(CG, C, AM, UR);
1608         ASSERT_NO_FATAL_FAILURE(CGU.reanalyzeFunction(*FnF));
1609       }));
1610 
1611   ModulePassManager MPM;
1612   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1613   MPM.run(*M, MAM);
1614 }
1615 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses8)1616 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses8) {
1617   CGSCCPassManager CGPM;
1618   CGPM.addPass(LambdaSCCPassNoPreserve(
1619       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1620           CGSCCUpdateResult &UR) {
1621         if (C.getName() != "(f)")
1622           return;
1623 
1624         Function *FnF = M->getFunction("f");
1625         Function *FnewF = Function::Create(FnF->getFunctionType(),
1626                                            FnF->getLinkage(), "newF", *M);
1627         BasicBlock *BB = BasicBlock::Create(FnewF->getContext(), "", FnewF);
1628         auto *RI = ReturnInst::Create(FnewF->getContext(), BB);
1629         while (FnF->getEntryBlock().size() > 1)
1630           FnF->getEntryBlock().front().moveBefore(RI);
1631         ASSERT_NE(FnF, nullptr);
1632 
1633         // Create an unsused constant that is referencing the old (=replaced)
1634         // function.
1635         ConstantExpr::getBitCast(FnF, Type::getInt8PtrTy(FnF->getContext()));
1636 
1637         // Use the CallGraphUpdater to update the call graph.
1638         CallGraphUpdater CGU;
1639         CGU.initialize(CG, C, AM, UR);
1640         ASSERT_NO_FATAL_FAILURE(CGU.replaceFunctionWith(*FnF, *FnewF));
1641         ASSERT_TRUE(FnF->isDeclaration());
1642         ASSERT_EQ(FnF->getNumUses(), 0U);
1643       }));
1644 
1645   ModulePassManager MPM;
1646   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1647   MPM.run(*M, MAM);
1648 }
1649 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses9)1650 TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses9) {
1651   CGSCCPassManager CGPM;
1652   CGPM.addPass(LambdaSCCPassNoPreserve(
1653       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1654           CGSCCUpdateResult &UR) {
1655         if (C.getName() != "(f)")
1656           return;
1657 
1658         Function *FnF = M->getFunction("f");
1659 
1660         // Use the CallGraphUpdater to update the call graph.
1661         {
1662           CallGraphUpdater CGU;
1663           CGU.initialize(CG, C, AM, UR);
1664           ASSERT_NO_FATAL_FAILURE(CGU.removeFunction(*FnF));
1665           ASSERT_EQ(M->getFunctionList().size(), 6U);
1666         }
1667         ASSERT_EQ(M->getFunctionList().size(), 5U);
1668       }));
1669 
1670   ModulePassManager MPM;
1671   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1672   MPM.run(*M, MAM);
1673 }
1674 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses10)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;
1682 
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);
1691 
1692         // And insert a call to `h1`, and `h3`.
1693         Instruction *IP = &FnH1->getEntryBlock().front();
1694         (void)CallInst::Create(FnH1, {}, "", IP);
1695         (void)CallInst::Create(FnH3, {}, "", IP);
1696 
1697         // Remove the `h2` call.
1698         ASSERT_TRUE(isa<CallBase>(IP));
1699         ASSERT_EQ(cast<CallBase>(IP)->getCalledFunction(), FnH2);
1700         IP->eraseFromParent();
1701 
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       }));
1708 
1709   ModulePassManager MPM;
1710   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1711   MPM.run(*M, MAM);
1712 }
1713 
1714 // Returns a vector containing the SCC's nodes. Useful for not iterating over an
1715 // SCC while mutating it.
SCCNodes(LazyCallGraph::SCC & C)1716 static SmallVector<LazyCallGraph::Node *> SCCNodes(LazyCallGraph::SCC &C) {
1717   SmallVector<LazyCallGraph::Node *> Nodes;
1718   for (auto &N : C)
1719     Nodes.push_back(&N);
1720 
1721   return Nodes;
1722 }
1723 
1724 // Start with call recursive f, create f -> g and ref recursive f.
TEST_F(CGSCCPassManagerTest,TestInsertionOfNewFunctions1)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");
1731 
1732   bool Ran = false;
1733 
1734   CGSCCPassManager CGPM;
1735   CGPM.addPass(LambdaSCCPassNoPreserve(
1736       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1737           CGSCCUpdateResult &UR) {
1738         if (Ran)
1739           return;
1740 
1741         auto &FAM =
1742             AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1743 
1744         for (LazyCallGraph::Node *N : SCCNodes(C)) {
1745           Function &F = N->getFunction();
1746           if (F.getName() != "f")
1747             continue;
1748 
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)].
1759 
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, Type::getInt8PtrTy(F.getContext()), "f.ref",
1766               &F.getEntryBlock().front());
1767           // 3. Insert a ref edge from 'f' to 'g'.
1768           (void)CastInst::CreatePointerCast(
1769               G, Type::getInt8PtrTy(F.getContext()), "g.ref",
1770               &F.getEntryBlock().front());
1771 
1772           CG.addSplitFunction(F, *G);
1773 
1774           ASSERT_FALSE(verifyModule(*F.getParent(), &errs()));
1775 
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";
1781 
1782           Ran = true;
1783         }
1784       }));
1785 
1786   ModulePassManager MPM;
1787   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1788   MPM.run(*M, MAM);
1789   ASSERT_TRUE(Ran);
1790 }
1791 
1792 // Start with f, end with f -> g1, f -> g2, and f -ref-> (h1 <-ref-> h2).
TEST_F(CGSCCPassManagerTest,TestInsertionOfNewFunctions2)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");
1798 
1799   bool Ran = false;
1800 
1801   CGSCCPassManager CGPM;
1802   CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
1803                                            CGSCCAnalysisManager &AM,
1804                                            LazyCallGraph &CG,
1805                                            CGSCCUpdateResult &UR) {
1806     if (Ran)
1807       return;
1808 
1809     auto &FAM =
1810         AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1811 
1812     for (LazyCallGraph::Node *N : SCCNodes(C)) {
1813       Function &F = N->getFunction();
1814       if (F.getName() != "f")
1815         continue;
1816 
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);
1828 
1829       // Add 'f -> g1' call edge.
1830       (void)CallInst::Create(G1, {}, "", &F.getEntryBlock().front());
1831       // Add 'f -> g2' call edge.
1832       (void)CallInst::Create(G2, {}, "", &F.getEntryBlock().front());
1833 
1834       CG.addSplitFunction(F, *G1);
1835       CG.addSplitFunction(F, *G2);
1836 
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(H2, Type::getInt8PtrTy(F.getContext()),
1847                                         "h2.ref", H1BB);
1848       (void)ReturnInst::Create(H1->getContext(), H1BB);
1849       (void)CastInst::CreatePointerCast(H1, Type::getInt8PtrTy(F.getContext()),
1850                                         "h1.ref", H2BB);
1851       (void)ReturnInst::Create(H2->getContext(), H2BB);
1852 
1853       // Add 'f -> h1' ref edge.
1854       (void)CastInst::CreatePointerCast(H1, Type::getInt8PtrTy(F.getContext()),
1855                                         "h1.ref", &F.getEntryBlock().front());
1856       // Add 'f -> h2' ref edge.
1857       (void)CastInst::CreatePointerCast(H2, Type::getInt8PtrTy(F.getContext()),
1858                                         "h2.ref", &F.getEntryBlock().front());
1859 
1860       CG.addSplitRefRecursiveFunctions(F, SmallVector<Function *, 2>({H1, H2}));
1861 
1862       ASSERT_FALSE(verifyModule(*F.getParent(), &errs()));
1863 
1864       ASSERT_NO_FATAL_FAILURE(
1865           updateCGAndAnalysisManagerForCGSCCPass(CG, C, *N, AM, UR, FAM))
1866           << "Updating the call graph with mutually recursive g1 <-> g2, h1 "
1867              "<-> h2 caused a fatal failure";
1868 
1869       Ran = true;
1870     }
1871   }));
1872 
1873   ModulePassManager MPM;
1874   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1875   MPM.run(*M, MAM);
1876   ASSERT_TRUE(Ran);
1877 }
1878 
TEST_F(CGSCCPassManagerTest,TestInsertionOfNewNonTrivialCallEdge)1879 TEST_F(CGSCCPassManagerTest, TestInsertionOfNewNonTrivialCallEdge) {
1880   std::unique_ptr<Module> M = parseIR("define void @f1() {\n"
1881                                       "entry:\n"
1882                                       "  %a = bitcast void ()* @f4 to i8*\n"
1883                                       "  %b = bitcast void ()* @f2 to i8*\n"
1884                                       "  ret void\n"
1885                                       "}\n"
1886                                       "define void @f2() {\n"
1887                                       "entry:\n"
1888                                       "  %a = bitcast void ()* @f1 to i8*\n"
1889                                       "  %b = bitcast void ()* @f3 to i8*\n"
1890                                       "  ret void\n"
1891                                       "}\n"
1892                                       "define void @f3() {\n"
1893                                       "entry:\n"
1894                                       "  %a = bitcast void ()* @f2 to i8*\n"
1895                                       "  %b = bitcast void ()* @f4 to i8*\n"
1896                                       "  ret void\n"
1897                                       "}\n"
1898                                       "define void @f4() {\n"
1899                                       "entry:\n"
1900                                       "  %a = bitcast void ()* @f3 to i8*\n"
1901                                       "  %b = bitcast void ()* @f1 to i8*\n"
1902                                       "  ret void\n"
1903                                       "}\n");
1904 
1905   bool Ran = false;
1906   CGSCCPassManager CGPM;
1907   CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
1908                                            CGSCCAnalysisManager &AM,
1909                                            LazyCallGraph &CG,
1910                                            CGSCCUpdateResult &UR) {
1911     if (Ran)
1912       return;
1913 
1914     auto &FAM =
1915         AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1916 
1917     for (LazyCallGraph::Node *N : SCCNodes(C)) {
1918       Function &F = N->getFunction();
1919       if (F.getName() != "f1")
1920         continue;
1921 
1922       Function *F3 = F.getParent()->getFunction("f3");
1923       ASSERT_TRUE(F3 != nullptr);
1924 
1925       // Create call from f1 to f3.
1926       (void)CallInst::Create(F3, {}, "", F.getEntryBlock().getTerminator());
1927 
1928       ASSERT_NO_FATAL_FAILURE(
1929           updateCGAndAnalysisManagerForCGSCCPass(CG, C, *N, AM, UR, FAM))
1930           << "Updating the call graph with mutually recursive g1 <-> g2, h1 "
1931              "<-> h2 caused a fatal failure";
1932 
1933       Ran = true;
1934     }
1935   }));
1936 
1937   ModulePassManager MPM;
1938   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1939   MPM.run(*M, MAM);
1940 
1941   ASSERT_TRUE(Ran);
1942 }
1943 
TEST_F(CGSCCPassManagerTest,TestFunctionPassesAreQueriedForInvalidation)1944 TEST_F(CGSCCPassManagerTest, TestFunctionPassesAreQueriedForInvalidation) {
1945   std::unique_ptr<Module> M = parseIR("define void @f() { ret void }");
1946   CGSCCPassManager CGPM;
1947   bool SCCCalled = false;
1948   FunctionPassManager FPM;
1949   int ImmRuns = 0;
1950   FAM.registerPass([&] { return TestImmutableFunctionAnalysis(ImmRuns); });
1951   FPM.addPass(RequireAnalysisPass<TestImmutableFunctionAnalysis, Function>());
1952   CGPM.addPass(
1953       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1954                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
1955         SCCCalled = true;
1956         return PreservedAnalyses::none();
1957       }));
1958   CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1959       RequireAnalysisPass<TestImmutableFunctionAnalysis, Function>()));
1960   ModulePassManager MPM;
1961 
1962   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
1963   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1964   MPM.run(*M, MAM);
1965   ASSERT_EQ(ImmRuns, 1);
1966   ASSERT_TRUE(SCCCalled);
1967 }
1968 
1969 #endif
1970 } // namespace
1971