[llvm] r282378 - [PM] Add a unittest covering the invalidation of a Module analysis from

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 25 21:17:12 PDT 2016


Author: chandlerc
Date: Sun Sep 25 23:17:12 2016
New Revision: 282378

URL: http://llvm.org/viewvc/llvm-project?rev=282378&view=rev
Log:
[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.

Modified:
    llvm/trunk/unittests/Analysis/CGSCCPassManagerTest.cpp

Modified: llvm/trunk/unittests/Analysis/CGSCCPassManagerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Analysis/CGSCCPassManagerTest.cpp?rev=282378&r1=282377&r2=282378&view=diff
==============================================================================
--- llvm/trunk/unittests/Analysis/CGSCCPassManagerTest.cpp (original)
+++ llvm/trunk/unittests/Analysis/CGSCCPassManagerTest.cpp Sun Sep 25 23:17:12 2016
@@ -385,4 +385,99 @@ TEST_F(CGSCCPassManagerTest, TestSCCPass
   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);
+}
+
 }




More information about the llvm-commits mailing list