EXPECT_EQ(4 * 6, AnalyzedModuleFunctionCount1);
}
-// Test that an SCC pass which fails to preserve a module analysis does in fact
-// invalidate that module analysis.
-TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
- FunctionAnalysisManager FAM(/*DebugLogging*/ true);
- CGSCCAnalysisManager CGAM(/*DebugLogging*/ true);
- ModuleAnalysisManager MAM(/*DebugLogging*/ true);
- MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
- MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
- CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(FAM); });
- CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
- FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
- FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
- MAM.registerPass([&] { return LazyCallGraphAnalysis(); });
-
- int ModuleAnalysisRuns = 0;
- MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
-
- ModulePassManager MPM(/*DebugLogging*/ true);
- MPM.addPass(RequireAnalysisPass<TestModuleAnalysis, Module>());
-
- // The first CGSCC run we preserve everything and make sure that works and
- // the module analysis is available in the second CGSCC run from the one
- // required module pass above.
- CGSCCPassManager CGPM1(/*DebugLogging*/ true);
- // Start true and mark false if we ever failed to find a module analysis
- // because we expect this to succeed for each SCC.
- bool FoundModuleAnalysis1 = true;
- CGPM1.addPass(
- LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
- LazyCallGraph &CG, CGSCCUpdateResult &UR) {
- const auto &MAM =
- AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
- auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
- *C.begin()->getFunction().getParent());
-
- if (!TMA)
- FoundModuleAnalysis1 = false;
-
- return PreservedAnalyses::all();
- }));
- MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
-
- // The second CGSCC run checks that the module analysis got preserved the
- // previous time and in one SCC fails to preserve it.
- CGSCCPassManager CGPM2(/*DebugLogging*/ true);
- // Again, start true and mark false if we ever failed to find a module analysis
- // because we expect this to succeed for each SCC.
- bool FoundModuleAnalysis2 = true;
- CGPM2.addPass(
- LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
- LazyCallGraph &CG, CGSCCUpdateResult &UR) {
- const auto &MAM =
- AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
- auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
- *C.begin()->getFunction().getParent());
-
- if (!TMA)
- FoundModuleAnalysis2 = false;
-
- // Only fail to preserve analyses on one SCC and make sure that gets
- // propagated.
- return false/*C.getName() == "h1"*/ ? PreservedAnalyses::none()
- : PreservedAnalyses::all();
- }));
- MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
-
- // The third CGSCC run should fail to find a cached module analysis as it
- // should have been invalidated by the above CGSCC run.
- CGSCCPassManager CGPM3(/*DebugLogging*/ true);
- // Start false and mark true if we ever *succeeded* to find a module
- // analysis, as we expect this to fail for every SCC.
- bool FoundModuleAnalysis3 = false;
- CGPM3.addPass(
- LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
- LazyCallGraph &CG, CGSCCUpdateResult &UR) {
- const auto &MAM =
- AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
- auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
- *C.begin()->getFunction().getParent());
-
- if (TMA)
- FoundModuleAnalysis3 = true;
-
- assert(false && "WHAT THE HELL IS GOING ON!!!");
- return PreservedAnalyses::none();
- }));
- MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
-
- MPM.run(*M, MAM);
-
- EXPECT_EQ(1, ModuleAnalysisRuns);
- EXPECT_TRUE(FoundModuleAnalysis1);
- EXPECT_TRUE(FoundModuleAnalysis2);
- EXPECT_FALSE(FoundModuleAnalysis3);
-}
-
}