diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2016-09-26 04:17:12 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2016-09-26 04:17:12 +0000 |
commit | e35f84a2f0b0c3029827eaf1faac8dc12b7163c9 (patch) | |
tree | 623650fa284b68dc389969ec436d681de600b285 /llvm/unittests/Analysis/CGSCCPassManagerTest.cpp | |
parent | b52b573deb40adeb4b85d4cbe918efb82fed3661 (diff) | |
download | bcm5719-llvm-e35f84a2f0b0c3029827eaf1faac8dc12b7163c9.tar.gz bcm5719-llvm-e35f84a2f0b0c3029827eaf1faac8dc12b7163c9.zip |
[PM] Add a unittest covering the invalidation of a Module analysis from
a function pass nested inside of a CGSCC pass manager.
This is very similar to the previous unittest but makes sure the
invalidation logic works across all the layers here.
llvm-svn: 282378
Diffstat (limited to 'llvm/unittests/Analysis/CGSCCPassManagerTest.cpp')
-rw-r--r-- | llvm/unittests/Analysis/CGSCCPassManagerTest.cpp | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp b/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp index 9a378574f9e..8ef3f9ea436 100644 --- a/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp +++ b/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp @@ -385,4 +385,99 @@ TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) { EXPECT_EQ(0, CountFoundModuleAnalysis3); } +// Similar to the above, but test that this works for function passes embedded +// *within* a CGSCC layer. +TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysis) { + 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 run we preserve everything and make sure that works and the + // module analysis is available in the second run from the one required + // module pass above. + FunctionPassManager FPM1(/*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; + FPM1.addPass( + LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) { + const auto &MAM = + AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); + auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); + + if (!TMA) + FoundModuleAnalysis1 = false; + + return PreservedAnalyses::all(); + })); + CGSCCPassManager CGPM1(/*DebugLogging*/ true); + CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); + + // The second run checks that the module analysis got preserved the previous + // time and in one function fails to preserve it. + FunctionPassManager FPM2(/*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; + FPM2.addPass( + LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) { + const auto &MAM = + AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); + auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); + + if (!TMA) + FoundModuleAnalysis2 = false; + + // Only fail to preserve analyses on one SCC and make sure that gets + // propagated. + return F.getName() == "h2" ? PreservedAnalyses::none() + : PreservedAnalyses::all(); + })); + CGSCCPassManager CGPM2(/*DebugLogging*/ true); + CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); + + // The third run should fail to find a cached module analysis as it should + // have been invalidated by the above run. + FunctionPassManager FPM3(/*DebugLogging*/ true); + // Start false and mark true if we ever *succeeded* to find a module + // analysis, as we expect this to fail for every function. + bool FoundModuleAnalysis3 = false; + FPM3.addPass( + LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) { + const auto &MAM = + AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); + auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()); + + if (TMA) + FoundModuleAnalysis3 = true; + + return PreservedAnalyses::none(); + })); + CGSCCPassManager CGPM3(/*DebugLogging*/ true); + CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3))); + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3))); + + MPM.run(*M, MAM); + + EXPECT_EQ(1, ModuleAnalysisRuns); + EXPECT_TRUE(FoundModuleAnalysis1); + EXPECT_TRUE(FoundModuleAnalysis2); + EXPECT_FALSE(FoundModuleAnalysis3); +} + } |