174319922SChandler Carruth //===- CGSCCPassManagerTest.cpp -------------------------------------------===//
274319922SChandler Carruth //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
674319922SChandler Carruth //
774319922SChandler Carruth //===----------------------------------------------------------------------===//
874319922SChandler Carruth 
974319922SChandler Carruth #include "llvm/Analysis/CGSCCPassManager.h"
1074319922SChandler Carruth #include "llvm/Analysis/LazyCallGraph.h"
11f59a8387SChandler Carruth #include "llvm/Analysis/TargetLibraryInfo.h"
1274319922SChandler Carruth #include "llvm/AsmParser/Parser.h"
13*823b32fbSBill Wendling #include "llvm/IR/Constants.h"
1474319922SChandler Carruth #include "llvm/IR/Function.h"
1574319922SChandler Carruth #include "llvm/IR/InstIterator.h"
168e140869SCraig Topper #include "llvm/IR/Instructions.h"
1774319922SChandler Carruth #include "llvm/IR/LLVMContext.h"
1874319922SChandler Carruth #include "llvm/IR/Module.h"
1974319922SChandler Carruth #include "llvm/IR/PassManager.h"
204c8c6368SArthur Eubanks #include "llvm/IR/Verifier.h"
2174319922SChandler Carruth #include "llvm/Support/SourceMgr.h"
2272277ecdSJohannes Doerfert #include "llvm/Transforms/Utils/CallGraphUpdater.h"
2374319922SChandler Carruth #include "gtest/gtest.h"
2474319922SChandler Carruth 
2574319922SChandler Carruth using namespace llvm;
2674319922SChandler Carruth 
2774319922SChandler Carruth namespace {
2874319922SChandler Carruth 
29dab4eae2SChandler Carruth class TestModuleAnalysis : public AnalysisInfoMixin<TestModuleAnalysis> {
3074319922SChandler Carruth public:
3174319922SChandler Carruth   struct Result {
Result__anone177e1640111::TestModuleAnalysis::Result3274319922SChandler Carruth     Result(int Count) : FunctionCount(Count) {}
3374319922SChandler Carruth     int FunctionCount;
invalidate__anone177e1640111::TestModuleAnalysis::Result3454356b4bSAlina Sbirlea     bool invalidate(Module &, const PreservedAnalyses &PA,
3554356b4bSAlina Sbirlea                     ModuleAnalysisManager::Invalidator &) {
3654356b4bSAlina Sbirlea       // Check whether the analysis or all analyses on modules have been
3754356b4bSAlina Sbirlea       // preserved.
3854356b4bSAlina Sbirlea       auto PAC = PA.getChecker<TestModuleAnalysis>();
3954356b4bSAlina Sbirlea       return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>());
4054356b4bSAlina Sbirlea     }
4174319922SChandler Carruth   };
4274319922SChandler Carruth 
TestModuleAnalysis(int & Runs)4374319922SChandler Carruth   TestModuleAnalysis(int &Runs) : Runs(Runs) {}
4474319922SChandler Carruth 
run(Module & M,ModuleAnalysisManager & AM)45b47f8010SChandler Carruth   Result run(Module &M, ModuleAnalysisManager &AM) {
4674319922SChandler Carruth     ++Runs;
4774319922SChandler Carruth     return Result(M.size());
4874319922SChandler Carruth   }
4974319922SChandler Carruth 
5074319922SChandler Carruth private:
51dab4eae2SChandler Carruth   friend AnalysisInfoMixin<TestModuleAnalysis>;
52dab4eae2SChandler Carruth   static AnalysisKey Key;
5374319922SChandler Carruth 
5474319922SChandler Carruth   int &Runs;
5574319922SChandler Carruth };
5674319922SChandler Carruth 
57dab4eae2SChandler Carruth AnalysisKey TestModuleAnalysis::Key;
5874319922SChandler Carruth 
59dab4eae2SChandler Carruth class TestSCCAnalysis : public AnalysisInfoMixin<TestSCCAnalysis> {
6074319922SChandler Carruth public:
6174319922SChandler Carruth   struct Result {
Result__anone177e1640111::TestSCCAnalysis::Result6274319922SChandler Carruth     Result(int Count) : FunctionCount(Count) {}
6374319922SChandler Carruth     int FunctionCount;
invalidate__anone177e1640111::TestSCCAnalysis::Result6454356b4bSAlina Sbirlea     bool invalidate(LazyCallGraph::SCC &, const PreservedAnalyses &PA,
6554356b4bSAlina Sbirlea                     CGSCCAnalysisManager::Invalidator &) {
6654356b4bSAlina Sbirlea       // Check whether the analysis or all analyses on SCCs have been
6754356b4bSAlina Sbirlea       // preserved.
6854356b4bSAlina Sbirlea       auto PAC = PA.getChecker<TestSCCAnalysis>();
6954356b4bSAlina Sbirlea       return !(PAC.preserved() ||
7054356b4bSAlina Sbirlea                PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>());
7154356b4bSAlina Sbirlea     }
7274319922SChandler Carruth   };
7374319922SChandler Carruth 
TestSCCAnalysis(int & Runs)7474319922SChandler Carruth   TestSCCAnalysis(int &Runs) : Runs(Runs) {}
7574319922SChandler Carruth 
run(LazyCallGraph::SCC & C,CGSCCAnalysisManager & AM,LazyCallGraph &)7688823468SChandler Carruth   Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &) {
7774319922SChandler Carruth     ++Runs;
7874319922SChandler Carruth     return Result(C.size());
7974319922SChandler Carruth   }
8074319922SChandler Carruth 
8174319922SChandler Carruth private:
82dab4eae2SChandler Carruth   friend AnalysisInfoMixin<TestSCCAnalysis>;
83dab4eae2SChandler Carruth   static AnalysisKey Key;
8474319922SChandler Carruth 
8574319922SChandler Carruth   int &Runs;
8674319922SChandler Carruth };
8774319922SChandler Carruth 
88dab4eae2SChandler Carruth AnalysisKey TestSCCAnalysis::Key;
8974319922SChandler Carruth 
90dab4eae2SChandler Carruth class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
9174319922SChandler Carruth public:
9274319922SChandler Carruth   struct Result {
Result__anone177e1640111::TestFunctionAnalysis::Result9374319922SChandler Carruth     Result(int Count) : InstructionCount(Count) {}
9474319922SChandler Carruth     int InstructionCount;
invalidate__anone177e1640111::TestFunctionAnalysis::Result9554356b4bSAlina Sbirlea     bool invalidate(Function &, const PreservedAnalyses &PA,
9654356b4bSAlina Sbirlea                     FunctionAnalysisManager::Invalidator &) {
9754356b4bSAlina Sbirlea       // Check whether the analysis or all analyses on functions have been
9854356b4bSAlina Sbirlea       // preserved.
9954356b4bSAlina Sbirlea       auto PAC = PA.getChecker<TestFunctionAnalysis>();
10054356b4bSAlina Sbirlea       return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>());
10154356b4bSAlina Sbirlea     }
10274319922SChandler Carruth   };
10374319922SChandler Carruth 
TestFunctionAnalysis(int & Runs)10474319922SChandler Carruth   TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
10574319922SChandler Carruth 
run(Function & F,FunctionAnalysisManager & AM)106b47f8010SChandler Carruth   Result run(Function &F, FunctionAnalysisManager &AM) {
10774319922SChandler Carruth     ++Runs;
10874319922SChandler Carruth     int Count = 0;
10974319922SChandler Carruth     for (Instruction &I : instructions(F)) {
11074319922SChandler Carruth       (void)I;
11174319922SChandler Carruth       ++Count;
11274319922SChandler Carruth     }
11374319922SChandler Carruth     return Result(Count);
11474319922SChandler Carruth   }
11574319922SChandler Carruth 
11674319922SChandler Carruth private:
117dab4eae2SChandler Carruth   friend AnalysisInfoMixin<TestFunctionAnalysis>;
118dab4eae2SChandler Carruth   static AnalysisKey Key;
11974319922SChandler Carruth 
12074319922SChandler Carruth   int &Runs;
12174319922SChandler Carruth };
12274319922SChandler Carruth 
123dab4eae2SChandler Carruth AnalysisKey TestFunctionAnalysis::Key;
12474319922SChandler Carruth 
125dab4eae2SChandler Carruth class TestImmutableFunctionAnalysis
126dab4eae2SChandler Carruth     : public AnalysisInfoMixin<TestImmutableFunctionAnalysis> {
127c5d211efSChandler Carruth public:
128c5d211efSChandler Carruth   struct Result {
invalidate__anone177e1640111::TestImmutableFunctionAnalysis::Result1293ab2a5a8SChandler Carruth     bool invalidate(Function &, const PreservedAnalyses &,
1303ab2a5a8SChandler Carruth                     FunctionAnalysisManager::Invalidator &) {
1313ab2a5a8SChandler Carruth       return false;
1323ab2a5a8SChandler Carruth     }
133c5d211efSChandler Carruth   };
134c5d211efSChandler Carruth 
TestImmutableFunctionAnalysis(int & Runs)135c5d211efSChandler Carruth   TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {}
136c5d211efSChandler Carruth 
run(Function & F,FunctionAnalysisManager & AM)137b47f8010SChandler Carruth   Result run(Function &F, FunctionAnalysisManager &AM) {
138c5d211efSChandler Carruth     ++Runs;
139c5d211efSChandler Carruth     return Result();
140c5d211efSChandler Carruth   }
141c5d211efSChandler Carruth 
142c5d211efSChandler Carruth private:
143dab4eae2SChandler Carruth   friend AnalysisInfoMixin<TestImmutableFunctionAnalysis>;
144dab4eae2SChandler Carruth   static AnalysisKey Key;
145c5d211efSChandler Carruth 
146c5d211efSChandler Carruth   int &Runs;
147c5d211efSChandler Carruth };
148c5d211efSChandler Carruth 
149dab4eae2SChandler Carruth AnalysisKey TestImmutableFunctionAnalysis::Key;
150c5d211efSChandler Carruth 
1516b981647SChandler Carruth struct LambdaModulePass : public PassInfoMixin<LambdaModulePass> {
1526b981647SChandler Carruth   template <typename T>
LambdaModulePass__anone177e1640111::LambdaModulePass1536b981647SChandler Carruth   LambdaModulePass(T &&Arg) : Func(std::forward<T>(Arg)) {}
1546b981647SChandler Carruth 
run__anone177e1640111::LambdaModulePass1556b981647SChandler Carruth   PreservedAnalyses run(Module &F, ModuleAnalysisManager &AM) {
1566b981647SChandler Carruth     return Func(F, AM);
1576b981647SChandler Carruth   }
1586b981647SChandler Carruth 
1596b981647SChandler Carruth   std::function<PreservedAnalyses(Module &, ModuleAnalysisManager &)> Func;
1606b981647SChandler Carruth };
1616b981647SChandler Carruth 
162d4e80a96SChandler Carruth struct LambdaSCCPass : public PassInfoMixin<LambdaSCCPass> {
LambdaSCCPass__anone177e1640111::LambdaSCCPass163d4e80a96SChandler Carruth   template <typename T> LambdaSCCPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
16474319922SChandler Carruth 
run__anone177e1640111::LambdaSCCPass16588823468SChandler Carruth   PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
16688823468SChandler Carruth                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
167d4e80a96SChandler Carruth     return Func(C, AM, CG, UR);
16874319922SChandler Carruth   }
16974319922SChandler Carruth 
170d4e80a96SChandler Carruth   std::function<PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
171d4e80a96SChandler Carruth                                   LazyCallGraph &, CGSCCUpdateResult &)>
172d4e80a96SChandler Carruth       Func;
17374319922SChandler Carruth };
17474319922SChandler Carruth 
175d4e80a96SChandler Carruth struct LambdaFunctionPass : public PassInfoMixin<LambdaFunctionPass> {
1766b981647SChandler Carruth   template <typename T>
LambdaFunctionPass__anone177e1640111::LambdaFunctionPass1776b981647SChandler Carruth   LambdaFunctionPass(T &&Arg) : Func(std::forward<T>(Arg)) {}
17874319922SChandler Carruth 
run__anone177e1640111::LambdaFunctionPass179d4e80a96SChandler Carruth   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
180d4e80a96SChandler Carruth     return Func(F, AM);
18174319922SChandler Carruth   }
18274319922SChandler Carruth 
183d4e80a96SChandler Carruth   std::function<PreservedAnalyses(Function &, FunctionAnalysisManager &)> Func;
18474319922SChandler Carruth };
18574319922SChandler Carruth 
parseIR(const char * IR)1866c138ce3SChandler Carruth std::unique_ptr<Module> parseIR(const char *IR) {
1876c138ce3SChandler Carruth   // We just use a static context here. This is never called from multiple
1886c138ce3SChandler Carruth   // threads so it is harmless no matter how it is implemented. We just need
1896c138ce3SChandler Carruth   // the context to outlive the module which it does.
1906c138ce3SChandler Carruth   static LLVMContext C;
19174319922SChandler Carruth   SMDiagnostic Err;
19274319922SChandler Carruth   return parseAssemblyString(IR, Err, C);
19374319922SChandler Carruth }
19474319922SChandler Carruth 
1954f83742aSChandler Carruth class CGSCCPassManagerTest : public ::testing::Test {
1964f83742aSChandler Carruth protected:
1974f83742aSChandler Carruth   LLVMContext Context;
198dc288a89SChandler Carruth   FunctionAnalysisManager FAM;
199dc288a89SChandler Carruth   CGSCCAnalysisManager CGAM;
200dc288a89SChandler Carruth   ModuleAnalysisManager MAM;
201dc288a89SChandler Carruth 
2024f83742aSChandler Carruth   std::unique_ptr<Module> M;
2034f83742aSChandler Carruth 
2044f83742aSChandler Carruth public:
CGSCCPassManagerTest()2054f83742aSChandler Carruth   CGSCCPassManagerTest()
2066f713100SArthur Eubanks       : FAM(), CGAM(), MAM(),
2074cf2c898SChandler Carruth         M(parseIR(
2084cf2c898SChandler Carruth             // Define a module with the following call graph, where calls go
2094cf2c898SChandler Carruth             // out the bottom of nodes and enter the top:
2104cf2c898SChandler Carruth             //
2114cf2c898SChandler Carruth             // f
2124cf2c898SChandler Carruth             // |\   _
2134cf2c898SChandler Carruth             // | \ / |
2144cf2c898SChandler Carruth             // g  h1 |
2154cf2c898SChandler Carruth             // |  |  |
2164cf2c898SChandler Carruth             // |  h2 |
2174cf2c898SChandler Carruth             // |  |  |
2184cf2c898SChandler Carruth             // |  h3 |
2194cf2c898SChandler Carruth             // | / \_/
2204cf2c898SChandler Carruth             // |/
2214cf2c898SChandler Carruth             // x
2224cf2c898SChandler Carruth             //
223491dd271SFangrui Song             "define void @x() {\n"
22474319922SChandler Carruth             "entry:\n"
225491dd271SFangrui Song             "  ret void\n"
226491dd271SFangrui Song             "}\n"
227491dd271SFangrui Song             "define void @h3() {\n"
228491dd271SFangrui Song             "entry:\n"
22974319922SChandler Carruth             "  call void @h1()\n"
23074319922SChandler Carruth             "  ret void\n"
23174319922SChandler Carruth             "}\n"
23274319922SChandler Carruth             "define void @h2() {\n"
23374319922SChandler Carruth             "entry:\n"
23474319922SChandler Carruth             "  call void @h3()\n"
23574319922SChandler Carruth             "  call void @x()\n"
23674319922SChandler Carruth             "  ret void\n"
23774319922SChandler Carruth             "}\n"
238491dd271SFangrui Song             "define void @h1() {\n"
23974319922SChandler Carruth             "entry:\n"
240491dd271SFangrui Song             "  call void @h2()\n"
24174319922SChandler Carruth             "  ret void\n"
24274319922SChandler Carruth             "}\n"
243491dd271SFangrui Song             "define void @g() {\n"
24474319922SChandler Carruth             "entry:\n"
245491dd271SFangrui Song             "  call void @g()\n"
246491dd271SFangrui Song             "  call void @x()\n"
247491dd271SFangrui Song             "  ret void\n"
248491dd271SFangrui Song             "}\n"
249491dd271SFangrui Song             "define void @f() {\n"
250491dd271SFangrui Song             "entry:\n"
251491dd271SFangrui Song             "  call void @g()\n"
252491dd271SFangrui Song             "  call void @h1()\n"
25374319922SChandler Carruth             "  ret void\n"
254dc288a89SChandler Carruth             "}\n")) {
2559c27b59cSTeresa Johnson     FAM.registerPass([&] { return TargetLibraryAnalysis(); });
256dc288a89SChandler Carruth     MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
257dc288a89SChandler Carruth     MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
258ee8d31c4SFedor Sergeev 
259ee8d31c4SFedor Sergeev     // Register required pass instrumentation analysis.
260ee8d31c4SFedor Sergeev     MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
261ee8d31c4SFedor Sergeev     CGAM.registerPass([&] { return PassInstrumentationAnalysis(); });
262ee8d31c4SFedor Sergeev     FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
263ee8d31c4SFedor Sergeev 
264ee8d31c4SFedor Sergeev     // Cross-register proxies.
265dc288a89SChandler Carruth     MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
2666b981647SChandler Carruth     CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); });
267dc288a89SChandler Carruth     CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
268dc288a89SChandler Carruth     FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
269dc288a89SChandler Carruth     FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
270dc288a89SChandler Carruth   }
2714f83742aSChandler Carruth };
2724f83742aSChandler Carruth 
TEST_F(CGSCCPassManagerTest,Basic)2734f83742aSChandler Carruth TEST_F(CGSCCPassManagerTest, Basic) {
27474319922SChandler Carruth   int FunctionAnalysisRuns = 0;
27574319922SChandler Carruth   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
276c5d211efSChandler Carruth   int ImmutableFunctionAnalysisRuns = 0;
277c5d211efSChandler Carruth   FAM.registerPass([&] {
278c5d211efSChandler Carruth     return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns);
279c5d211efSChandler Carruth   });
28074319922SChandler Carruth 
28174319922SChandler Carruth   int SCCAnalysisRuns = 0;
28274319922SChandler Carruth   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
28374319922SChandler Carruth 
28474319922SChandler Carruth   int ModuleAnalysisRuns = 0;
28574319922SChandler Carruth   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
28674319922SChandler Carruth 
28734a8a437SArthur Eubanks   ModulePassManager MPM;
288d4e80a96SChandler Carruth   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
28974319922SChandler Carruth 
29034a8a437SArthur Eubanks   CGSCCPassManager CGPM1;
29134a8a437SArthur Eubanks   FunctionPassManager FPM1;
2926b981647SChandler Carruth   int FunctionPassRunCount1 = 0;
2936b981647SChandler Carruth   FPM1.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
2946b981647SChandler Carruth     ++FunctionPassRunCount1;
2956b981647SChandler Carruth     return PreservedAnalyses::none();
2966b981647SChandler Carruth   }));
2976b981647SChandler Carruth   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
2986b981647SChandler Carruth 
29974319922SChandler Carruth   int SCCPassRunCount1 = 0;
30074319922SChandler Carruth   int AnalyzedInstrCount1 = 0;
30174319922SChandler Carruth   int AnalyzedSCCFunctionCount1 = 0;
30274319922SChandler Carruth   int AnalyzedModuleFunctionCount1 = 0;
303d4e80a96SChandler Carruth   CGPM1.addPass(
304d4e80a96SChandler Carruth       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
305d4e80a96SChandler Carruth                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
306d4e80a96SChandler Carruth         ++SCCPassRunCount1;
307d4e80a96SChandler Carruth 
308bd541b21SAlina Sbirlea         // Note: The proper way to get to a module pass from a CGSCC pass is
309bd541b21SAlina Sbirlea         // through the ModuleAnalysisManagerCGSCCProxy:
310bd541b21SAlina Sbirlea         // ```
311bd541b21SAlina Sbirlea         // const auto &MAMProxy =
312bd541b21SAlina Sbirlea         //    AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
313bd541b21SAlina Sbirlea         // ```
314bd541b21SAlina Sbirlea         // However getting a stateful analysis is incorrect usage, and the call
315bd541b21SAlina Sbirlea         // to getCachedResult below asserts:
316bd541b21SAlina Sbirlea         // ```
317bd541b21SAlina Sbirlea         // if (TestModuleAnalysis::Result *TMA =
318bd541b21SAlina Sbirlea         //        MAMProxy.getCachedResult<TestModuleAnalysis>(
319bd541b21SAlina Sbirlea         //            *C.begin()->getFunction().getParent()))
320bd541b21SAlina Sbirlea         //   AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
321bd541b21SAlina Sbirlea         // ```
322bd541b21SAlina Sbirlea         // For the purposes of this unittest, use the above MAM directly.
323d4e80a96SChandler Carruth         if (TestModuleAnalysis::Result *TMA =
324d4e80a96SChandler Carruth                 MAM.getCachedResult<TestModuleAnalysis>(
325d4e80a96SChandler Carruth                     *C.begin()->getFunction().getParent()))
326d4e80a96SChandler Carruth           AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
327d4e80a96SChandler Carruth 
328bd541b21SAlina Sbirlea         FunctionAnalysisManager &FAM =
329bd541b21SAlina Sbirlea             AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
330d4e80a96SChandler Carruth         TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
331d4e80a96SChandler Carruth         AnalyzedSCCFunctionCount1 += AR.FunctionCount;
332d4e80a96SChandler Carruth         for (LazyCallGraph::Node &N : C) {
333d4e80a96SChandler Carruth           TestFunctionAnalysis::Result &FAR =
334d4e80a96SChandler Carruth               FAM.getResult<TestFunctionAnalysis>(N.getFunction());
335d4e80a96SChandler Carruth           AnalyzedInstrCount1 += FAR.InstructionCount;
336d4e80a96SChandler Carruth 
337d4e80a96SChandler Carruth           // Just ensure we get the immutable results.
338d4e80a96SChandler Carruth           (void)FAM.getResult<TestImmutableFunctionAnalysis>(N.getFunction());
339d4e80a96SChandler Carruth         }
340d4e80a96SChandler Carruth 
341d4e80a96SChandler Carruth         return PreservedAnalyses::all();
342d4e80a96SChandler Carruth       }));
34374319922SChandler Carruth 
34434a8a437SArthur Eubanks   FunctionPassManager FPM2;
3456b981647SChandler Carruth   int FunctionPassRunCount2 = 0;
3466b981647SChandler Carruth   FPM2.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
3476b981647SChandler Carruth     ++FunctionPassRunCount2;
3486b981647SChandler Carruth     return PreservedAnalyses::none();
349d4e80a96SChandler Carruth   }));
3506b981647SChandler Carruth   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
3516b981647SChandler Carruth 
35274319922SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
35374319922SChandler Carruth 
35434a8a437SArthur Eubanks   FunctionPassManager FPM3;
3556b981647SChandler Carruth   int FunctionPassRunCount3 = 0;
3566b981647SChandler Carruth   FPM3.addPass(LambdaFunctionPass([&](Function &, FunctionAnalysisManager &) {
3576b981647SChandler Carruth     ++FunctionPassRunCount3;
3586b981647SChandler Carruth     return PreservedAnalyses::none();
3596b981647SChandler Carruth   }));
3606b981647SChandler Carruth   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM3)));
3616b981647SChandler Carruth 
362b47f8010SChandler Carruth   MPM.run(*M, MAM);
36374319922SChandler Carruth 
3646b981647SChandler Carruth   EXPECT_EQ(4, SCCPassRunCount1);
3656b981647SChandler Carruth   EXPECT_EQ(6, FunctionPassRunCount1);
3666b981647SChandler Carruth   EXPECT_EQ(6, FunctionPassRunCount2);
3676b981647SChandler Carruth   EXPECT_EQ(6, FunctionPassRunCount3);
3686b981647SChandler Carruth 
36974319922SChandler Carruth   EXPECT_EQ(1, ModuleAnalysisRuns);
37074319922SChandler Carruth   EXPECT_EQ(4, SCCAnalysisRuns);
37174319922SChandler Carruth   EXPECT_EQ(6, FunctionAnalysisRuns);
372c5d211efSChandler Carruth   EXPECT_EQ(6, ImmutableFunctionAnalysisRuns);
37374319922SChandler Carruth 
37474319922SChandler Carruth   EXPECT_EQ(14, AnalyzedInstrCount1);
37574319922SChandler Carruth   EXPECT_EQ(6, AnalyzedSCCFunctionCount1);
37674319922SChandler Carruth   EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
37774319922SChandler Carruth }
37874319922SChandler Carruth 
379b52b573dSChandler Carruth // Test that an SCC pass which fails to preserve a module analysis does in fact
380b52b573dSChandler Carruth // invalidate that module analysis.
TEST_F(CGSCCPassManagerTest,TestSCCPassInvalidatesModuleAnalysis)381b52b573dSChandler Carruth TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
382b52b573dSChandler Carruth   int ModuleAnalysisRuns = 0;
383b52b573dSChandler Carruth   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
384b52b573dSChandler Carruth 
38534a8a437SArthur Eubanks   ModulePassManager MPM;
386b52b573dSChandler Carruth   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
387b52b573dSChandler Carruth 
388b52b573dSChandler Carruth   // The first CGSCC run we preserve everything and make sure that works and
389b52b573dSChandler Carruth   // the module analysis is available in the second CGSCC run from the one
390b52b573dSChandler Carruth   // required module pass above.
39134a8a437SArthur Eubanks   CGSCCPassManager CGPM1;
392b52b573dSChandler Carruth   int CountFoundModuleAnalysis1 = 0;
393bd541b21SAlina Sbirlea   CGPM1.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C,
394bd541b21SAlina Sbirlea                                   CGSCCAnalysisManager &AM, LazyCallGraph &CG,
395bd541b21SAlina Sbirlea                                   CGSCCUpdateResult &UR) {
396bd541b21SAlina Sbirlea     const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
397bd541b21SAlina Sbirlea     if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
398bd541b21SAlina Sbirlea             *C.begin()->getFunction().getParent()))
399b52b573dSChandler Carruth       ++CountFoundModuleAnalysis1;
400b52b573dSChandler Carruth 
401b52b573dSChandler Carruth     return PreservedAnalyses::all();
402b52b573dSChandler Carruth   }));
403b52b573dSChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
404b52b573dSChandler Carruth 
405b52b573dSChandler Carruth   // The second CGSCC run checks that the module analysis got preserved the
406b52b573dSChandler Carruth   // previous time and in one SCC fails to preserve it.
40734a8a437SArthur Eubanks   CGSCCPassManager CGPM2;
408b52b573dSChandler Carruth   int CountFoundModuleAnalysis2 = 0;
409b52b573dSChandler Carruth   CGPM2.addPass(
410b52b573dSChandler Carruth       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
411b52b573dSChandler Carruth                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
412bd541b21SAlina Sbirlea         const auto &MAMProxy =
413bd541b21SAlina Sbirlea             AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
414bd541b21SAlina Sbirlea         if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
415bd541b21SAlina Sbirlea                 *C.begin()->getFunction().getParent()))
416b52b573dSChandler Carruth           ++CountFoundModuleAnalysis2;
417b52b573dSChandler Carruth 
418b52b573dSChandler Carruth         // Only fail to preserve analyses on one SCC and make sure that gets
419b52b573dSChandler Carruth         // propagated.
420b52b573dSChandler Carruth         return C.getName() == "(g)" ? PreservedAnalyses::none()
421b52b573dSChandler Carruth                                   : PreservedAnalyses::all();
422b52b573dSChandler Carruth       }));
423b52b573dSChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
424b52b573dSChandler Carruth 
425b52b573dSChandler Carruth   // The third CGSCC run should fail to find a cached module analysis as it
426b52b573dSChandler Carruth   // should have been invalidated by the above CGSCC run.
42734a8a437SArthur Eubanks   CGSCCPassManager CGPM3;
428b52b573dSChandler Carruth   int CountFoundModuleAnalysis3 = 0;
429bd541b21SAlina Sbirlea   CGPM3.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C,
430bd541b21SAlina Sbirlea                                   CGSCCAnalysisManager &AM, LazyCallGraph &CG,
431bd541b21SAlina Sbirlea                                   CGSCCUpdateResult &UR) {
432bd541b21SAlina Sbirlea     const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
433bd541b21SAlina Sbirlea     if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
434bd541b21SAlina Sbirlea             *C.begin()->getFunction().getParent()))
435b52b573dSChandler Carruth       ++CountFoundModuleAnalysis3;
436b52b573dSChandler Carruth 
437b52b573dSChandler Carruth     return PreservedAnalyses::none();
438b52b573dSChandler Carruth   }));
439b52b573dSChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
440b52b573dSChandler Carruth 
441b52b573dSChandler Carruth   MPM.run(*M, MAM);
442b52b573dSChandler Carruth 
443b52b573dSChandler Carruth   EXPECT_EQ(1, ModuleAnalysisRuns);
444b52b573dSChandler Carruth   EXPECT_EQ(4, CountFoundModuleAnalysis1);
445b52b573dSChandler Carruth   EXPECT_EQ(4, CountFoundModuleAnalysis2);
446b52b573dSChandler Carruth   EXPECT_EQ(0, CountFoundModuleAnalysis3);
447b52b573dSChandler Carruth }
448b52b573dSChandler Carruth 
449e35f84a2SChandler Carruth // Similar to the above, but test that this works for function passes embedded
450e35f84a2SChandler Carruth // *within* a CGSCC layer.
TEST_F(CGSCCPassManagerTest,TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis)451e35f84a2SChandler Carruth TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) {
452e35f84a2SChandler Carruth   int ModuleAnalysisRuns = 0;
453e35f84a2SChandler Carruth   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
454e35f84a2SChandler Carruth 
45534a8a437SArthur Eubanks   ModulePassManager MPM;
456e35f84a2SChandler Carruth   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
457e35f84a2SChandler Carruth 
458e35f84a2SChandler Carruth   // The first run we preserve everything and make sure that works and the
459e35f84a2SChandler Carruth   // module analysis is available in the second run from the one required
460e35f84a2SChandler Carruth   // module pass above.
46134a8a437SArthur Eubanks   FunctionPassManager FPM1;
462e35f84a2SChandler Carruth   // Start true and mark false if we ever failed to find a module analysis
463e35f84a2SChandler Carruth   // because we expect this to succeed for each SCC.
464e35f84a2SChandler Carruth   bool FoundModuleAnalysis1 = true;
465bd541b21SAlina Sbirlea   FPM1.addPass(LambdaFunctionPass([&](Function &F,
466bd541b21SAlina Sbirlea                                       FunctionAnalysisManager &AM) {
467bd541b21SAlina Sbirlea     const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
468bd541b21SAlina Sbirlea     if (!MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
469e35f84a2SChandler Carruth       FoundModuleAnalysis1 = false;
470e35f84a2SChandler Carruth 
471e35f84a2SChandler Carruth     return PreservedAnalyses::all();
472e35f84a2SChandler Carruth   }));
47334a8a437SArthur Eubanks   CGSCCPassManager CGPM1;
474e35f84a2SChandler Carruth   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
475e35f84a2SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
476e35f84a2SChandler Carruth 
477e35f84a2SChandler Carruth   // The second run checks that the module analysis got preserved the previous
478e35f84a2SChandler Carruth   // time and in one function fails to preserve it.
47934a8a437SArthur Eubanks   FunctionPassManager FPM2;
480e35f84a2SChandler Carruth   // Again, start true and mark false if we ever failed to find a module analysis
481e35f84a2SChandler Carruth   // because we expect this to succeed for each SCC.
482e35f84a2SChandler Carruth   bool FoundModuleAnalysis2 = true;
483bd541b21SAlina Sbirlea   FPM2.addPass(LambdaFunctionPass([&](Function &F,
484bd541b21SAlina Sbirlea                                       FunctionAnalysisManager &AM) {
485bd541b21SAlina Sbirlea     const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
486bd541b21SAlina Sbirlea     if (!MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
487e35f84a2SChandler Carruth       FoundModuleAnalysis2 = false;
488e35f84a2SChandler Carruth 
489e35f84a2SChandler Carruth     // Only fail to preserve analyses on one SCC and make sure that gets
490e35f84a2SChandler Carruth     // propagated.
491e35f84a2SChandler Carruth     return F.getName() == "h2" ? PreservedAnalyses::none()
492e35f84a2SChandler Carruth                                : PreservedAnalyses::all();
493e35f84a2SChandler Carruth   }));
49434a8a437SArthur Eubanks   CGSCCPassManager CGPM2;
495e35f84a2SChandler Carruth   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
496e35f84a2SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
497e35f84a2SChandler Carruth 
498e35f84a2SChandler Carruth   // The third run should fail to find a cached module analysis as it should
499e35f84a2SChandler Carruth   // have been invalidated by the above run.
50034a8a437SArthur Eubanks   FunctionPassManager FPM3;
501e35f84a2SChandler Carruth   // Start false and mark true if we ever *succeeded* to find a module
502e35f84a2SChandler Carruth   // analysis, as we expect this to fail for every function.
503e35f84a2SChandler Carruth   bool FoundModuleAnalysis3 = false;
504bd541b21SAlina Sbirlea   FPM3.addPass(LambdaFunctionPass([&](Function &F,
505bd541b21SAlina Sbirlea                                       FunctionAnalysisManager &AM) {
506bd541b21SAlina Sbirlea     const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
507bd541b21SAlina Sbirlea     if (MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
508e35f84a2SChandler Carruth       FoundModuleAnalysis3 = true;
509e35f84a2SChandler Carruth 
510e35f84a2SChandler Carruth     return PreservedAnalyses::none();
511e35f84a2SChandler Carruth   }));
51234a8a437SArthur Eubanks   CGSCCPassManager CGPM3;
513e35f84a2SChandler Carruth   CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3)));
514e35f84a2SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
515e35f84a2SChandler Carruth 
516e35f84a2SChandler Carruth   MPM.run(*M, MAM);
517e35f84a2SChandler Carruth 
518e35f84a2SChandler Carruth   EXPECT_EQ(1, ModuleAnalysisRuns);
519e35f84a2SChandler Carruth   EXPECT_TRUE(FoundModuleAnalysis1);
520e35f84a2SChandler Carruth   EXPECT_TRUE(FoundModuleAnalysis2);
521e35f84a2SChandler Carruth   EXPECT_FALSE(FoundModuleAnalysis3);
522e35f84a2SChandler Carruth }
523e35f84a2SChandler Carruth 
5246b981647SChandler Carruth // Test that a Module pass which fails to preserve an SCC analysis in fact
5256b981647SChandler Carruth // invalidates that analysis.
TEST_F(CGSCCPassManagerTest,TestModulePassInvalidatesSCCAnalysis)5266b981647SChandler Carruth TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysis) {
5276b981647SChandler Carruth   int SCCAnalysisRuns = 0;
5286b981647SChandler Carruth   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
5296b981647SChandler Carruth 
53034a8a437SArthur Eubanks   ModulePassManager MPM;
5316b981647SChandler Carruth 
5326b981647SChandler Carruth   // First force the analysis to be run.
53334a8a437SArthur Eubanks   CGSCCPassManager CGPM1;
5346b981647SChandler Carruth   CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
5356b981647SChandler Carruth                                     CGSCCAnalysisManager, LazyCallGraph &,
5366b981647SChandler Carruth                                     CGSCCUpdateResult &>());
5376b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
5386b981647SChandler Carruth 
5396b981647SChandler Carruth   // Now run a module pass that preserves the LazyCallGraph and the proxy but
5406b981647SChandler Carruth   // not the SCC analysis.
5416b981647SChandler Carruth   MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
5426b981647SChandler Carruth     PreservedAnalyses PA;
5436b981647SChandler Carruth     PA.preserve<LazyCallGraphAnalysis>();
5446b981647SChandler Carruth     PA.preserve<CGSCCAnalysisManagerModuleProxy>();
5456b981647SChandler Carruth     PA.preserve<FunctionAnalysisManagerModuleProxy>();
5466b981647SChandler Carruth     return PA;
5476b981647SChandler Carruth   }));
5486b981647SChandler Carruth 
5496b981647SChandler Carruth   // And now a second CGSCC run which requires the SCC analysis again. This
5506b981647SChandler Carruth   // will trigger re-running it.
55134a8a437SArthur Eubanks   CGSCCPassManager CGPM2;
5526b981647SChandler Carruth   CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
5536b981647SChandler Carruth                                     CGSCCAnalysisManager, LazyCallGraph &,
5546b981647SChandler Carruth                                     CGSCCUpdateResult &>());
5556b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
5566b981647SChandler Carruth 
5576b981647SChandler Carruth   MPM.run(*M, MAM);
5586b981647SChandler Carruth   // Two runs and four SCCs.
5596b981647SChandler Carruth   EXPECT_EQ(2 * 4, SCCAnalysisRuns);
5606b981647SChandler Carruth }
5616b981647SChandler Carruth 
5626b981647SChandler Carruth // Check that marking the SCC analysis preserved is sufficient to avoid
5636b981647SChandler Carruth // invaliadtion. This should only run the analysis once for each SCC.
TEST_F(CGSCCPassManagerTest,TestModulePassCanPreserveSCCAnalysis)5646b981647SChandler Carruth TEST_F(CGSCCPassManagerTest, TestModulePassCanPreserveSCCAnalysis) {
5656b981647SChandler Carruth   int SCCAnalysisRuns = 0;
5666b981647SChandler Carruth   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
5676b981647SChandler Carruth 
56834a8a437SArthur Eubanks   ModulePassManager MPM;
5696b981647SChandler Carruth 
5706b981647SChandler Carruth   // First force the analysis to be run.
57134a8a437SArthur Eubanks   CGSCCPassManager CGPM1;
5726b981647SChandler Carruth   CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
5736b981647SChandler Carruth                                     CGSCCAnalysisManager, LazyCallGraph &,
5746b981647SChandler Carruth                                     CGSCCUpdateResult &>());
5756b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
5766b981647SChandler Carruth 
5776b981647SChandler Carruth   // Now run a module pass that preserves each of the necessary components
5786b981647SChandler Carruth   // (but not everything).
5796b981647SChandler Carruth   MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
5806b981647SChandler Carruth     PreservedAnalyses PA;
5816b981647SChandler Carruth     PA.preserve<LazyCallGraphAnalysis>();
5826b981647SChandler Carruth     PA.preserve<CGSCCAnalysisManagerModuleProxy>();
5836b981647SChandler Carruth     PA.preserve<FunctionAnalysisManagerModuleProxy>();
5846b981647SChandler Carruth     PA.preserve<TestSCCAnalysis>();
5856b981647SChandler Carruth     return PA;
5866b981647SChandler Carruth   }));
5876b981647SChandler Carruth 
5886b981647SChandler Carruth   // And now a second CGSCC run which requires the SCC analysis again but find
5896b981647SChandler Carruth   // it in the cache.
59034a8a437SArthur Eubanks   CGSCCPassManager CGPM2;
5916b981647SChandler Carruth   CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
5926b981647SChandler Carruth                                     CGSCCAnalysisManager, LazyCallGraph &,
5936b981647SChandler Carruth                                     CGSCCUpdateResult &>());
5946b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
5956b981647SChandler Carruth 
5966b981647SChandler Carruth   MPM.run(*M, MAM);
5976b981647SChandler Carruth   // Four SCCs
5986b981647SChandler Carruth   EXPECT_EQ(4, SCCAnalysisRuns);
5996b981647SChandler Carruth }
6006b981647SChandler Carruth 
6016b981647SChandler Carruth // Check that even when the analysis is preserved, if the SCC information isn't
6026b981647SChandler Carruth // we still nuke things because the SCC keys could change.
TEST_F(CGSCCPassManagerTest,TestModulePassInvalidatesSCCAnalysisOnCGChange)6036b981647SChandler Carruth TEST_F(CGSCCPassManagerTest, TestModulePassInvalidatesSCCAnalysisOnCGChange) {
6046b981647SChandler Carruth   int SCCAnalysisRuns = 0;
6056b981647SChandler Carruth   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
6066b981647SChandler Carruth 
60734a8a437SArthur Eubanks   ModulePassManager MPM;
6086b981647SChandler Carruth 
6096b981647SChandler Carruth   // First force the analysis to be run.
61034a8a437SArthur Eubanks   CGSCCPassManager CGPM1;
6116b981647SChandler Carruth   CGPM1.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
6126b981647SChandler Carruth                                     CGSCCAnalysisManager, LazyCallGraph &,
6136b981647SChandler Carruth                                     CGSCCUpdateResult &>());
6146b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
6156b981647SChandler Carruth 
6166b981647SChandler Carruth   // Now run a module pass that preserves the analysis but not the call
6176b981647SChandler Carruth   // graph or proxy.
6186b981647SChandler Carruth   MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
6196b981647SChandler Carruth     PreservedAnalyses PA;
6206b981647SChandler Carruth     PA.preserve<TestSCCAnalysis>();
6216b981647SChandler Carruth     return PA;
6226b981647SChandler Carruth   }));
6236b981647SChandler Carruth 
6246b981647SChandler Carruth   // And now a second CGSCC run which requires the SCC analysis again.
62534a8a437SArthur Eubanks   CGSCCPassManager CGPM2;
6266b981647SChandler Carruth   CGPM2.addPass(RequireAnalysisPass<TestSCCAnalysis, LazyCallGraph::SCC,
6276b981647SChandler Carruth                                     CGSCCAnalysisManager, LazyCallGraph &,
6286b981647SChandler Carruth                                     CGSCCUpdateResult &>());
6296b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
6306b981647SChandler Carruth 
6316b981647SChandler Carruth   MPM.run(*M, MAM);
6326b981647SChandler Carruth   // Two runs and four SCCs.
6336b981647SChandler Carruth   EXPECT_EQ(2 * 4, SCCAnalysisRuns);
6346b981647SChandler Carruth }
6356b981647SChandler Carruth 
6366b981647SChandler Carruth // Test that an SCC pass which fails to preserve a Function analysis in fact
6376b981647SChandler Carruth // invalidates that analysis.
TEST_F(CGSCCPassManagerTest,TestSCCPassInvalidatesFunctionAnalysis)6386b981647SChandler Carruth TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesFunctionAnalysis) {
6396b981647SChandler Carruth   int FunctionAnalysisRuns = 0;
6406b981647SChandler Carruth   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
6416b981647SChandler Carruth 
6426b981647SChandler Carruth   // Create a very simple module with a single function and SCC to make testing
6436b981647SChandler Carruth   // these issues much easier.
6446b981647SChandler Carruth   std::unique_ptr<Module> M = parseIR("declare void @g()\n"
6456b981647SChandler Carruth                                       "declare void @h()\n"
6466b981647SChandler Carruth                                       "define void @f() {\n"
6476b981647SChandler Carruth                                       "entry:\n"
6486b981647SChandler Carruth                                       "  call void @g()\n"
6496b981647SChandler Carruth                                       "  call void @h()\n"
6506b981647SChandler Carruth                                       "  ret void\n"
6516b981647SChandler Carruth                                       "}\n");
6526b981647SChandler Carruth 
65334a8a437SArthur Eubanks   CGSCCPassManager CGPM;
6546b981647SChandler Carruth 
6556b981647SChandler Carruth   // First force the analysis to be run.
65634a8a437SArthur Eubanks   FunctionPassManager FPM1;
6576b981647SChandler Carruth   FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
6586b981647SChandler Carruth   CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
6596b981647SChandler Carruth 
6606b981647SChandler Carruth   // Now run a module pass that preserves the LazyCallGraph and proxy but not
6616b981647SChandler Carruth   // the SCC analysis.
6626b981647SChandler Carruth   CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
6636b981647SChandler Carruth                                  LazyCallGraph &, CGSCCUpdateResult &) {
6646b981647SChandler Carruth     PreservedAnalyses PA;
6656b981647SChandler Carruth     PA.preserve<LazyCallGraphAnalysis>();
6666b981647SChandler Carruth     return PA;
6676b981647SChandler Carruth   }));
6686b981647SChandler Carruth 
6696b981647SChandler Carruth   // And now a second CGSCC run which requires the SCC analysis again. This
6706b981647SChandler Carruth   // will trigger re-running it.
67134a8a437SArthur Eubanks   FunctionPassManager FPM2;
6726b981647SChandler Carruth   FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
6736b981647SChandler Carruth   CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
6746b981647SChandler Carruth 
67534a8a437SArthur Eubanks   ModulePassManager MPM;
6766b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
6776b981647SChandler Carruth   MPM.run(*M, MAM);
6786b981647SChandler Carruth   EXPECT_EQ(2, FunctionAnalysisRuns);
6796b981647SChandler Carruth }
6806b981647SChandler Carruth 
6816b981647SChandler Carruth // Check that marking the SCC analysis preserved is sufficient. This should
6826b981647SChandler Carruth // only run the analysis once the SCC.
TEST_F(CGSCCPassManagerTest,TestSCCPassCanPreserveFunctionAnalysis)6836b981647SChandler Carruth TEST_F(CGSCCPassManagerTest, TestSCCPassCanPreserveFunctionAnalysis) {
6846b981647SChandler Carruth   int FunctionAnalysisRuns = 0;
6856b981647SChandler Carruth   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
6866b981647SChandler Carruth 
6876b981647SChandler Carruth   // Create a very simple module with a single function and SCC to make testing
6886b981647SChandler Carruth   // these issues much easier.
6896b981647SChandler Carruth   std::unique_ptr<Module> M = parseIR("declare void @g()\n"
6906b981647SChandler Carruth                                       "declare void @h()\n"
6916b981647SChandler Carruth                                       "define void @f() {\n"
6926b981647SChandler Carruth                                       "entry:\n"
6936b981647SChandler Carruth                                       "  call void @g()\n"
6946b981647SChandler Carruth                                       "  call void @h()\n"
6956b981647SChandler Carruth                                       "  ret void\n"
6966b981647SChandler Carruth                                       "}\n");
6976b981647SChandler Carruth 
69834a8a437SArthur Eubanks   CGSCCPassManager CGPM;
6996b981647SChandler Carruth 
7006b981647SChandler Carruth   // First force the analysis to be run.
70134a8a437SArthur Eubanks   FunctionPassManager FPM1;
7026b981647SChandler Carruth   FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
7036b981647SChandler Carruth   CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
7046b981647SChandler Carruth 
7056b981647SChandler Carruth   // Now run a module pass that preserves each of the necessary components
7066b981647SChandler Carruth   // (but
7076b981647SChandler Carruth   // not everything).
7086b981647SChandler Carruth   CGPM.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
7096b981647SChandler Carruth                                  LazyCallGraph &, CGSCCUpdateResult &) {
7106b981647SChandler Carruth     PreservedAnalyses PA;
7116b981647SChandler Carruth     PA.preserve<LazyCallGraphAnalysis>();
712bd9c2903SChandler Carruth     PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
7136b981647SChandler Carruth     PA.preserve<TestFunctionAnalysis>();
7146b981647SChandler Carruth     return PA;
7156b981647SChandler Carruth   }));
7166b981647SChandler Carruth 
7176b981647SChandler Carruth   // And now a second CGSCC run which requires the SCC analysis again but find
7186b981647SChandler Carruth   // it in the cache.
71934a8a437SArthur Eubanks   FunctionPassManager FPM2;
7206b981647SChandler Carruth   FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
7216b981647SChandler Carruth   CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
7226b981647SChandler Carruth 
72334a8a437SArthur Eubanks   ModulePassManager MPM;
7246b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
7256b981647SChandler Carruth   MPM.run(*M, MAM);
7266b981647SChandler Carruth   EXPECT_EQ(1, FunctionAnalysisRuns);
7276b981647SChandler Carruth }
7286b981647SChandler Carruth 
7296b981647SChandler Carruth // Note that there is no test for invalidating the call graph or other
7306b981647SChandler Carruth // structure with an SCC pass because there is no mechanism to do that from
7316b981647SChandler Carruth // withinsuch a pass. Instead, such a pass has to directly update the call
7326b981647SChandler Carruth // graph structure.
7336b981647SChandler Carruth 
7346b981647SChandler Carruth // Test that a madule pass invalidates function analyses when the CGSCC proxies
7356b981647SChandler Carruth // and pass manager.
TEST_F(CGSCCPassManagerTest,TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC)7366b981647SChandler Carruth TEST_F(CGSCCPassManagerTest,
7376b981647SChandler Carruth        TestModulePassInvalidatesFunctionAnalysisNestedInCGSCC) {
7386b981647SChandler Carruth   MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
7396b981647SChandler Carruth 
7406b981647SChandler Carruth   int FunctionAnalysisRuns = 0;
7416b981647SChandler Carruth   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
7426b981647SChandler Carruth 
74334a8a437SArthur Eubanks   ModulePassManager MPM;
7446b981647SChandler Carruth 
7456b981647SChandler Carruth   // First force the analysis to be run.
74634a8a437SArthur Eubanks   FunctionPassManager FPM1;
7476b981647SChandler Carruth   FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
74834a8a437SArthur Eubanks   CGSCCPassManager CGPM1;
7496b981647SChandler Carruth   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
7506b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
7516b981647SChandler Carruth 
752bd9c2903SChandler Carruth   // Now run a module pass that preserves the LazyCallGraph and proxies but not
7536b981647SChandler Carruth   // the Function analysis.
7546b981647SChandler Carruth   MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
7556b981647SChandler Carruth     PreservedAnalyses PA;
7566b981647SChandler Carruth     PA.preserve<LazyCallGraphAnalysis>();
7576b981647SChandler Carruth     PA.preserve<CGSCCAnalysisManagerModuleProxy>();
758bd9c2903SChandler Carruth     PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
759bd9c2903SChandler Carruth     PA.preserve<FunctionAnalysisManagerModuleProxy>();
7606b981647SChandler Carruth     return PA;
7616b981647SChandler Carruth   }));
7626b981647SChandler Carruth 
7636b981647SChandler Carruth   // And now a second CGSCC run which requires the SCC analysis again. This
7646b981647SChandler Carruth   // will trigger re-running it.
76534a8a437SArthur Eubanks   FunctionPassManager FPM2;
7666b981647SChandler Carruth   FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
76734a8a437SArthur Eubanks   CGSCCPassManager CGPM2;
7686b981647SChandler Carruth   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
7696b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
7706b981647SChandler Carruth 
7716b981647SChandler Carruth   MPM.run(*M, MAM);
7726b981647SChandler Carruth   // Two runs and 6 functions.
7736b981647SChandler Carruth   EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
7746b981647SChandler Carruth }
7756b981647SChandler Carruth 
776bd9c2903SChandler Carruth // Check that by marking the function pass and proxies as preserved, this
7776b981647SChandler Carruth // propagates all the way through.
TEST_F(CGSCCPassManagerTest,TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC)7786b981647SChandler Carruth TEST_F(CGSCCPassManagerTest,
7796b981647SChandler Carruth        TestModulePassCanPreserveFunctionAnalysisNestedInCGSCC) {
7806b981647SChandler Carruth   MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
7816b981647SChandler Carruth 
7826b981647SChandler Carruth   int FunctionAnalysisRuns = 0;
7836b981647SChandler Carruth   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
7846b981647SChandler Carruth 
78534a8a437SArthur Eubanks   ModulePassManager MPM;
7866b981647SChandler Carruth 
7876b981647SChandler Carruth   // First force the analysis to be run.
78834a8a437SArthur Eubanks   FunctionPassManager FPM1;
7896b981647SChandler Carruth   FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
79034a8a437SArthur Eubanks   CGSCCPassManager CGPM1;
7916b981647SChandler Carruth   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
7926b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
7936b981647SChandler Carruth 
7946b981647SChandler Carruth   // Now run a module pass that preserves the LazyCallGraph, the proxy, and
7956b981647SChandler Carruth   // the Function analysis.
7966b981647SChandler Carruth   MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
7976b981647SChandler Carruth     PreservedAnalyses PA;
7986b981647SChandler Carruth     PA.preserve<LazyCallGraphAnalysis>();
7996b981647SChandler Carruth     PA.preserve<CGSCCAnalysisManagerModuleProxy>();
800bd9c2903SChandler Carruth     PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
8016b981647SChandler Carruth     PA.preserve<FunctionAnalysisManagerModuleProxy>();
8026b981647SChandler Carruth     PA.preserve<TestFunctionAnalysis>();
8036b981647SChandler Carruth     return PA;
8046b981647SChandler Carruth   }));
8056b981647SChandler Carruth 
8066b981647SChandler Carruth   // And now a second CGSCC run which requires the SCC analysis again. This
8076b981647SChandler Carruth   // will trigger re-running it.
80834a8a437SArthur Eubanks   FunctionPassManager FPM2;
8096b981647SChandler Carruth   FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
81034a8a437SArthur Eubanks   CGSCCPassManager CGPM2;
8116b981647SChandler Carruth   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
8126b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
8136b981647SChandler Carruth 
8146b981647SChandler Carruth   MPM.run(*M, MAM);
8156b981647SChandler Carruth   // One run and 6 functions.
8166b981647SChandler Carruth   EXPECT_EQ(6, FunctionAnalysisRuns);
8176b981647SChandler Carruth }
8186b981647SChandler Carruth 
8196b981647SChandler Carruth // Check that if the lazy call graph itself isn't preserved we still manage to
8206b981647SChandler Carruth // invalidate everything.
TEST_F(CGSCCPassManagerTest,TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange)8216b981647SChandler Carruth TEST_F(CGSCCPassManagerTest,
8226b981647SChandler Carruth        TestModulePassInvalidatesFunctionAnalysisNestedInCGSCCOnCGChange) {
8236b981647SChandler Carruth   MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
8246b981647SChandler Carruth 
8256b981647SChandler Carruth   int FunctionAnalysisRuns = 0;
8266b981647SChandler Carruth   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
8276b981647SChandler Carruth 
82834a8a437SArthur Eubanks   ModulePassManager MPM;
8296b981647SChandler Carruth 
8306b981647SChandler Carruth   // First force the analysis to be run.
83134a8a437SArthur Eubanks   FunctionPassManager FPM1;
8326b981647SChandler Carruth   FPM1.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
83334a8a437SArthur Eubanks   CGSCCPassManager CGPM1;
8346b981647SChandler Carruth   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
8356b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
8366b981647SChandler Carruth 
8376b981647SChandler Carruth   // Now run a module pass that preserves the LazyCallGraph but not the
8386b981647SChandler Carruth   // Function analysis.
8396b981647SChandler Carruth   MPM.addPass(LambdaModulePass([&](Module &M, ModuleAnalysisManager &) {
8406b981647SChandler Carruth     PreservedAnalyses PA;
8416b981647SChandler Carruth     return PA;
8426b981647SChandler Carruth   }));
8436b981647SChandler Carruth 
8446b981647SChandler Carruth   // And now a second CGSCC run which requires the SCC analysis again. This
8456b981647SChandler Carruth   // will trigger re-running it.
84634a8a437SArthur Eubanks   FunctionPassManager FPM2;
8476b981647SChandler Carruth   FPM2.addPass(RequireAnalysisPass<TestFunctionAnalysis, Function>());
84834a8a437SArthur Eubanks   CGSCCPassManager CGPM2;
8496b981647SChandler Carruth   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
8506b981647SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
8516b981647SChandler Carruth 
8526b981647SChandler Carruth   MPM.run(*M, MAM);
8536b981647SChandler Carruth   // Two runs and 6 functions.
8546b981647SChandler Carruth   EXPECT_EQ(2 * 6, FunctionAnalysisRuns);
8556b981647SChandler Carruth }
856ba90ae96SChandler Carruth 
857ba90ae96SChandler Carruth /// A test CGSCC-level analysis pass which caches in its result another
858ba90ae96SChandler Carruth /// analysis pass and uses it to serve queries. This requires the result to
859ba90ae96SChandler Carruth /// invalidate itself when its dependency is invalidated.
860ba90ae96SChandler Carruth ///
861ba90ae96SChandler Carruth /// FIXME: Currently this doesn't also depend on a function analysis, and if it
862ba90ae96SChandler Carruth /// did we would fail to invalidate it correctly.
863ba90ae96SChandler Carruth struct TestIndirectSCCAnalysis
864ba90ae96SChandler Carruth     : public AnalysisInfoMixin<TestIndirectSCCAnalysis> {
865ba90ae96SChandler Carruth   struct Result {
Result__anone177e1640111::TestIndirectSCCAnalysis::Result866ba90ae96SChandler Carruth     Result(TestSCCAnalysis::Result &SCCDep, TestModuleAnalysis::Result &MDep)
867ba90ae96SChandler Carruth         : SCCDep(SCCDep), MDep(MDep) {}
868ba90ae96SChandler Carruth     TestSCCAnalysis::Result &SCCDep;
869ba90ae96SChandler Carruth     TestModuleAnalysis::Result &MDep;
870ba90ae96SChandler Carruth 
invalidate__anone177e1640111::TestIndirectSCCAnalysis::Result871ba90ae96SChandler Carruth     bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
872ba90ae96SChandler Carruth                     CGSCCAnalysisManager::Invalidator &Inv) {
873ba90ae96SChandler Carruth       auto PAC = PA.getChecker<TestIndirectSCCAnalysis>();
874ba90ae96SChandler Carruth       return !(PAC.preserved() ||
875ba90ae96SChandler Carruth                PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
876ba90ae96SChandler Carruth              Inv.invalidate<TestSCCAnalysis>(C, PA);
877ba90ae96SChandler Carruth     }
878ba90ae96SChandler Carruth   };
879ba90ae96SChandler Carruth 
TestIndirectSCCAnalysis__anone177e1640111::TestIndirectSCCAnalysis880bd541b21SAlina Sbirlea   TestIndirectSCCAnalysis(int &Runs, ModuleAnalysisManager &MAM)
881bd541b21SAlina Sbirlea       : Runs(Runs), MAM(MAM) {}
882ba90ae96SChandler Carruth 
883ba90ae96SChandler Carruth   /// Run the analysis pass over the function and return a result.
run__anone177e1640111::TestIndirectSCCAnalysis884ba90ae96SChandler Carruth   Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
885ba90ae96SChandler Carruth              LazyCallGraph &CG) {
886ba90ae96SChandler Carruth     ++Runs;
887ba90ae96SChandler Carruth     auto &SCCDep = AM.getResult<TestSCCAnalysis>(C, CG);
888ba90ae96SChandler Carruth 
889ba90ae96SChandler Carruth     auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
890ba90ae96SChandler Carruth     // For the test, we insist that the module analysis starts off in the
891bd541b21SAlina Sbirlea     // cache. Getting a cached result that isn't stateless triggers an assert.
892bd541b21SAlina Sbirlea     // auto &MDep = *ModuleProxy.getCachedResult<TestModuleAnalysis>(
893bd541b21SAlina Sbirlea     //  *C.begin()->getFunction().getParent());
894bd541b21SAlina Sbirlea     // Use MAM, for the purposes of this unittest.
895ba90ae96SChandler Carruth     auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(
896ba90ae96SChandler Carruth         *C.begin()->getFunction().getParent());
897ba90ae96SChandler Carruth     // Register the dependency as module analysis dependencies have to be
898ba90ae96SChandler Carruth     // pre-registered on the proxy.
899ba90ae96SChandler Carruth     ModuleProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
900ba90ae96SChandler Carruth                                                   TestIndirectSCCAnalysis>();
901ba90ae96SChandler Carruth 
902ba90ae96SChandler Carruth     return Result(SCCDep, MDep);
903ba90ae96SChandler Carruth   }
904ba90ae96SChandler Carruth 
905ba90ae96SChandler Carruth private:
906ba90ae96SChandler Carruth   friend AnalysisInfoMixin<TestIndirectSCCAnalysis>;
907ba90ae96SChandler Carruth   static AnalysisKey Key;
908ba90ae96SChandler Carruth 
909ba90ae96SChandler Carruth   int &Runs;
910bd541b21SAlina Sbirlea   ModuleAnalysisManager &MAM;
911ba90ae96SChandler Carruth };
912ba90ae96SChandler Carruth 
913ba90ae96SChandler Carruth AnalysisKey TestIndirectSCCAnalysis::Key;
914ba90ae96SChandler Carruth 
915ba90ae96SChandler Carruth /// A test analysis pass which caches in its result the result from the above
916ba90ae96SChandler Carruth /// indirect analysis pass.
917ba90ae96SChandler Carruth ///
918ba90ae96SChandler Carruth /// This allows us to ensure that whenever an analysis pass is invalidated due
919ba90ae96SChandler Carruth /// to dependencies (especially dependencies across IR units that trigger
920ba90ae96SChandler Carruth /// asynchronous invalidation) we correctly detect that this may in turn cause
921ba90ae96SChandler Carruth /// other analysis to be invalidated.
922ba90ae96SChandler Carruth struct TestDoublyIndirectSCCAnalysis
923ba90ae96SChandler Carruth     : public AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis> {
924ba90ae96SChandler Carruth   struct Result {
Result__anone177e1640111::TestDoublyIndirectSCCAnalysis::Result925ba90ae96SChandler Carruth     Result(TestIndirectSCCAnalysis::Result &IDep) : IDep(IDep) {}
926ba90ae96SChandler Carruth     TestIndirectSCCAnalysis::Result &IDep;
927ba90ae96SChandler Carruth 
invalidate__anone177e1640111::TestDoublyIndirectSCCAnalysis::Result928ba90ae96SChandler Carruth     bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
929ba90ae96SChandler Carruth                     CGSCCAnalysisManager::Invalidator &Inv) {
930ba90ae96SChandler Carruth       auto PAC = PA.getChecker<TestDoublyIndirectSCCAnalysis>();
931ba90ae96SChandler Carruth       return !(PAC.preserved() ||
932ba90ae96SChandler Carruth                PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) ||
933ba90ae96SChandler Carruth              Inv.invalidate<TestIndirectSCCAnalysis>(C, PA);
934ba90ae96SChandler Carruth     }
935ba90ae96SChandler Carruth   };
936ba90ae96SChandler Carruth 
TestDoublyIndirectSCCAnalysis__anone177e1640111::TestDoublyIndirectSCCAnalysis937ba90ae96SChandler Carruth   TestDoublyIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
938ba90ae96SChandler Carruth 
939ba90ae96SChandler Carruth   /// Run the analysis pass over the function and return a result.
run__anone177e1640111::TestDoublyIndirectSCCAnalysis940ba90ae96SChandler Carruth   Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
941ba90ae96SChandler Carruth              LazyCallGraph &CG) {
942ba90ae96SChandler Carruth     ++Runs;
943ba90ae96SChandler Carruth     auto &IDep = AM.getResult<TestIndirectSCCAnalysis>(C, CG);
944ba90ae96SChandler Carruth     return Result(IDep);
945ba90ae96SChandler Carruth   }
946ba90ae96SChandler Carruth 
947ba90ae96SChandler Carruth private:
948ba90ae96SChandler Carruth   friend AnalysisInfoMixin<TestDoublyIndirectSCCAnalysis>;
949ba90ae96SChandler Carruth   static AnalysisKey Key;
950ba90ae96SChandler Carruth 
951ba90ae96SChandler Carruth   int &Runs;
952ba90ae96SChandler Carruth };
953ba90ae96SChandler Carruth 
954ba90ae96SChandler Carruth AnalysisKey TestDoublyIndirectSCCAnalysis::Key;
955ba90ae96SChandler Carruth 
956ba90ae96SChandler Carruth /// A test analysis pass which caches results from three different IR unit
957ba90ae96SChandler Carruth /// layers and requires intermediate layers to correctly propagate the entire
958ba90ae96SChandler Carruth /// distance.
959ba90ae96SChandler Carruth struct TestIndirectFunctionAnalysis
960ba90ae96SChandler Carruth     : public AnalysisInfoMixin<TestIndirectFunctionAnalysis> {
961ba90ae96SChandler Carruth   struct Result {
Result__anone177e1640111::TestIndirectFunctionAnalysis::Result962ba90ae96SChandler Carruth     Result(TestFunctionAnalysis::Result &FDep, TestModuleAnalysis::Result &MDep,
963ba90ae96SChandler Carruth            TestSCCAnalysis::Result &SCCDep)
964ba90ae96SChandler Carruth         : FDep(FDep), MDep(MDep), SCCDep(SCCDep) {}
965ba90ae96SChandler Carruth     TestFunctionAnalysis::Result &FDep;
966ba90ae96SChandler Carruth     TestModuleAnalysis::Result &MDep;
967ba90ae96SChandler Carruth     TestSCCAnalysis::Result &SCCDep;
968ba90ae96SChandler Carruth 
invalidate__anone177e1640111::TestIndirectFunctionAnalysis::Result969ba90ae96SChandler Carruth     bool invalidate(Function &F, const PreservedAnalyses &PA,
970ba90ae96SChandler Carruth                     FunctionAnalysisManager::Invalidator &Inv) {
971ba90ae96SChandler Carruth       auto PAC = PA.getChecker<TestIndirectFunctionAnalysis>();
972ba90ae96SChandler Carruth       return !(PAC.preserved() ||
973ba90ae96SChandler Carruth                PAC.preservedSet<AllAnalysesOn<Function>>()) ||
974ba90ae96SChandler Carruth              Inv.invalidate<TestFunctionAnalysis>(F, PA);
975ba90ae96SChandler Carruth     }
976ba90ae96SChandler Carruth   };
977ba90ae96SChandler Carruth 
TestIndirectFunctionAnalysis__anone177e1640111::TestIndirectFunctionAnalysis978bd541b21SAlina Sbirlea   TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM,
979bd541b21SAlina Sbirlea                                CGSCCAnalysisManager &CGAM)
980bd541b21SAlina Sbirlea       : Runs(Runs), MAM(MAM), CGAM(CGAM) {}
981ba90ae96SChandler Carruth 
982ba90ae96SChandler Carruth   /// Run the analysis pass over the function and return a result.
run__anone177e1640111::TestIndirectFunctionAnalysis983ba90ae96SChandler Carruth   Result run(Function &F, FunctionAnalysisManager &AM) {
984ba90ae96SChandler Carruth     ++Runs;
985ba90ae96SChandler Carruth     auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
986ba90ae96SChandler Carruth 
987ba90ae96SChandler Carruth     auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
988ba90ae96SChandler Carruth     // For the test, we insist that the module analysis starts off in the
989bd541b21SAlina Sbirlea     // cache. Getting a cached result that isn't stateless triggers an assert.
990bd541b21SAlina Sbirlea     // Use MAM, for the purposes of this unittest.
991ba90ae96SChandler Carruth     auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
992ba90ae96SChandler Carruth     // Register the dependency as module analysis dependencies have to be
993ba90ae96SChandler Carruth     // pre-registered on the proxy.
994ba90ae96SChandler Carruth     ModuleProxy.registerOuterAnalysisInvalidation<
995ba90ae96SChandler Carruth         TestModuleAnalysis, TestIndirectFunctionAnalysis>();
996ba90ae96SChandler Carruth 
997bd541b21SAlina Sbirlea     // For the test we assume this is run inside a CGSCC pass manager.
998bd541b21SAlina Sbirlea     // Use MAM, for the purposes of this unittest.
999ba90ae96SChandler Carruth     const LazyCallGraph &CG =
1000ba90ae96SChandler Carruth         *MAM.getCachedResult<LazyCallGraphAnalysis>(*F.getParent());
1001ba90ae96SChandler Carruth     auto &CGSCCProxy = AM.getResult<CGSCCAnalysisManagerFunctionProxy>(F);
1002ba90ae96SChandler Carruth     // For the test, we insist that the CGSCC analysis starts off in the cache.
1003bd541b21SAlina Sbirlea     // Getting a cached result that isn't stateless triggers an assert.
1004bd541b21SAlina Sbirlea     // Use CGAM, for the purposes of this unittest.
1005ba90ae96SChandler Carruth     auto &SCCDep =
1006ba90ae96SChandler Carruth         *CGAM.getCachedResult<TestSCCAnalysis>(*CG.lookupSCC(*CG.lookup(F)));
1007ba90ae96SChandler Carruth     // Register the dependency as CGSCC analysis dependencies have to be
1008ba90ae96SChandler Carruth     // pre-registered on the proxy.
1009ba90ae96SChandler Carruth     CGSCCProxy.registerOuterAnalysisInvalidation<
1010ba90ae96SChandler Carruth         TestSCCAnalysis, TestIndirectFunctionAnalysis>();
1011ba90ae96SChandler Carruth 
1012ba90ae96SChandler Carruth     return Result(FDep, MDep, SCCDep);
1013ba90ae96SChandler Carruth   }
1014ba90ae96SChandler Carruth 
1015ba90ae96SChandler Carruth private:
1016ba90ae96SChandler Carruth   friend AnalysisInfoMixin<TestIndirectFunctionAnalysis>;
1017ba90ae96SChandler Carruth   static AnalysisKey Key;
1018ba90ae96SChandler Carruth 
1019ba90ae96SChandler Carruth   int &Runs;
1020bd541b21SAlina Sbirlea   ModuleAnalysisManager &MAM;
1021bd541b21SAlina Sbirlea   CGSCCAnalysisManager &CGAM;
1022ba90ae96SChandler Carruth };
1023ba90ae96SChandler Carruth 
1024ba90ae96SChandler Carruth AnalysisKey TestIndirectFunctionAnalysis::Key;
1025ba90ae96SChandler Carruth 
TEST_F(CGSCCPassManagerTest,TestIndirectAnalysisInvalidation)1026ba90ae96SChandler Carruth TEST_F(CGSCCPassManagerTest, TestIndirectAnalysisInvalidation) {
1027ba90ae96SChandler Carruth   int ModuleAnalysisRuns = 0;
1028ba90ae96SChandler Carruth   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
1029ba90ae96SChandler Carruth 
1030ba90ae96SChandler Carruth   int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
1031ba90ae96SChandler Carruth       DoublyIndirectSCCAnalysisRuns = 0;
1032ba90ae96SChandler Carruth   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
1033ba90ae96SChandler Carruth   CGAM.registerPass(
1034bd541b21SAlina Sbirlea       [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); });
1035ba90ae96SChandler Carruth   CGAM.registerPass([&] {
1036ba90ae96SChandler Carruth     return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
1037ba90ae96SChandler Carruth   });
1038ba90ae96SChandler Carruth 
1039ba90ae96SChandler Carruth   int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
1040ba90ae96SChandler Carruth   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
1041ba90ae96SChandler Carruth   FAM.registerPass([&] {
1042bd541b21SAlina Sbirlea     return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM,
1043bd541b21SAlina Sbirlea                                         CGAM);
1044ba90ae96SChandler Carruth   });
1045ba90ae96SChandler Carruth 
104634a8a437SArthur Eubanks   ModulePassManager MPM;
1047ba90ae96SChandler Carruth 
1048ba90ae96SChandler Carruth   int FunctionCount = 0;
104934a8a437SArthur Eubanks   CGSCCPassManager CGPM;
1050ba90ae96SChandler Carruth   // First just use the analysis to get the function count and preserve
1051ba90ae96SChandler Carruth   // everything.
1052ba90ae96SChandler Carruth   CGPM.addPass(
1053ba90ae96SChandler Carruth       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1054ba90ae96SChandler Carruth                         LazyCallGraph &CG, CGSCCUpdateResult &) {
1055ba90ae96SChandler Carruth         auto &DoublyIndirectResult =
1056ba90ae96SChandler Carruth             AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1057ba90ae96SChandler Carruth         auto &IndirectResult = DoublyIndirectResult.IDep;
1058ba90ae96SChandler Carruth         FunctionCount += IndirectResult.SCCDep.FunctionCount;
1059ba90ae96SChandler Carruth         return PreservedAnalyses::all();
1060ba90ae96SChandler Carruth       }));
1061bd9c2903SChandler Carruth   CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1062bd9c2903SChandler Carruth       RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1063bd9c2903SChandler Carruth 
1064ba90ae96SChandler Carruth   // Next, invalidate
1065ba90ae96SChandler Carruth   //   - both analyses for the (f) and (x) SCCs,
1066ba90ae96SChandler Carruth   //   - just the underlying (indirect) analysis for (g) SCC, and
1067ba90ae96SChandler Carruth   //   - just the direct analysis for (h1,h2,h3) SCC.
1068ba90ae96SChandler Carruth   CGPM.addPass(
1069ba90ae96SChandler Carruth       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1070ba90ae96SChandler Carruth                         LazyCallGraph &CG, CGSCCUpdateResult &) {
1071ba90ae96SChandler Carruth         auto &DoublyIndirectResult =
1072ba90ae96SChandler Carruth             AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1073ba90ae96SChandler Carruth         auto &IndirectResult = DoublyIndirectResult.IDep;
1074ba90ae96SChandler Carruth         FunctionCount += IndirectResult.SCCDep.FunctionCount;
1075ba90ae96SChandler Carruth         auto PA = PreservedAnalyses::none();
1076bd9c2903SChandler Carruth         PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
1077bd9c2903SChandler Carruth         PA.preserveSet<AllAnalysesOn<Function>>();
1078ba90ae96SChandler Carruth         if (C.getName() == "(g)")
1079ba90ae96SChandler Carruth           PA.preserve<TestSCCAnalysis>();
1080ba90ae96SChandler Carruth         else if (C.getName() == "(h3, h1, h2)")
1081ba90ae96SChandler Carruth           PA.preserve<TestIndirectSCCAnalysis>();
1082ba90ae96SChandler Carruth         return PA;
1083ba90ae96SChandler Carruth       }));
1084bd9c2903SChandler Carruth   // Finally, use the analysis again on each SCC (and function), forcing
1085bd9c2903SChandler Carruth   // re-computation for all of them.
1086ba90ae96SChandler Carruth   CGPM.addPass(
1087ba90ae96SChandler Carruth       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1088ba90ae96SChandler Carruth                         LazyCallGraph &CG, CGSCCUpdateResult &) {
1089ba90ae96SChandler Carruth         auto &DoublyIndirectResult =
1090ba90ae96SChandler Carruth             AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1091ba90ae96SChandler Carruth         auto &IndirectResult = DoublyIndirectResult.IDep;
1092ba90ae96SChandler Carruth         FunctionCount += IndirectResult.SCCDep.FunctionCount;
1093ba90ae96SChandler Carruth         return PreservedAnalyses::all();
1094ba90ae96SChandler Carruth       }));
1095bd9c2903SChandler Carruth   CGPM.addPass(createCGSCCToFunctionPassAdaptor(
1096bd9c2903SChandler Carruth       RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1097ba90ae96SChandler Carruth 
1098ba90ae96SChandler Carruth   // Create a second CGSCC pass manager. This will cause the module-level
1099ba90ae96SChandler Carruth   // invalidation to occur, which will force yet another invalidation of the
1100ba90ae96SChandler Carruth   // indirect SCC-level analysis as the module analysis it depends on gets
1101ba90ae96SChandler Carruth   // invalidated.
110234a8a437SArthur Eubanks   CGSCCPassManager CGPM2;
1103ba90ae96SChandler Carruth   CGPM2.addPass(
1104ba90ae96SChandler Carruth       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
1105ba90ae96SChandler Carruth                         LazyCallGraph &CG, CGSCCUpdateResult &) {
1106ba90ae96SChandler Carruth         auto &DoublyIndirectResult =
1107ba90ae96SChandler Carruth             AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
1108ba90ae96SChandler Carruth         auto &IndirectResult = DoublyIndirectResult.IDep;
1109ba90ae96SChandler Carruth         FunctionCount += IndirectResult.SCCDep.FunctionCount;
1110ba90ae96SChandler Carruth         return PreservedAnalyses::all();
1111ba90ae96SChandler Carruth       }));
1112bd9c2903SChandler Carruth   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
1113bd9c2903SChandler Carruth       RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>()));
1114ba90ae96SChandler Carruth 
1115bd9c2903SChandler Carruth   // Add a requires pass to populate the module analysis and then our CGSCC
1116ba90ae96SChandler Carruth   // pass pipeline.
1117ba90ae96SChandler Carruth   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1118ba90ae96SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1119ba90ae96SChandler Carruth   // Now require the module analysis again (it will have been invalidated once)
1120bd9c2903SChandler Carruth   // and then use it again from our second CGSCC pipeline..
1121ba90ae96SChandler Carruth   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
1122ba90ae96SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
1123ba90ae96SChandler Carruth   MPM.run(*M, MAM);
1124ba90ae96SChandler Carruth 
1125ba90ae96SChandler Carruth   // There are generally two possible runs for each of the four SCCs. But
1126ba90ae96SChandler Carruth   // for one SCC, we only invalidate the indirect analysis so the base one
1127ba90ae96SChandler Carruth   // only gets run seven times.
1128ba90ae96SChandler Carruth   EXPECT_EQ(7, SCCAnalysisRuns);
1129ba90ae96SChandler Carruth   // The module analysis pass should be run twice here.
1130ba90ae96SChandler Carruth   EXPECT_EQ(2, ModuleAnalysisRuns);
1131ba90ae96SChandler Carruth   // The indirect analysis is invalidated (either directly or indirectly) three
1132ba90ae96SChandler Carruth   // times for each of four SCCs.
1133ba90ae96SChandler Carruth   EXPECT_EQ(3 * 4, IndirectSCCAnalysisRuns);
1134ba90ae96SChandler Carruth   EXPECT_EQ(3 * 4, DoublyIndirectSCCAnalysisRuns);
1135ba90ae96SChandler Carruth 
1136bd9c2903SChandler Carruth   // We run the indirect function analysis once per function the first time.
1137bd9c2903SChandler Carruth   // Then we re-run it for every SCC but "(g)". Then we re-run it for every
1138bd9c2903SChandler Carruth   // function again.
1139bd9c2903SChandler Carruth   EXPECT_EQ(6 + 5 + 6, IndirectFunctionAnalysisRuns);
1140bd9c2903SChandler Carruth 
1141ba90ae96SChandler Carruth   // Four passes count each of six functions once (via SCCs).
1142ba90ae96SChandler Carruth   EXPECT_EQ(4 * 6, FunctionCount);
1143ba90ae96SChandler Carruth }
11447c8964d8SChandler Carruth 
TEST_F(CGSCCPassManagerTest,TestAnalysisInvalidationCGSCCUpdate)11457c8964d8SChandler Carruth TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) {
11467c8964d8SChandler Carruth   int ModuleAnalysisRuns = 0;
11477c8964d8SChandler Carruth   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
11487c8964d8SChandler Carruth 
11497c8964d8SChandler Carruth   int SCCAnalysisRuns = 0, IndirectSCCAnalysisRuns = 0,
11507c8964d8SChandler Carruth       DoublyIndirectSCCAnalysisRuns = 0;
11517c8964d8SChandler Carruth   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
11527c8964d8SChandler Carruth   CGAM.registerPass(
1153bd541b21SAlina Sbirlea       [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); });
11547c8964d8SChandler Carruth   CGAM.registerPass([&] {
11557c8964d8SChandler Carruth     return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
11567c8964d8SChandler Carruth   });
11577c8964d8SChandler Carruth 
11587c8964d8SChandler Carruth   int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
11597c8964d8SChandler Carruth   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
11607c8964d8SChandler Carruth   FAM.registerPass([&] {
1161bd541b21SAlina Sbirlea     return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM,
1162bd541b21SAlina Sbirlea                                         CGAM);
11637c8964d8SChandler Carruth   });
11647c8964d8SChandler Carruth 
116534a8a437SArthur Eubanks   ModulePassManager MPM;
11667c8964d8SChandler Carruth 
116734a8a437SArthur Eubanks   CGSCCPassManager CGPM;
11687c8964d8SChandler Carruth   // First just use the analysis to get the function count and preserve
11697c8964d8SChandler Carruth   // everything.
11707c8964d8SChandler Carruth   using RequireTestIndirectFunctionAnalysisPass =
11717c8964d8SChandler Carruth       RequireAnalysisPass<TestIndirectFunctionAnalysis, Function>;
11727c8964d8SChandler Carruth   using RequireTestDoublyIndirectSCCAnalysisPass =
11737c8964d8SChandler Carruth       RequireAnalysisPass<TestDoublyIndirectSCCAnalysis, LazyCallGraph::SCC,
11747c8964d8SChandler Carruth                           CGSCCAnalysisManager, LazyCallGraph &,
11757c8964d8SChandler Carruth                           CGSCCUpdateResult &>;
11767c8964d8SChandler Carruth   CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
11777c8964d8SChandler Carruth   CGPM.addPass(createCGSCCToFunctionPassAdaptor(
11787c8964d8SChandler Carruth       RequireTestIndirectFunctionAnalysisPass()));
11797c8964d8SChandler Carruth 
11807c8964d8SChandler Carruth   // Next, we inject an SCC pass that invalidates everything for the `(h3, h1,
11817c8964d8SChandler Carruth   // h2)` SCC but also deletes the call edge from `h2` to `h3` and updates the
11827c8964d8SChandler Carruth   // CG. This should successfully invalidate (and force to be re-run) all the
11837c8964d8SChandler Carruth   // analyses for that SCC and for the functions.
11847c8964d8SChandler Carruth   CGPM.addPass(
11857c8964d8SChandler Carruth       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
11867c8964d8SChandler Carruth                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
11877c8964d8SChandler Carruth         (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
11887c8964d8SChandler Carruth         if (C.getName() != "(h3, h1, h2)")
11897c8964d8SChandler Carruth           return PreservedAnalyses::all();
11907c8964d8SChandler Carruth 
11917c8964d8SChandler Carruth         // Build the preserved set.
11927c8964d8SChandler Carruth         auto PA = PreservedAnalyses::none();
11937c8964d8SChandler Carruth         PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
11947c8964d8SChandler Carruth         PA.preserve<TestIndirectSCCAnalysis>();
11957c8964d8SChandler Carruth         PA.preserve<TestDoublyIndirectSCCAnalysis>();
11967c8964d8SChandler Carruth 
11977c8964d8SChandler Carruth         // Delete the call from `h2` to `h3`.
11987c8964d8SChandler Carruth         auto &H2N = *llvm::find_if(
11997c8964d8SChandler Carruth             C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
12007c8964d8SChandler Carruth         auto &H2F = H2N.getFunction();
12017c8964d8SChandler Carruth         auto &H3F = *cast<CallInst>(H2F.begin()->begin())->getCalledFunction();
12027c8964d8SChandler Carruth         assert(H3F.getName() == "h3" && "Wrong called function!");
12037c8964d8SChandler Carruth         H2F.begin()->begin()->eraseFromParent();
12047c8964d8SChandler Carruth         // Insert a bitcast of `h3` so that we retain a ref edge to it.
12057c8964d8SChandler Carruth         (void)CastInst::CreatePointerCast(&H3F,
12067c8964d8SChandler Carruth                                           Type::getInt8PtrTy(H2F.getContext()),
12077c8964d8SChandler Carruth                                           "dummy", &*H2F.begin()->begin());
12087c8964d8SChandler Carruth 
12097c8964d8SChandler Carruth         // Now update the call graph.
121019913b22SChandler Carruth         auto &NewC =
1211bd541b21SAlina Sbirlea             updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM);
12127c8964d8SChandler Carruth         assert(&NewC != &C && "Should get a new SCC due to update!");
12133733fc40SNAKAMURA Takumi         (void)&NewC;
12147c8964d8SChandler Carruth 
12157c8964d8SChandler Carruth         return PA;
12167c8964d8SChandler Carruth       }));
12177c8964d8SChandler Carruth   // Now use the analysis again on each SCC and function, forcing
12187c8964d8SChandler Carruth   // re-computation for all of them.
12197c8964d8SChandler Carruth   CGPM.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
12207c8964d8SChandler Carruth   CGPM.addPass(createCGSCCToFunctionPassAdaptor(
12217c8964d8SChandler Carruth       RequireTestIndirectFunctionAnalysisPass()));
12227c8964d8SChandler Carruth 
12237c8964d8SChandler Carruth   // Create another CGSCC pipeline that requires all the analyses again.
122434a8a437SArthur Eubanks   CGSCCPassManager CGPM2;
12257c8964d8SChandler Carruth   CGPM2.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
12267c8964d8SChandler Carruth   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(
12277c8964d8SChandler Carruth       RequireTestIndirectFunctionAnalysisPass()));
12287c8964d8SChandler Carruth 
12297c8964d8SChandler Carruth   // Next we inject an SCC pass that finds the `(h2)` SCC, adds a call to `h3`
12307c8964d8SChandler Carruth   // back to `h2`, and then invalidates everything for what will then be the
12317c8964d8SChandler Carruth   // `(h3, h1, h2)` SCC again.
123234a8a437SArthur Eubanks   CGSCCPassManager CGPM3;
12337c8964d8SChandler Carruth   CGPM3.addPass(
12347c8964d8SChandler Carruth       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
12357c8964d8SChandler Carruth                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
12367c8964d8SChandler Carruth         (void)AM.getResult<TestDoublyIndirectSCCAnalysis>(C, CG);
12377c8964d8SChandler Carruth         if (C.getName() != "(h2)")
12387c8964d8SChandler Carruth           return PreservedAnalyses::all();
12397c8964d8SChandler Carruth 
12407c8964d8SChandler Carruth         // Build the preserved set.
12417c8964d8SChandler Carruth         auto PA = PreservedAnalyses::none();
12427c8964d8SChandler Carruth         PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
12437c8964d8SChandler Carruth         PA.preserve<TestIndirectSCCAnalysis>();
12447c8964d8SChandler Carruth         PA.preserve<TestDoublyIndirectSCCAnalysis>();
12457c8964d8SChandler Carruth 
12467c8964d8SChandler Carruth         // Delete the bitcast of `h3` that we added earlier.
12477c8964d8SChandler Carruth         auto &H2N = *C.begin();
12487c8964d8SChandler Carruth         auto &H2F = H2N.getFunction();
12497c8964d8SChandler Carruth         auto &H3F = *cast<Function>(cast<BitCastInst>(H2F.begin()->begin())->getOperand(0));
12507c8964d8SChandler Carruth         assert(H3F.getName() == "h3" && "Wrong called function!");
12517c8964d8SChandler Carruth         H2F.begin()->begin()->eraseFromParent();
12527c8964d8SChandler Carruth         // And insert a call to `h3`.
12537c8964d8SChandler Carruth         (void)CallInst::Create(&H3F, {}, "", &*H2F.begin()->begin());
12547c8964d8SChandler Carruth 
12557c8964d8SChandler Carruth         // Now update the call graph.
125619913b22SChandler Carruth         auto &NewC =
1257bd541b21SAlina Sbirlea             updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM);
12587c8964d8SChandler Carruth         assert(&NewC != &C && "Should get a new SCC due to update!");
12593733fc40SNAKAMURA Takumi         (void)&NewC;
12607c8964d8SChandler Carruth 
12617c8964d8SChandler Carruth         return PA;
12627c8964d8SChandler Carruth       }));
12637c8964d8SChandler Carruth   // Now use the analysis again on each SCC and function, forcing
12647c8964d8SChandler Carruth   // re-computation for all of them.
12657c8964d8SChandler Carruth   CGPM3.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
12667c8964d8SChandler Carruth   CGPM3.addPass(createCGSCCToFunctionPassAdaptor(
12677c8964d8SChandler Carruth       RequireTestIndirectFunctionAnalysisPass()));
12687c8964d8SChandler Carruth 
12697c8964d8SChandler Carruth   // Create a second CGSCC pass manager. This will cause the module-level
12707c8964d8SChandler Carruth   // invalidation to occur, which will force yet another invalidation of the
12717c8964d8SChandler Carruth   // indirect SCC-level analysis as the module analysis it depends on gets
12727c8964d8SChandler Carruth   // invalidated.
127334a8a437SArthur Eubanks   CGSCCPassManager CGPM4;
12747c8964d8SChandler Carruth   CGPM4.addPass(RequireTestDoublyIndirectSCCAnalysisPass());
12757c8964d8SChandler Carruth   CGPM4.addPass(createCGSCCToFunctionPassAdaptor(
12767c8964d8SChandler Carruth       RequireTestIndirectFunctionAnalysisPass()));
12777c8964d8SChandler Carruth 
12787c8964d8SChandler Carruth   // Add a requires pass to populate the module analysis and then one of our
12797c8964d8SChandler Carruth   // CGSCC pipelines. Repeat for all four CGSCC pipelines.
12807c8964d8SChandler Carruth   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
12817c8964d8SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
12827c8964d8SChandler Carruth   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
12837c8964d8SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
12847c8964d8SChandler Carruth   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
12857c8964d8SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
12867c8964d8SChandler Carruth   MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
12877c8964d8SChandler Carruth   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM4)));
12887c8964d8SChandler Carruth   MPM.run(*M, MAM);
12897c8964d8SChandler Carruth 
12907c8964d8SChandler Carruth   // We run over four SCCs the first time. But then we split an SCC into three.
1291923ff550SChandler Carruth   // And then we merge those three back into one. However, this also
1292923ff550SChandler Carruth   // invalidates all three SCCs further down in the PO walk.
1293b559535aSWenlei He   EXPECT_EQ(4 + 3 + 3, SCCAnalysisRuns);
12947c8964d8SChandler Carruth   // The module analysis pass should be run three times.
12957c8964d8SChandler Carruth   EXPECT_EQ(3, ModuleAnalysisRuns);
12967c8964d8SChandler Carruth   // We run over four SCCs the first time. Then over the two new ones. Then the
12977c8964d8SChandler Carruth   // entire module is invalidated causing a full run over all seven. Then we
1298923ff550SChandler Carruth   // fold three SCCs back to one, re-compute for it and the two SCCs above it
1299923ff550SChandler Carruth   // in the graph, and then run over the whole module again.
1300b559535aSWenlei He   EXPECT_EQ(4 + 2 + 7 + 3 + 4, IndirectSCCAnalysisRuns);
1301b559535aSWenlei He   EXPECT_EQ(4 + 2 + 7 + 3 + 4, DoublyIndirectSCCAnalysisRuns);
13027c8964d8SChandler Carruth 
13037c8964d8SChandler Carruth   // First we run over all six functions. Then we re-run it over three when we
13047c8964d8SChandler Carruth   // split their SCCs. Then we re-run over the whole module. Then we re-run
1305923ff550SChandler Carruth   // over three functions merged back into a single SCC, then those three
1306923ff550SChandler Carruth   // functions again, the two functions in SCCs above it in the graph, and then
1307923ff550SChandler Carruth   // over the whole module again.
1308b559535aSWenlei He   EXPECT_EQ(6 + 3 + 6 + 3 + 2 + 6, FunctionAnalysisRuns);
13097c8964d8SChandler Carruth 
1310051bdb0bSChandler Carruth   // Re run the function analysis over the entire module, and then re-run it
1311051bdb0bSChandler Carruth   // over the `(h3, h1, h2)` SCC due to invalidation. Then we re-run it over
1312051bdb0bSChandler Carruth   // the entire module, then the three functions merged back into a single SCC,
1313923ff550SChandler Carruth   // those three functions again, then the two functions in SCCs above it in
1314923ff550SChandler Carruth   // the graph, and then over the whole module.
1315b559535aSWenlei He   EXPECT_EQ(6 + 3 + 6 + 3 + 2 + 6, IndirectFunctionAnalysisRuns);
13167c8964d8SChandler Carruth }
131701377453SJohannes Doerfert 
131801377453SJohannes Doerfert // The (negative) tests below check for assertions so we only run them if NDEBUG
131901377453SJohannes Doerfert // is not defined.
132001377453SJohannes Doerfert #ifndef NDEBUG
132101377453SJohannes Doerfert 
132201377453SJohannes Doerfert struct LambdaSCCPassNoPreserve : public PassInfoMixin<LambdaSCCPassNoPreserve> {
132301377453SJohannes Doerfert   template <typename T>
LambdaSCCPassNoPreserve__anone177e1640111::LambdaSCCPassNoPreserve132401377453SJohannes Doerfert   LambdaSCCPassNoPreserve(T &&Arg) : Func(std::forward<T>(Arg)) {}
132501377453SJohannes Doerfert 
run__anone177e1640111::LambdaSCCPassNoPreserve132601377453SJohannes Doerfert   PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
132701377453SJohannes Doerfert                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
132801377453SJohannes Doerfert     Func(C, AM, CG, UR);
132972277ecdSJohannes Doerfert     PreservedAnalyses PA;
133072277ecdSJohannes Doerfert     // We update the core CGSCC data structures and so can preserve the proxy to
133172277ecdSJohannes Doerfert     // the function analysis manager.
133272277ecdSJohannes Doerfert     PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
133372277ecdSJohannes Doerfert     return PA;
133474319922SChandler Carruth   }
133501377453SJohannes Doerfert 
133601377453SJohannes Doerfert   std::function<void(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
133701377453SJohannes Doerfert                      LazyCallGraph &, CGSCCUpdateResult &)>
133801377453SJohannes Doerfert       Func;
133901377453SJohannes Doerfert };
134001377453SJohannes Doerfert 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses0)134101377453SJohannes Doerfert TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses0) {
134234a8a437SArthur Eubanks   CGSCCPassManager CGPM;
134301377453SJohannes Doerfert   CGPM.addPass(LambdaSCCPassNoPreserve(
134401377453SJohannes Doerfert       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
134501377453SJohannes Doerfert           CGSCCUpdateResult &UR) {
134601377453SJohannes Doerfert         if (C.getName() != "(h3, h1, h2)")
134701377453SJohannes Doerfert           return;
134801377453SJohannes Doerfert 
1349bd541b21SAlina Sbirlea         auto &FAM =
1350bd541b21SAlina Sbirlea             AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
135101377453SJohannes Doerfert         Function *FnX = M->getFunction("x");
135201377453SJohannes Doerfert         Function *FnH1 = M->getFunction("h1");
135301377453SJohannes Doerfert         Function *FnH2 = M->getFunction("h2");
135401377453SJohannes Doerfert         Function *FnH3 = M->getFunction("h3");
135501377453SJohannes Doerfert         ASSERT_NE(FnX, nullptr);
135601377453SJohannes Doerfert         ASSERT_NE(FnH1, nullptr);
135701377453SJohannes Doerfert         ASSERT_NE(FnH2, nullptr);
135801377453SJohannes Doerfert         ASSERT_NE(FnH3, nullptr);
135901377453SJohannes Doerfert 
136001377453SJohannes Doerfert         // And insert a call to `h1`, `h2`, and `h3`.
136101377453SJohannes Doerfert         Instruction *IP = &FnH2->getEntryBlock().front();
136201377453SJohannes Doerfert         (void)CallInst::Create(FnH1, {}, "", IP);
136301377453SJohannes Doerfert         (void)CallInst::Create(FnH2, {}, "", IP);
136401377453SJohannes Doerfert         (void)CallInst::Create(FnH3, {}, "", IP);
136501377453SJohannes Doerfert 
136601377453SJohannes Doerfert         auto &H2N = *llvm::find_if(
136701377453SJohannes Doerfert             C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
136801377453SJohannes Doerfert         ASSERT_NO_FATAL_FAILURE(
1369bd541b21SAlina Sbirlea             updateCGAndAnalysisManagerForCGSCCPass(CG, C, H2N, AM, UR, FAM));
137001377453SJohannes Doerfert       }));
137101377453SJohannes Doerfert 
137234a8a437SArthur Eubanks   ModulePassManager MPM;
137301377453SJohannes Doerfert   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
137401377453SJohannes Doerfert   MPM.run(*M, MAM);
137501377453SJohannes Doerfert }
137601377453SJohannes Doerfert 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses1)137701377453SJohannes Doerfert TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses1) {
137834a8a437SArthur Eubanks   CGSCCPassManager CGPM;
137901377453SJohannes Doerfert   CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
138001377453SJohannes Doerfert                                            CGSCCAnalysisManager &AM,
138101377453SJohannes Doerfert                                            LazyCallGraph &CG,
138201377453SJohannes Doerfert                                            CGSCCUpdateResult &UR) {
138301377453SJohannes Doerfert     if (C.getName() != "(h3, h1, h2)")
138401377453SJohannes Doerfert       return;
138501377453SJohannes Doerfert 
1386bd541b21SAlina Sbirlea     auto &FAM =
1387bd541b21SAlina Sbirlea         AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
138801377453SJohannes Doerfert     Function *FnX = M->getFunction("x");
138901377453SJohannes Doerfert     Function *FnH1 = M->getFunction("h1");
139001377453SJohannes Doerfert     Function *FnH2 = M->getFunction("h2");
139101377453SJohannes Doerfert     Function *FnH3 = M->getFunction("h3");
139201377453SJohannes Doerfert     ASSERT_NE(FnX, nullptr);
139301377453SJohannes Doerfert     ASSERT_NE(FnH1, nullptr);
139401377453SJohannes Doerfert     ASSERT_NE(FnH2, nullptr);
139501377453SJohannes Doerfert     ASSERT_NE(FnH3, nullptr);
139601377453SJohannes Doerfert 
139701377453SJohannes Doerfert     // And insert a call to `h1`, `h2`, and `h3`.
139801377453SJohannes Doerfert     Instruction *IP = &FnH2->getEntryBlock().front();
139901377453SJohannes Doerfert     (void)CallInst::Create(FnH1, {}, "", IP);
140001377453SJohannes Doerfert     (void)CallInst::Create(FnH2, {}, "", IP);
140101377453SJohannes Doerfert     (void)CallInst::Create(FnH3, {}, "", IP);
140201377453SJohannes Doerfert 
140301377453SJohannes Doerfert     auto &H2N = *llvm::find_if(
140401377453SJohannes Doerfert         C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
1405bd541b21SAlina Sbirlea     ASSERT_DEATH(
1406bd541b21SAlina Sbirlea         updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM),
140701377453SJohannes Doerfert         "Any new calls should be modeled as");
140801377453SJohannes Doerfert   }));
140901377453SJohannes Doerfert 
141034a8a437SArthur Eubanks   ModulePassManager MPM;
141101377453SJohannes Doerfert   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
141201377453SJohannes Doerfert   MPM.run(*M, MAM);
141301377453SJohannes Doerfert }
141401377453SJohannes Doerfert 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses2)141501377453SJohannes Doerfert TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses2) {
141634a8a437SArthur Eubanks   CGSCCPassManager CGPM;
141701377453SJohannes Doerfert   CGPM.addPass(LambdaSCCPassNoPreserve(
141801377453SJohannes Doerfert       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
141901377453SJohannes Doerfert           CGSCCUpdateResult &UR) {
142001377453SJohannes Doerfert         if (C.getName() != "(f)")
142101377453SJohannes Doerfert           return;
142201377453SJohannes Doerfert 
1423bd541b21SAlina Sbirlea         auto &FAM =
1424bd541b21SAlina Sbirlea             AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
142501377453SJohannes Doerfert         Function *FnF = M->getFunction("f");
142601377453SJohannes Doerfert         Function *FnH2 = M->getFunction("h2");
142701377453SJohannes Doerfert         ASSERT_NE(FnF, nullptr);
142801377453SJohannes Doerfert         ASSERT_NE(FnH2, nullptr);
142901377453SJohannes Doerfert 
143001377453SJohannes Doerfert         // And insert a call to `h2`
143101377453SJohannes Doerfert         Instruction *IP = &FnF->getEntryBlock().front();
143201377453SJohannes Doerfert         (void)CallInst::Create(FnH2, {}, "", IP);
143301377453SJohannes Doerfert 
143401377453SJohannes Doerfert         auto &FN = *llvm::find_if(
143501377453SJohannes Doerfert             C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
143601377453SJohannes Doerfert         ASSERT_NO_FATAL_FAILURE(
1437bd541b21SAlina Sbirlea             updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM));
143801377453SJohannes Doerfert       }));
143901377453SJohannes Doerfert 
144034a8a437SArthur Eubanks   ModulePassManager MPM;
144101377453SJohannes Doerfert   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
144201377453SJohannes Doerfert   MPM.run(*M, MAM);
144301377453SJohannes Doerfert }
144401377453SJohannes Doerfert 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses3)144501377453SJohannes Doerfert TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses3) {
144634a8a437SArthur Eubanks   CGSCCPassManager CGPM;
144701377453SJohannes Doerfert   CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
144801377453SJohannes Doerfert                                            CGSCCAnalysisManager &AM,
144901377453SJohannes Doerfert                                            LazyCallGraph &CG,
145001377453SJohannes Doerfert                                            CGSCCUpdateResult &UR) {
145101377453SJohannes Doerfert     if (C.getName() != "(f)")
145201377453SJohannes Doerfert       return;
145301377453SJohannes Doerfert 
1454bd541b21SAlina Sbirlea     auto &FAM =
1455bd541b21SAlina Sbirlea         AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
145601377453SJohannes Doerfert     Function *FnF = M->getFunction("f");
145701377453SJohannes Doerfert     Function *FnH2 = M->getFunction("h2");
145801377453SJohannes Doerfert     ASSERT_NE(FnF, nullptr);
145901377453SJohannes Doerfert     ASSERT_NE(FnH2, nullptr);
146001377453SJohannes Doerfert 
146101377453SJohannes Doerfert     // And insert a call to `h2`
146201377453SJohannes Doerfert     Instruction *IP = &FnF->getEntryBlock().front();
146301377453SJohannes Doerfert     (void)CallInst::Create(FnH2, {}, "", IP);
146401377453SJohannes Doerfert 
146501377453SJohannes Doerfert     auto &FN = *llvm::find_if(
146601377453SJohannes Doerfert         C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
1467bd541b21SAlina Sbirlea     ASSERT_DEATH(
1468bd541b21SAlina Sbirlea         updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR, FAM),
146901377453SJohannes Doerfert         "Any new calls should be modeled as");
147001377453SJohannes Doerfert   }));
147101377453SJohannes Doerfert 
147234a8a437SArthur Eubanks   ModulePassManager MPM;
147301377453SJohannes Doerfert   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
147401377453SJohannes Doerfert   MPM.run(*M, MAM);
147501377453SJohannes Doerfert }
147601377453SJohannes Doerfert 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses4)147772277ecdSJohannes Doerfert TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses4) {
147834a8a437SArthur Eubanks   CGSCCPassManager CGPM;
147972277ecdSJohannes Doerfert   CGPM.addPass(LambdaSCCPassNoPreserve(
148072277ecdSJohannes Doerfert       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
148172277ecdSJohannes Doerfert           CGSCCUpdateResult &UR) {
148272277ecdSJohannes Doerfert         if (C.getName() != "(f)")
148372277ecdSJohannes Doerfert           return;
148472277ecdSJohannes Doerfert 
1485bd541b21SAlina Sbirlea         auto &FAM =
1486bd541b21SAlina Sbirlea             AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
148772277ecdSJohannes Doerfert         Function *FnF = M->getFunction("f");
148872277ecdSJohannes Doerfert         Function *FnewF = Function::Create(FnF->getFunctionType(),
148972277ecdSJohannes Doerfert                                            FnF->getLinkage(), "newF", *M);
149072277ecdSJohannes Doerfert         BasicBlock *BB = BasicBlock::Create(FnewF->getContext(), "", FnewF);
149172277ecdSJohannes Doerfert         ReturnInst::Create(FnewF->getContext(), BB);
149272277ecdSJohannes Doerfert 
14937fea561eSArthur Eubanks         // And insert a call to `newF`
14947fea561eSArthur Eubanks         Instruction *IP = &FnF->getEntryBlock().front();
14957fea561eSArthur Eubanks         (void)CallInst::Create(FnewF, {}, "", IP);
14967fea561eSArthur Eubanks 
149772277ecdSJohannes Doerfert         // Use the CallGraphUpdater to update the call graph for the new
149872277ecdSJohannes Doerfert         // function.
149972277ecdSJohannes Doerfert         CallGraphUpdater CGU;
150072277ecdSJohannes Doerfert         CGU.initialize(CG, C, AM, UR);
15017fea561eSArthur Eubanks         CGU.registerOutlinedFunction(*FnF, *FnewF);
150272277ecdSJohannes Doerfert 
150372277ecdSJohannes Doerfert         auto &FN = *llvm::find_if(
150472277ecdSJohannes Doerfert             C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
150572277ecdSJohannes Doerfert 
150672277ecdSJohannes Doerfert         ASSERT_NO_FATAL_FAILURE(
1507bd541b21SAlina Sbirlea             updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM));
150872277ecdSJohannes Doerfert       }));
150972277ecdSJohannes Doerfert 
151034a8a437SArthur Eubanks   ModulePassManager MPM;
151172277ecdSJohannes Doerfert   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
151272277ecdSJohannes Doerfert   MPM.run(*M, MAM);
151372277ecdSJohannes Doerfert }
151472277ecdSJohannes Doerfert 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses5)151572277ecdSJohannes Doerfert TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses5) {
151634a8a437SArthur Eubanks   CGSCCPassManager CGPM;
151772277ecdSJohannes Doerfert   CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
151872277ecdSJohannes Doerfert                                            CGSCCAnalysisManager &AM,
151972277ecdSJohannes Doerfert                                            LazyCallGraph &CG,
152072277ecdSJohannes Doerfert                                            CGSCCUpdateResult &UR) {
152172277ecdSJohannes Doerfert     if (C.getName() != "(f)")
152272277ecdSJohannes Doerfert       return;
152372277ecdSJohannes Doerfert 
1524bd541b21SAlina Sbirlea     auto &FAM =
1525bd541b21SAlina Sbirlea         AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
152672277ecdSJohannes Doerfert     Function *FnF = M->getFunction("f");
152772277ecdSJohannes Doerfert     Function *FnewF =
152872277ecdSJohannes Doerfert         Function::Create(FnF->getFunctionType(), FnF->getLinkage(), "newF", *M);
152972277ecdSJohannes Doerfert     BasicBlock *BB = BasicBlock::Create(FnewF->getContext(), "", FnewF);
153072277ecdSJohannes Doerfert     ReturnInst::Create(FnewF->getContext(), BB);
153172277ecdSJohannes Doerfert 
153272277ecdSJohannes Doerfert     // Use the CallGraphUpdater to update the call graph for the new
153372277ecdSJohannes Doerfert     // function.
153472277ecdSJohannes Doerfert     CallGraphUpdater CGU;
153572277ecdSJohannes Doerfert     CGU.initialize(CG, C, AM, UR);
153672277ecdSJohannes Doerfert 
153772277ecdSJohannes Doerfert     // And insert a call to `newF`
153872277ecdSJohannes Doerfert     Instruction *IP = &FnF->getEntryBlock().front();
153972277ecdSJohannes Doerfert     (void)CallInst::Create(FnewF, {}, "", IP);
154072277ecdSJohannes Doerfert 
154172277ecdSJohannes Doerfert     auto &FN = *llvm::find_if(
154272277ecdSJohannes Doerfert         C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
154372277ecdSJohannes Doerfert 
15447fea561eSArthur Eubanks     ASSERT_DEATH(updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM),
15457fea561eSArthur Eubanks                  "should already have an associated node");
154672277ecdSJohannes Doerfert   }));
154772277ecdSJohannes Doerfert 
154834a8a437SArthur Eubanks   ModulePassManager MPM;
154972277ecdSJohannes Doerfert   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
155072277ecdSJohannes Doerfert   MPM.run(*M, MAM);
155172277ecdSJohannes Doerfert }
155272277ecdSJohannes Doerfert 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses6)155372277ecdSJohannes Doerfert TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses6) {
155434a8a437SArthur Eubanks   CGSCCPassManager CGPM;
155572277ecdSJohannes Doerfert   CGPM.addPass(LambdaSCCPassNoPreserve(
155672277ecdSJohannes Doerfert       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
155772277ecdSJohannes Doerfert           CGSCCUpdateResult &UR) {
155872277ecdSJohannes Doerfert         if (C.getName() != "(h3, h1, h2)")
155972277ecdSJohannes Doerfert           return;
156072277ecdSJohannes Doerfert 
156172277ecdSJohannes Doerfert         Function *FnX = M->getFunction("x");
156272277ecdSJohannes Doerfert         Function *FnH1 = M->getFunction("h1");
156372277ecdSJohannes Doerfert         Function *FnH2 = M->getFunction("h2");
156472277ecdSJohannes Doerfert         Function *FnH3 = M->getFunction("h3");
156572277ecdSJohannes Doerfert         ASSERT_NE(FnX, nullptr);
156672277ecdSJohannes Doerfert         ASSERT_NE(FnH1, nullptr);
156772277ecdSJohannes Doerfert         ASSERT_NE(FnH2, nullptr);
156872277ecdSJohannes Doerfert         ASSERT_NE(FnH3, nullptr);
156972277ecdSJohannes Doerfert 
157072277ecdSJohannes Doerfert         // And insert a call to `h1`, `h2`, and `h3`.
157172277ecdSJohannes Doerfert         Instruction *IP = &FnH2->getEntryBlock().front();
157272277ecdSJohannes Doerfert         (void)CallInst::Create(FnH1, {}, "", IP);
157372277ecdSJohannes Doerfert         (void)CallInst::Create(FnH2, {}, "", IP);
157472277ecdSJohannes Doerfert         (void)CallInst::Create(FnH3, {}, "", IP);
157572277ecdSJohannes Doerfert 
157672277ecdSJohannes Doerfert         // Use the CallGraphUpdater to update the call graph for the new
157772277ecdSJohannes Doerfert         // function.
157872277ecdSJohannes Doerfert         CallGraphUpdater CGU;
157972277ecdSJohannes Doerfert         CGU.initialize(CG, C, AM, UR);
158072277ecdSJohannes Doerfert         ASSERT_NO_FATAL_FAILURE(CGU.reanalyzeFunction(*FnH2));
158172277ecdSJohannes Doerfert       }));
158272277ecdSJohannes Doerfert 
158334a8a437SArthur Eubanks   ModulePassManager MPM;
158472277ecdSJohannes Doerfert   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
158572277ecdSJohannes Doerfert   MPM.run(*M, MAM);
158672277ecdSJohannes Doerfert }
158772277ecdSJohannes Doerfert 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses7)158872277ecdSJohannes Doerfert TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses7) {
158934a8a437SArthur Eubanks   CGSCCPassManager CGPM;
159072277ecdSJohannes Doerfert   CGPM.addPass(LambdaSCCPassNoPreserve(
159172277ecdSJohannes Doerfert       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
159272277ecdSJohannes Doerfert           CGSCCUpdateResult &UR) {
159372277ecdSJohannes Doerfert         if (C.getName() != "(f)")
159472277ecdSJohannes Doerfert           return;
159572277ecdSJohannes Doerfert 
159672277ecdSJohannes Doerfert         Function *FnF = M->getFunction("f");
159772277ecdSJohannes Doerfert         Function *FnH2 = M->getFunction("h2");
159872277ecdSJohannes Doerfert         ASSERT_NE(FnF, nullptr);
159972277ecdSJohannes Doerfert         ASSERT_NE(FnH2, nullptr);
160072277ecdSJohannes Doerfert 
160172277ecdSJohannes Doerfert         // And insert a call to `h2`
160272277ecdSJohannes Doerfert         Instruction *IP = &FnF->getEntryBlock().front();
160372277ecdSJohannes Doerfert         (void)CallInst::Create(FnH2, {}, "", IP);
160472277ecdSJohannes Doerfert 
160572277ecdSJohannes Doerfert         // Use the CallGraphUpdater to update the call graph for the new
160672277ecdSJohannes Doerfert         // function.
160772277ecdSJohannes Doerfert         CallGraphUpdater CGU;
160872277ecdSJohannes Doerfert         CGU.initialize(CG, C, AM, UR);
160972277ecdSJohannes Doerfert         ASSERT_NO_FATAL_FAILURE(CGU.reanalyzeFunction(*FnF));
161072277ecdSJohannes Doerfert       }));
161172277ecdSJohannes Doerfert 
161234a8a437SArthur Eubanks   ModulePassManager MPM;
161372277ecdSJohannes Doerfert   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
161472277ecdSJohannes Doerfert   MPM.run(*M, MAM);
161572277ecdSJohannes Doerfert }
161672277ecdSJohannes Doerfert 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses8)161772277ecdSJohannes Doerfert TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses8) {
161834a8a437SArthur Eubanks   CGSCCPassManager CGPM;
161972277ecdSJohannes Doerfert   CGPM.addPass(LambdaSCCPassNoPreserve(
162072277ecdSJohannes Doerfert       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
162172277ecdSJohannes Doerfert           CGSCCUpdateResult &UR) {
162272277ecdSJohannes Doerfert         if (C.getName() != "(f)")
162372277ecdSJohannes Doerfert           return;
162472277ecdSJohannes Doerfert 
162572277ecdSJohannes Doerfert         Function *FnF = M->getFunction("f");
162672277ecdSJohannes Doerfert         Function *FnewF = Function::Create(FnF->getFunctionType(),
162772277ecdSJohannes Doerfert                                            FnF->getLinkage(), "newF", *M);
162872277ecdSJohannes Doerfert         BasicBlock *BB = BasicBlock::Create(FnewF->getContext(), "", FnewF);
162972277ecdSJohannes Doerfert         auto *RI = ReturnInst::Create(FnewF->getContext(), BB);
163072277ecdSJohannes Doerfert         while (FnF->getEntryBlock().size() > 1)
163172277ecdSJohannes Doerfert           FnF->getEntryBlock().front().moveBefore(RI);
163272277ecdSJohannes Doerfert         ASSERT_NE(FnF, nullptr);
163372277ecdSJohannes Doerfert 
1634cb0ecc5cSJohannes Doerfert         // Create an unsused constant that is referencing the old (=replaced)
1635cb0ecc5cSJohannes Doerfert         // function.
1636cb0ecc5cSJohannes Doerfert         ConstantExpr::getBitCast(FnF, Type::getInt8PtrTy(FnF->getContext()));
1637cb0ecc5cSJohannes Doerfert 
163872277ecdSJohannes Doerfert         // Use the CallGraphUpdater to update the call graph.
163972277ecdSJohannes Doerfert         CallGraphUpdater CGU;
164072277ecdSJohannes Doerfert         CGU.initialize(CG, C, AM, UR);
164172277ecdSJohannes Doerfert         ASSERT_NO_FATAL_FAILURE(CGU.replaceFunctionWith(*FnF, *FnewF));
164272277ecdSJohannes Doerfert         ASSERT_TRUE(FnF->isDeclaration());
164372277ecdSJohannes Doerfert         ASSERT_EQ(FnF->getNumUses(), 0U);
164472277ecdSJohannes Doerfert       }));
164572277ecdSJohannes Doerfert 
164634a8a437SArthur Eubanks   ModulePassManager MPM;
164772277ecdSJohannes Doerfert   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
164872277ecdSJohannes Doerfert   MPM.run(*M, MAM);
164972277ecdSJohannes Doerfert }
165072277ecdSJohannes Doerfert 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses9)165172277ecdSJohannes Doerfert TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses9) {
165234a8a437SArthur Eubanks   CGSCCPassManager CGPM;
165372277ecdSJohannes Doerfert   CGPM.addPass(LambdaSCCPassNoPreserve(
165472277ecdSJohannes Doerfert       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
165572277ecdSJohannes Doerfert           CGSCCUpdateResult &UR) {
165672277ecdSJohannes Doerfert         if (C.getName() != "(f)")
165772277ecdSJohannes Doerfert           return;
165872277ecdSJohannes Doerfert 
165972277ecdSJohannes Doerfert         Function *FnF = M->getFunction("f");
166072277ecdSJohannes Doerfert 
166172277ecdSJohannes Doerfert         // Use the CallGraphUpdater to update the call graph.
166272277ecdSJohannes Doerfert         {
166372277ecdSJohannes Doerfert           CallGraphUpdater CGU;
166472277ecdSJohannes Doerfert           CGU.initialize(CG, C, AM, UR);
166572277ecdSJohannes Doerfert           ASSERT_NO_FATAL_FAILURE(CGU.removeFunction(*FnF));
166672277ecdSJohannes Doerfert           ASSERT_EQ(M->getFunctionList().size(), 6U);
166772277ecdSJohannes Doerfert         }
166872277ecdSJohannes Doerfert         ASSERT_EQ(M->getFunctionList().size(), 5U);
166972277ecdSJohannes Doerfert       }));
167072277ecdSJohannes Doerfert 
167134a8a437SArthur Eubanks   ModulePassManager MPM;
167272277ecdSJohannes Doerfert   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
167372277ecdSJohannes Doerfert   MPM.run(*M, MAM);
167472277ecdSJohannes Doerfert }
167572277ecdSJohannes Doerfert 
TEST_F(CGSCCPassManagerTest,TestUpdateCGAndAnalysisManagerForPasses10)167672277ecdSJohannes Doerfert TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses10) {
167734a8a437SArthur Eubanks   CGSCCPassManager CGPM;
167872277ecdSJohannes Doerfert   CGPM.addPass(LambdaSCCPassNoPreserve(
167972277ecdSJohannes Doerfert       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
168072277ecdSJohannes Doerfert           CGSCCUpdateResult &UR) {
168172277ecdSJohannes Doerfert         if (C.getName() != "(h3, h1, h2)")
168272277ecdSJohannes Doerfert           return;
168372277ecdSJohannes Doerfert 
168472277ecdSJohannes Doerfert         Function *FnX = M->getFunction("x");
168572277ecdSJohannes Doerfert         Function *FnH1 = M->getFunction("h1");
168672277ecdSJohannes Doerfert         Function *FnH2 = M->getFunction("h2");
168772277ecdSJohannes Doerfert         Function *FnH3 = M->getFunction("h3");
168872277ecdSJohannes Doerfert         ASSERT_NE(FnX, nullptr);
168972277ecdSJohannes Doerfert         ASSERT_NE(FnH1, nullptr);
169072277ecdSJohannes Doerfert         ASSERT_NE(FnH2, nullptr);
169172277ecdSJohannes Doerfert         ASSERT_NE(FnH3, nullptr);
169272277ecdSJohannes Doerfert 
169372277ecdSJohannes Doerfert         // And insert a call to `h1`, and `h3`.
169472277ecdSJohannes Doerfert         Instruction *IP = &FnH1->getEntryBlock().front();
169572277ecdSJohannes Doerfert         (void)CallInst::Create(FnH1, {}, "", IP);
169672277ecdSJohannes Doerfert         (void)CallInst::Create(FnH3, {}, "", IP);
169772277ecdSJohannes Doerfert 
169872277ecdSJohannes Doerfert         // Remove the `h2` call.
169972277ecdSJohannes Doerfert         ASSERT_TRUE(isa<CallBase>(IP));
170072277ecdSJohannes Doerfert         ASSERT_EQ(cast<CallBase>(IP)->getCalledFunction(), FnH2);
170172277ecdSJohannes Doerfert         IP->eraseFromParent();
170272277ecdSJohannes Doerfert 
170372277ecdSJohannes Doerfert         // Use the CallGraphUpdater to update the call graph.
170472277ecdSJohannes Doerfert         CallGraphUpdater CGU;
170572277ecdSJohannes Doerfert         CGU.initialize(CG, C, AM, UR);
170672277ecdSJohannes Doerfert         ASSERT_NO_FATAL_FAILURE(CGU.reanalyzeFunction(*FnH1));
170772277ecdSJohannes Doerfert         ASSERT_NO_FATAL_FAILURE(CGU.removeFunction(*FnH2));
170872277ecdSJohannes Doerfert       }));
170972277ecdSJohannes Doerfert 
171034a8a437SArthur Eubanks   ModulePassManager MPM;
171172277ecdSJohannes Doerfert   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
171272277ecdSJohannes Doerfert   MPM.run(*M, MAM);
171372277ecdSJohannes Doerfert }
171472277ecdSJohannes Doerfert 
17157529fab6SArthur Eubanks // Returns a vector containing the SCC's nodes. Useful for not iterating over an
17167529fab6SArthur Eubanks // SCC while mutating it.
SCCNodes(LazyCallGraph::SCC & C)17177529fab6SArthur Eubanks static SmallVector<LazyCallGraph::Node *> SCCNodes(LazyCallGraph::SCC &C) {
17187529fab6SArthur Eubanks   SmallVector<LazyCallGraph::Node *> Nodes;
17197529fab6SArthur Eubanks   for (auto &N : C)
17207529fab6SArthur Eubanks     Nodes.push_back(&N);
17217529fab6SArthur Eubanks 
17227529fab6SArthur Eubanks   return Nodes;
17237529fab6SArthur Eubanks }
17247529fab6SArthur Eubanks 
17254c8c6368SArthur Eubanks // Start with call recursive f, create f -> g and ref recursive f.
TEST_F(CGSCCPassManagerTest,TestInsertionOfNewFunctions1)17264c8c6368SArthur Eubanks TEST_F(CGSCCPassManagerTest, TestInsertionOfNewFunctions1) {
172726f35635SBrian Gesiak   std::unique_ptr<Module> M = parseIR("define void @f() {\n"
172826f35635SBrian Gesiak                                       "entry:\n"
172926f35635SBrian Gesiak                                       "  call void @f()\n"
173026f35635SBrian Gesiak                                       "  ret void\n"
173126f35635SBrian Gesiak                                       "}\n");
173226f35635SBrian Gesiak 
17334c8c6368SArthur Eubanks   bool Ran = false;
17344c8c6368SArthur Eubanks 
173534a8a437SArthur Eubanks   CGSCCPassManager CGPM;
173626f35635SBrian Gesiak   CGPM.addPass(LambdaSCCPassNoPreserve(
173726f35635SBrian Gesiak       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
173826f35635SBrian Gesiak           CGSCCUpdateResult &UR) {
17394c8c6368SArthur Eubanks         if (Ran)
17404c8c6368SArthur Eubanks           return;
17414c8c6368SArthur Eubanks 
1742bd541b21SAlina Sbirlea         auto &FAM =
1743bd541b21SAlina Sbirlea             AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1744bd541b21SAlina Sbirlea 
17457529fab6SArthur Eubanks         for (LazyCallGraph::Node *N : SCCNodes(C)) {
17464c8c6368SArthur Eubanks           Function &F = N->getFunction();
174726f35635SBrian Gesiak           if (F.getName() != "f")
174826f35635SBrian Gesiak             continue;
174926f35635SBrian Gesiak 
175026f35635SBrian Gesiak           // Create a new function 'g'.
175126f35635SBrian Gesiak           auto *G = Function::Create(F.getFunctionType(), F.getLinkage(),
175226f35635SBrian Gesiak                                      F.getAddressSpace(), "g", F.getParent());
17534c8c6368SArthur Eubanks           auto *GBB =
175426f35635SBrian Gesiak               BasicBlock::Create(F.getParent()->getContext(), "entry", G);
17554c8c6368SArthur Eubanks           (void)ReturnInst::Create(G->getContext(), GBB);
175626f35635SBrian Gesiak           // Instruct the LazyCallGraph to create a new node for 'g', as the
175726f35635SBrian Gesiak           // single node in a new SCC, into the call graph. As a result
175826f35635SBrian Gesiak           // the call graph is composed of a single RefSCC with two SCCs:
175926f35635SBrian Gesiak           // [(f), (g)].
176026f35635SBrian Gesiak 
17614c8c6368SArthur Eubanks           // "Demote" the 'f -> f' call edge to a ref edge.
176226f35635SBrian Gesiak           // 1. Erase the call edge from 'f' to 'f'.
17634c8c6368SArthur Eubanks           F.getEntryBlock().front().eraseFromParent();
176426f35635SBrian Gesiak           // 2. Insert a ref edge from 'f' to 'f'.
17654c8c6368SArthur Eubanks           (void)CastInst::CreatePointerCast(
17664c8c6368SArthur Eubanks               &F, Type::getInt8PtrTy(F.getContext()), "f.ref",
17674c8c6368SArthur Eubanks               &F.getEntryBlock().front());
17687fea561eSArthur Eubanks           // 3. Insert a ref edge from 'f' to 'g'.
17697fea561eSArthur Eubanks           (void)CastInst::CreatePointerCast(
17707fea561eSArthur Eubanks               G, Type::getInt8PtrTy(F.getContext()), "g.ref",
17717fea561eSArthur Eubanks               &F.getEntryBlock().front());
17727fea561eSArthur Eubanks 
17737fea561eSArthur Eubanks           CG.addSplitFunction(F, *G);
17744c8c6368SArthur Eubanks 
17754c8c6368SArthur Eubanks           ASSERT_FALSE(verifyModule(*F.getParent(), &errs()));
177626f35635SBrian Gesiak 
177726f35635SBrian Gesiak           ASSERT_NO_FATAL_FAILURE(
17784c8c6368SArthur Eubanks               updateCGAndAnalysisManagerForCGSCCPass(CG, C, *N, AM, UR, FAM))
177926f35635SBrian Gesiak               << "Updating the call graph with a demoted, self-referential "
178026f35635SBrian Gesiak                  "call edge 'f -> f', and a newly inserted ref edge 'f -> g', "
178126f35635SBrian Gesiak                  "caused a fatal failure";
17824c8c6368SArthur Eubanks 
17834c8c6368SArthur Eubanks           Ran = true;
178426f35635SBrian Gesiak         }
178526f35635SBrian Gesiak       }));
178626f35635SBrian Gesiak 
178734a8a437SArthur Eubanks   ModulePassManager MPM;
178826f35635SBrian Gesiak   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
178926f35635SBrian Gesiak   MPM.run(*M, MAM);
17904c8c6368SArthur Eubanks   ASSERT_TRUE(Ran);
179126f35635SBrian Gesiak }
179226f35635SBrian Gesiak 
17937fea561eSArthur Eubanks // Start with f, end with f -> g1, f -> g2, and f -ref-> (h1 <-ref-> h2).
TEST_F(CGSCCPassManagerTest,TestInsertionOfNewFunctions2)17944c8c6368SArthur Eubanks TEST_F(CGSCCPassManagerTest, TestInsertionOfNewFunctions2) {
179591332c4dSArthur Eubanks   std::unique_ptr<Module> M = parseIR("define void @f() {\n"
179691332c4dSArthur Eubanks                                       "entry:\n"
179791332c4dSArthur Eubanks                                       "  ret void\n"
179891332c4dSArthur Eubanks                                       "}\n");
179991332c4dSArthur Eubanks 
18004c8c6368SArthur Eubanks   bool Ran = false;
18014c8c6368SArthur Eubanks 
180234a8a437SArthur Eubanks   CGSCCPassManager CGPM;
180391332c4dSArthur Eubanks   CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
180491332c4dSArthur Eubanks                                            CGSCCAnalysisManager &AM,
180591332c4dSArthur Eubanks                                            LazyCallGraph &CG,
180691332c4dSArthur Eubanks                                            CGSCCUpdateResult &UR) {
18074c8c6368SArthur Eubanks     if (Ran)
18084c8c6368SArthur Eubanks       return;
18094c8c6368SArthur Eubanks 
181091332c4dSArthur Eubanks     auto &FAM =
181191332c4dSArthur Eubanks         AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
181291332c4dSArthur Eubanks 
18137529fab6SArthur Eubanks     for (LazyCallGraph::Node *N : SCCNodes(C)) {
18144c8c6368SArthur Eubanks       Function &F = N->getFunction();
181591332c4dSArthur Eubanks       if (F.getName() != "f")
181691332c4dSArthur Eubanks         continue;
181791332c4dSArthur Eubanks 
18187fea561eSArthur Eubanks       // Create g1 and g2.
18196b1ce83aSArthur Eubanks       auto *G1 = Function::Create(F.getFunctionType(), F.getLinkage(),
18206b1ce83aSArthur Eubanks                                   F.getAddressSpace(), "g1", F.getParent());
18216b1ce83aSArthur Eubanks       auto *G2 = Function::Create(F.getFunctionType(), F.getLinkage(),
18226b1ce83aSArthur Eubanks                                   F.getAddressSpace(), "g2", F.getParent());
18236b1ce83aSArthur Eubanks       BasicBlock *G1BB =
18246b1ce83aSArthur Eubanks           BasicBlock::Create(F.getParent()->getContext(), "entry", G1);
18256b1ce83aSArthur Eubanks       BasicBlock *G2BB =
18266b1ce83aSArthur Eubanks           BasicBlock::Create(F.getParent()->getContext(), "entry", G2);
18274c8c6368SArthur Eubanks       (void)ReturnInst::Create(G1->getContext(), G1BB);
18286b1ce83aSArthur Eubanks       (void)ReturnInst::Create(G2->getContext(), G2BB);
18296b1ce83aSArthur Eubanks 
18306b1ce83aSArthur Eubanks       // Add 'f -> g1' call edge.
18316b1ce83aSArthur Eubanks       (void)CallInst::Create(G1, {}, "", &F.getEntryBlock().front());
18326b1ce83aSArthur Eubanks       // Add 'f -> g2' call edge.
18336b1ce83aSArthur Eubanks       (void)CallInst::Create(G2, {}, "", &F.getEntryBlock().front());
18346b1ce83aSArthur Eubanks 
18357fea561eSArthur Eubanks       CG.addSplitFunction(F, *G1);
18367fea561eSArthur Eubanks       CG.addSplitFunction(F, *G2);
18377fea561eSArthur Eubanks 
183891332c4dSArthur Eubanks       // Create mutually recursive functions (ref only) 'h1' and 'h2'.
183991332c4dSArthur Eubanks       auto *H1 = Function::Create(F.getFunctionType(), F.getLinkage(),
184091332c4dSArthur Eubanks                                   F.getAddressSpace(), "h1", F.getParent());
184191332c4dSArthur Eubanks       auto *H2 = Function::Create(F.getFunctionType(), F.getLinkage(),
184291332c4dSArthur Eubanks                                   F.getAddressSpace(), "h2", F.getParent());
184391332c4dSArthur Eubanks       BasicBlock *H1BB =
184491332c4dSArthur Eubanks           BasicBlock::Create(F.getParent()->getContext(), "entry", H1);
184591332c4dSArthur Eubanks       BasicBlock *H2BB =
184691332c4dSArthur Eubanks           BasicBlock::Create(F.getParent()->getContext(), "entry", H2);
184791332c4dSArthur Eubanks       (void)CastInst::CreatePointerCast(H2, Type::getInt8PtrTy(F.getContext()),
184891332c4dSArthur Eubanks                                         "h2.ref", H1BB);
184991332c4dSArthur Eubanks       (void)ReturnInst::Create(H1->getContext(), H1BB);
185091332c4dSArthur Eubanks       (void)CastInst::CreatePointerCast(H1, Type::getInt8PtrTy(F.getContext()),
185191332c4dSArthur Eubanks                                         "h1.ref", H2BB);
185291332c4dSArthur Eubanks       (void)ReturnInst::Create(H2->getContext(), H2BB);
185391332c4dSArthur Eubanks 
185491332c4dSArthur Eubanks       // Add 'f -> h1' ref edge.
185591332c4dSArthur Eubanks       (void)CastInst::CreatePointerCast(H1, Type::getInt8PtrTy(F.getContext()),
18566b1ce83aSArthur Eubanks                                         "h1.ref", &F.getEntryBlock().front());
18576b1ce83aSArthur Eubanks       // Add 'f -> h2' ref edge.
18586b1ce83aSArthur Eubanks       (void)CastInst::CreatePointerCast(H2, Type::getInt8PtrTy(F.getContext()),
18596b1ce83aSArthur Eubanks                                         "h2.ref", &F.getEntryBlock().front());
186091332c4dSArthur Eubanks 
18617fea561eSArthur Eubanks       CG.addSplitRefRecursiveFunctions(F, SmallVector<Function *, 2>({H1, H2}));
18627fea561eSArthur Eubanks 
18634c8c6368SArthur Eubanks       ASSERT_FALSE(verifyModule(*F.getParent(), &errs()));
18644c8c6368SArthur Eubanks 
186591332c4dSArthur Eubanks       ASSERT_NO_FATAL_FAILURE(
18664c8c6368SArthur Eubanks           updateCGAndAnalysisManagerForCGSCCPass(CG, C, *N, AM, UR, FAM))
18676b1ce83aSArthur Eubanks           << "Updating the call graph with mutually recursive g1 <-> g2, h1 "
18686b1ce83aSArthur Eubanks              "<-> h2 caused a fatal failure";
18694c8c6368SArthur Eubanks 
18704c8c6368SArthur Eubanks       Ran = true;
187191332c4dSArthur Eubanks     }
187291332c4dSArthur Eubanks   }));
187391332c4dSArthur Eubanks 
187434a8a437SArthur Eubanks   ModulePassManager MPM;
187591332c4dSArthur Eubanks   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
187691332c4dSArthur Eubanks   MPM.run(*M, MAM);
18774c8c6368SArthur Eubanks   ASSERT_TRUE(Ran);
187891332c4dSArthur Eubanks }
187991332c4dSArthur Eubanks 
TEST_F(CGSCCPassManagerTest,TestInsertionOfNewNonTrivialCallEdge)1880d9cbceb0SArthur Eubanks TEST_F(CGSCCPassManagerTest, TestInsertionOfNewNonTrivialCallEdge) {
1881d9cbceb0SArthur Eubanks   std::unique_ptr<Module> M = parseIR("define void @f1() {\n"
1882d9cbceb0SArthur Eubanks                                       "entry:\n"
1883d9cbceb0SArthur Eubanks                                       "  %a = bitcast void ()* @f4 to i8*\n"
1884d9cbceb0SArthur Eubanks                                       "  %b = bitcast void ()* @f2 to i8*\n"
1885d9cbceb0SArthur Eubanks                                       "  ret void\n"
1886d9cbceb0SArthur Eubanks                                       "}\n"
1887d9cbceb0SArthur Eubanks                                       "define void @f2() {\n"
1888d9cbceb0SArthur Eubanks                                       "entry:\n"
1889d9cbceb0SArthur Eubanks                                       "  %a = bitcast void ()* @f1 to i8*\n"
1890d9cbceb0SArthur Eubanks                                       "  %b = bitcast void ()* @f3 to i8*\n"
1891d9cbceb0SArthur Eubanks                                       "  ret void\n"
1892d9cbceb0SArthur Eubanks                                       "}\n"
1893d9cbceb0SArthur Eubanks                                       "define void @f3() {\n"
1894d9cbceb0SArthur Eubanks                                       "entry:\n"
1895d9cbceb0SArthur Eubanks                                       "  %a = bitcast void ()* @f2 to i8*\n"
1896d9cbceb0SArthur Eubanks                                       "  %b = bitcast void ()* @f4 to i8*\n"
1897d9cbceb0SArthur Eubanks                                       "  ret void\n"
1898d9cbceb0SArthur Eubanks                                       "}\n"
1899d9cbceb0SArthur Eubanks                                       "define void @f4() {\n"
1900d9cbceb0SArthur Eubanks                                       "entry:\n"
1901d9cbceb0SArthur Eubanks                                       "  %a = bitcast void ()* @f3 to i8*\n"
1902d9cbceb0SArthur Eubanks                                       "  %b = bitcast void ()* @f1 to i8*\n"
1903d9cbceb0SArthur Eubanks                                       "  ret void\n"
1904d9cbceb0SArthur Eubanks                                       "}\n");
1905d9cbceb0SArthur Eubanks 
1906d9cbceb0SArthur Eubanks   bool Ran = false;
190734a8a437SArthur Eubanks   CGSCCPassManager CGPM;
1908d9cbceb0SArthur Eubanks   CGPM.addPass(LambdaSCCPassNoPreserve([&](LazyCallGraph::SCC &C,
1909d9cbceb0SArthur Eubanks                                            CGSCCAnalysisManager &AM,
1910d9cbceb0SArthur Eubanks                                            LazyCallGraph &CG,
1911d9cbceb0SArthur Eubanks                                            CGSCCUpdateResult &UR) {
1912d9cbceb0SArthur Eubanks     if (Ran)
1913d9cbceb0SArthur Eubanks       return;
1914d9cbceb0SArthur Eubanks 
1915d9cbceb0SArthur Eubanks     auto &FAM =
1916d9cbceb0SArthur Eubanks         AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
1917d9cbceb0SArthur Eubanks 
19187529fab6SArthur Eubanks     for (LazyCallGraph::Node *N : SCCNodes(C)) {
19194c8c6368SArthur Eubanks       Function &F = N->getFunction();
1920d9cbceb0SArthur Eubanks       if (F.getName() != "f1")
1921d9cbceb0SArthur Eubanks         continue;
1922d9cbceb0SArthur Eubanks 
1923d9cbceb0SArthur Eubanks       Function *F3 = F.getParent()->getFunction("f3");
1924d9cbceb0SArthur Eubanks       ASSERT_TRUE(F3 != nullptr);
1925d9cbceb0SArthur Eubanks 
1926d9cbceb0SArthur Eubanks       // Create call from f1 to f3.
1927d9cbceb0SArthur Eubanks       (void)CallInst::Create(F3, {}, "", F.getEntryBlock().getTerminator());
1928d9cbceb0SArthur Eubanks 
1929d9cbceb0SArthur Eubanks       ASSERT_NO_FATAL_FAILURE(
19304c8c6368SArthur Eubanks           updateCGAndAnalysisManagerForCGSCCPass(CG, C, *N, AM, UR, FAM))
1931d9cbceb0SArthur Eubanks           << "Updating the call graph with mutually recursive g1 <-> g2, h1 "
1932d9cbceb0SArthur Eubanks              "<-> h2 caused a fatal failure";
1933d9cbceb0SArthur Eubanks 
1934d9cbceb0SArthur Eubanks       Ran = true;
1935d9cbceb0SArthur Eubanks     }
1936d9cbceb0SArthur Eubanks   }));
1937d9cbceb0SArthur Eubanks 
193834a8a437SArthur Eubanks   ModulePassManager MPM;
1939d9cbceb0SArthur Eubanks   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1940d9cbceb0SArthur Eubanks   MPM.run(*M, MAM);
1941d9cbceb0SArthur Eubanks 
1942d9cbceb0SArthur Eubanks   ASSERT_TRUE(Ran);
1943d9cbceb0SArthur Eubanks }
1944d9cbceb0SArthur Eubanks 
TEST_F(CGSCCPassManagerTest,TestFunctionPassesAreQueriedForInvalidation)194592ccc6cbSMircea Trofin TEST_F(CGSCCPassManagerTest, TestFunctionPassesAreQueriedForInvalidation) {
194692ccc6cbSMircea Trofin   std::unique_ptr<Module> M = parseIR("define void @f() { ret void }");
194792ccc6cbSMircea Trofin   CGSCCPassManager CGPM;
194892ccc6cbSMircea Trofin   bool SCCCalled = false;
194992ccc6cbSMircea Trofin   FunctionPassManager FPM;
195092ccc6cbSMircea Trofin   int ImmRuns = 0;
195192ccc6cbSMircea Trofin   FAM.registerPass([&] { return TestImmutableFunctionAnalysis(ImmRuns); });
195292ccc6cbSMircea Trofin   FPM.addPass(RequireAnalysisPass<TestImmutableFunctionAnalysis, Function>());
195392ccc6cbSMircea Trofin   CGPM.addPass(
195492ccc6cbSMircea Trofin       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
195592ccc6cbSMircea Trofin                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
195692ccc6cbSMircea Trofin         SCCCalled = true;
195792ccc6cbSMircea Trofin         return PreservedAnalyses::none();
195892ccc6cbSMircea Trofin       }));
195992ccc6cbSMircea Trofin   CGPM.addPass(createCGSCCToFunctionPassAdaptor(
196092ccc6cbSMircea Trofin       RequireAnalysisPass<TestImmutableFunctionAnalysis, Function>()));
196192ccc6cbSMircea Trofin   ModulePassManager MPM;
196292ccc6cbSMircea Trofin 
196392ccc6cbSMircea Trofin   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
196492ccc6cbSMircea Trofin   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
196592ccc6cbSMircea Trofin   MPM.run(*M, MAM);
196692ccc6cbSMircea Trofin   ASSERT_EQ(ImmRuns, 1);
196792ccc6cbSMircea Trofin   ASSERT_TRUE(SCCCalled);
196892ccc6cbSMircea Trofin }
196992ccc6cbSMircea Trofin 
197001377453SJohannes Doerfert #endif
197101377453SJohannes Doerfert } // namespace
1972