[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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195519 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chandler Carruth
2013-11-22 23:38:07 +00:00
parent 2fd69d0fcc
commit 4d32e85359
3 changed files with 41 additions and 16 deletions

View File

@@ -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);
}
}