From: Chandler Carruth Date: Mon, 26 Sep 2016 04:17:12 +0000 (+0000) Subject: [PM] Add a unittest covering the invalidation of a Module analysis from X-Git-Tag: android-x86-7.1-r4~26718 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=d6345b8af03b2460aef0957a39b9d4453c5cae37;p=android-x86%2Fexternal-llvm.git [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282378 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/unittests/Analysis/CGSCCPassManagerTest.cpp b/unittests/Analysis/CGSCCPassManagerTest.cpp index 9a378574f9e..8ef3f9ea436 100644 --- a/unittests/Analysis/CGSCCPassManagerTest.cpp +++ b/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()); + + // 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(F).getManager(); + auto *TMA = MAM.getCachedResult(*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(F).getManager(); + auto *TMA = MAM.getCachedResult(*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(F).getManager(); + auto *TMA = MAM.getCachedResult(*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); +} + }