OSDN Git Service

[PM] Add a unittest covering the invalidation of a Module analysis from
authorChandler Carruth <chandlerc@gmail.com>
Mon, 26 Sep 2016 04:17:12 +0000 (04:17 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Mon, 26 Sep 2016 04:17:12 +0000 (04:17 +0000)
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

unittests/Analysis/CGSCCPassManagerTest.cpp

index 9a37857..8ef3f9e 100644 (file)
@@ -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);
+}
+
 }