mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-29 10:32:47 +00:00
[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:
parent
2fd69d0fcc
commit
4d32e85359
@ -709,10 +709,22 @@ public:
|
|||||||
PreservedAnalyses PA = PreservedAnalyses::all();
|
PreservedAnalyses PA = PreservedAnalyses::all();
|
||||||
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
|
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
|
||||||
PreservedAnalyses PassPA = Pass.run(I, FAM);
|
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));
|
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>();
|
PA.preserve<FunctionAnalysisManagerModuleProxy>();
|
||||||
return PA;
|
return PA;
|
||||||
}
|
}
|
||||||
|
@ -147,18 +147,12 @@ FunctionAnalysisManagerModuleProxy::Result::~Result() {
|
|||||||
|
|
||||||
bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
|
bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
|
||||||
Module *M, const PreservedAnalyses &PA) {
|
Module *M, const PreservedAnalyses &PA) {
|
||||||
// If this proxy isn't marked as preserved, then it is has an invalid set of
|
// If this proxy isn't marked as preserved, then we can't even invalidate
|
||||||
// Function objects in the cache making it impossible to incrementally
|
// individual function analyses, there may be an invalid set of Function
|
||||||
// preserve them. Just clear the entire manager.
|
// objects in the cache making it impossible to incrementally preserve them.
|
||||||
if (!PA.preserved(ID())) {
|
// Just clear the entire manager.
|
||||||
|
if (!PA.preserved(ID()))
|
||||||
FAM.clear();
|
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 to indicate that this result is still a valid proxy.
|
||||||
return false;
|
return false;
|
||||||
|
@ -93,6 +93,19 @@ struct TestFunctionPass {
|
|||||||
int &AnalyzedInstrCount;
|
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) {
|
Module *parseIR(const char *IR) {
|
||||||
LLVMContext &C = getGlobalContext();
|
LLVMContext &C = getGlobalContext();
|
||||||
SMDiagnostic Err;
|
SMDiagnostic Err;
|
||||||
@ -147,12 +160,14 @@ TEST_F(PassManagerTest, Basic) {
|
|||||||
FPM2.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2));
|
FPM2.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2));
|
||||||
MPM.addPass(createModuleToFunctionPassAdaptor(FPM2));
|
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());
|
MPM.addPass(TestPreservingModulePass());
|
||||||
FunctionPassManager FPM3;
|
FunctionPassManager FPM3;
|
||||||
int FunctionPassRunCount3 = 0;
|
int FunctionPassRunCount3 = 0;
|
||||||
int AnalyzedInstrCount3 = 0;
|
int AnalyzedInstrCount3 = 0;
|
||||||
FPM3.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3));
|
FPM3.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3));
|
||||||
|
FPM3.addPass(TestInvalidationFunctionPass("f"));
|
||||||
MPM.addPass(createModuleToFunctionPassAdaptor(FPM3));
|
MPM.addPass(createModuleToFunctionPassAdaptor(FPM3));
|
||||||
|
|
||||||
// A fourth function pass manager but with a minimal intervening passes.
|
// A fourth function pass manager but with a minimal intervening passes.
|
||||||
@ -168,7 +183,7 @@ TEST_F(PassManagerTest, Basic) {
|
|||||||
// Validate module pass counters.
|
// Validate module pass counters.
|
||||||
EXPECT_EQ(1, ModulePassRunCount);
|
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(3, FunctionPassRunCount1);
|
||||||
EXPECT_EQ(5, AnalyzedInstrCount1);
|
EXPECT_EQ(5, AnalyzedInstrCount1);
|
||||||
EXPECT_EQ(3, FunctionPassRunCount2);
|
EXPECT_EQ(3, FunctionPassRunCount2);
|
||||||
@ -178,7 +193,11 @@ TEST_F(PassManagerTest, Basic) {
|
|||||||
EXPECT_EQ(3, FunctionPassRunCount4);
|
EXPECT_EQ(3, FunctionPassRunCount4);
|
||||||
EXPECT_EQ(5, AnalyzedInstrCount4);
|
EXPECT_EQ(5, AnalyzedInstrCount4);
|
||||||
|
|
||||||
// Validate the analysis counters.
|
// Validate the analysis counters:
|
||||||
EXPECT_EQ(9, AnalysisRuns);
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user