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