[llvm] r195519 - [PM] Switch the downward invalidation to be incremental where only the

Chandler Carruth chandlerc at gmail.com
Fri Nov 22 15:38:07 PST 2013


Author: chandlerc
Date: Fri Nov 22 17:38:07 2013
New Revision: 195519

URL: http://llvm.org/viewvc/llvm-project?rev=195519&view=rev
Log:
[PM] Switch the downward invalidation to be incremental where only the
one function's analyses are invalidated at a time. Also switch the
preservation of the proxy to *fully* preserve the lower (function)
analyses.

Combined, this gets both upward and downward analysis invalidation to
a point I'm happy with:

- A function pass invalidates its function analyses, and its parent's
  module analyses.
- A module pass invalidates all of its functions' analyses including the
  set of which functions are in the module.
- A function pass can preserve a module analysis pass.
- If all function passes preserve a module analysis pass, that
  preservation persists. If any doesn't the module analysis is
  invalidated.
- A module pass can opt into managing *all* function analysis
  invalidation itself or *none*.
- The conservative default is none, and the proxy takes the maximally
  conservative approach that works even if the set of functions has
  changed.
- If a module pass opts into managing function analysis invalidation it
  has to propagate the invalidation itself, the proxy just does nothing.

The only thing really missing is a way to query for a cached analysis or
nothing at all. With this, function passes can more safely request
a cached module analysis pass without fear of it accidentally running
part way through.

Modified:
    llvm/trunk/include/llvm/IR/PassManager.h
    llvm/trunk/lib/IR/PassManager.cpp
    llvm/trunk/unittests/IR/PassManagerTest.cpp

Modified: llvm/trunk/include/llvm/IR/PassManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassManager.h?rev=195519&r1=195518&r2=195519&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/PassManager.h (original)
+++ llvm/trunk/include/llvm/IR/PassManager.h Fri Nov 22 17:38:07 2013
@@ -709,10 +709,22 @@ public:
     PreservedAnalyses PA = PreservedAnalyses::all();
     for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
       PreservedAnalyses PassPA = Pass.run(I, FAM);
+
+      // We know that the function pass couldn't have invalidated any other
+      // function's analyses (that's the contract of a function pass), so
+      // directly handle the function analysis manager's invalidation here.
+      if (FAM)
+        FAM->invalidate(I, PassPA);
+
+      // Then intersect the preserved set so that invalidation of module
+      // analyses will eventually occur when the module pass completes.
       PA.intersect(llvm_move(PassPA));
     }
 
-    // By definition we preserve the proxy.
+    // By definition we preserve the proxy. This precludes *any* invalidation
+    // of function analyses by the proxy, but that's OK because we've taken
+    // care to invalidate analyses in the function analysis manager
+    // incrementally above.
     PA.preserve<FunctionAnalysisManagerModuleProxy>();
     return PA;
   }

Modified: llvm/trunk/lib/IR/PassManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/PassManager.cpp?rev=195519&r1=195518&r2=195519&view=diff
==============================================================================
--- llvm/trunk/lib/IR/PassManager.cpp (original)
+++ llvm/trunk/lib/IR/PassManager.cpp Fri Nov 22 17:38:07 2013
@@ -147,18 +147,12 @@ FunctionAnalysisManagerModuleProxy::Resu
 
 bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
     Module *M, const PreservedAnalyses &PA) {
-  // If this proxy isn't marked as preserved, then it is has an invalid set of
-  // Function objects in the cache making it impossible to incrementally
-  // preserve them. Just clear the entire manager.
-  if (!PA.preserved(ID())) {
+  // If this proxy isn't marked as preserved, then we can't even invalidate
+  // individual function analyses, there may be an invalid set of Function
+  // objects in the cache making it impossible to incrementally preserve them.
+  // Just clear the entire manager.
+  if (!PA.preserved(ID()))
     FAM.clear();
-    return false;
-  }
-
-  // The set of functions was preserved some how, so just directly invalidate
-  // any analysis results not preserved.
-  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
-    FAM.invalidate(I, PA);
 
   // Return false to indicate that this result is still a valid proxy.
   return false;

Modified: llvm/trunk/unittests/IR/PassManagerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/PassManagerTest.cpp?rev=195519&r1=195518&r2=195519&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/PassManagerTest.cpp (original)
+++ llvm/trunk/unittests/IR/PassManagerTest.cpp Fri Nov 22 17:38:07 2013
@@ -93,6 +93,19 @@ struct TestFunctionPass {
   int &AnalyzedInstrCount;
 };
 
+// A test function pass that invalidates all function analyses for a function
+// with a specific name.
+struct TestInvalidationFunctionPass {
+  TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
+
+  PreservedAnalyses run(Function *F) {
+    return F->getName() == Name ? PreservedAnalyses::none()
+                                : PreservedAnalyses::all();
+  }
+
+  StringRef Name;
+};
+
 Module *parseIR(const char *IR) {
   LLVMContext &C = getGlobalContext();
   SMDiagnostic Err;
@@ -147,12 +160,14 @@ TEST_F(PassManagerTest, Basic) {
   FPM2.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2));
   MPM.addPass(createModuleToFunctionPassAdaptor(FPM2));
 
-  // A third function pass manager but with only preserving intervening passes.
+  // A third function pass manager but with only preserving intervening passes
+  // and with a function pass that invalidates exactly one analysis.
   MPM.addPass(TestPreservingModulePass());
   FunctionPassManager FPM3;
   int FunctionPassRunCount3 = 0;
   int AnalyzedInstrCount3 = 0;
   FPM3.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3));
+  FPM3.addPass(TestInvalidationFunctionPass("f"));
   MPM.addPass(createModuleToFunctionPassAdaptor(FPM3));
 
   // A fourth function pass manager but with a minimal intervening passes.
@@ -168,7 +183,7 @@ TEST_F(PassManagerTest, Basic) {
   // Validate module pass counters.
   EXPECT_EQ(1, ModulePassRunCount);
 
-  // Validate both function pass counter sets.
+  // Validate all function pass counter sets are the same.
   EXPECT_EQ(3, FunctionPassRunCount1);
   EXPECT_EQ(5, AnalyzedInstrCount1);
   EXPECT_EQ(3, FunctionPassRunCount2);
@@ -178,7 +193,11 @@ TEST_F(PassManagerTest, Basic) {
   EXPECT_EQ(3, FunctionPassRunCount4);
   EXPECT_EQ(5, AnalyzedInstrCount4);
 
-  // Validate the analysis counters.
-  EXPECT_EQ(9, AnalysisRuns);
+  // Validate the analysis counters:
+  //   first run over 3 functions, then module pass invalidates
+  //   second run over 3 functions, nothing invalidates
+  //   third run over 0 functions, but 1 function invalidated
+  //   fourth run over 1 function
+  EXPECT_EQ(7, AnalysisRuns);
 }
 }





More information about the llvm-commits mailing list