summaryrefslogtreecommitdiff
path: root/include/llvm/IR/PassManager.h
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2013-11-21 10:53:05 +0000
committerChandler Carruth <chandlerc@gmail.com>2013-11-21 10:53:05 +0000
commitedd2b4913433d92fa6b6b89c31a2837d1bba32a5 (patch)
tree14f4cc19077778e00a39e4005ad899cdc90b373c /include/llvm/IR/PassManager.h
parent0bafaacfc96daefa43ac94fc186af71773c877a6 (diff)
downloadllvm-edd2b4913433d92fa6b6b89c31a2837d1bba32a5.tar.gz
llvm-edd2b4913433d92fa6b6b89c31a2837d1bba32a5.tar.bz2
llvm-edd2b4913433d92fa6b6b89c31a2837d1bba32a5.tar.xz
[PM] Widen the interface for invalidate on an analysis result now that
it is completely optional, and sink the logic for handling the preserved analysis set into it. This allows us to implement the delegation logic desired in the proxy module analysis for the function analysis manager where if the proxy itself is preserved we assume the set of functions hasn't changed and we do a fine grained invalidation by walking the functions in the module and running the invalidate for them all at the manager level and letting it try to invalidate any passes. This in turn makes it blindingly obvious why we should hoist the invalidate trait and have two collections of results. That allows handling invalidation for almost all analyses without indirect calls and it allows short circuiting when the preserved set is all. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195338 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/IR/PassManager.h')
-rw-r--r--include/llvm/IR/PassManager.h53
1 files changed, 39 insertions, 14 deletions
diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h
index a37fc8f2f9..c930f7b925 100644
--- a/include/llvm/IR/PassManager.h
+++ b/include/llvm/IR/PassManager.h
@@ -185,11 +185,15 @@ template <typename IRUnitT> struct AnalysisResultConcept {
/// \brief Method to try and mark a result as invalid.
///
- /// When the outer \c AnalysisManager detects a change in some underlying
+ /// When the outer analysis manager detects a change in some underlying
/// unit of the IR, it will call this method on all of the results cached.
///
- /// \returns true if the result should indeed be invalidated (the default).
- virtual bool invalidate(IRUnitT *IR) = 0;
+ /// This method also receives a set of preserved analyses which can be used
+ /// to avoid invalidation because the pass which changed the underlying IR
+ /// took care to update or preserve the analysis result in some way.
+ ///
+ /// \returns true if the result is indeed invalid (the default).
+ virtual bool invalidate(IRUnitT *IR, const PreservedAnalyses &PA) = 0;
};
/// \brief Wrapper to model the analysis result concept.
@@ -198,19 +202,22 @@ template <typename IRUnitT> struct AnalysisResultConcept {
/// implementation so that the actual analysis result doesn't need to provide
/// an invalidation handler. It is only selected when the invalidation handler
/// is not part of the ResultT's interface.
-template <typename IRUnitT, typename ResultT, bool HasInvalidateHandler = false>
+template <typename IRUnitT, typename PassT, typename ResultT,
+ bool HasInvalidateHandler = false>
struct AnalysisResultModel : AnalysisResultConcept<IRUnitT> {
AnalysisResultModel(ResultT Result) : Result(llvm_move(Result)) {}
virtual AnalysisResultModel *clone() {
return new AnalysisResultModel(Result);
}
- /// \brief The model returns true to allow the invalidation.
+ /// \brief The model bases invalidation soley on being in the preserved set.
//
// FIXME: We should actually use two different concepts for analysis results
// rather than two different models, and avoid the indirect function call for
// ones that use the trivial behavior.
- virtual bool invalidate(IRUnitT *) { return true; }
+ virtual bool invalidate(IRUnitT *, const PreservedAnalyses &PA) {
+ return !PA.preserved(PassT::ID());
+ }
ResultT Result;
};
@@ -219,15 +226,18 @@ struct AnalysisResultModel : AnalysisResultConcept<IRUnitT> {
///
/// Can wrap any type which implements a suitable invalidate member and model
/// the AnalysisResultConcept for the AnalysisManager.
-template <typename IRUnitT, typename ResultT>
-struct AnalysisResultModel<IRUnitT, ResultT, true> : AnalysisResultConcept<IRUnitT> {
+template <typename IRUnitT, typename PassT, typename ResultT>
+struct AnalysisResultModel<IRUnitT, PassT, ResultT,
+ true> : AnalysisResultConcept<IRUnitT> {
AnalysisResultModel(ResultT Result) : Result(llvm_move(Result)) {}
virtual AnalysisResultModel *clone() {
return new AnalysisResultModel(Result);
}
/// \brief The model delegates to the \c ResultT method.
- virtual bool invalidate(IRUnitT *IR) { return Result.invalidate(IR); }
+ virtual bool invalidate(IRUnitT *IR, const PreservedAnalyses &PA) {
+ return Result.invalidate(IR, PA);
+ }
ResultT Result;
};
@@ -237,7 +247,10 @@ struct AnalysisResultModel<IRUnitT, ResultT, true> : AnalysisResultConcept<IRUni
template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
typedef char SmallType;
struct BigType { char a, b; };
- template <typename T, bool (T::*)(IRUnitT *)> struct Checker;
+
+ template <typename T, bool (T::*)(IRUnitT *, const PreservedAnalyses &)>
+ struct Checker;
+
template <typename T> static SmallType f(Checker<T, &T::invalidate> *);
template <typename T> static BigType f(...);
@@ -274,7 +287,7 @@ struct AnalysisPassModel : AnalysisPassConcept<typename PassT::IRUnitT> {
// FIXME: Replace PassT::Result with type traits when we use C++11.
typedef AnalysisResultModel<
- IRUnitT, typename PassT::Result,
+ IRUnitT, PassT, typename PassT::Result,
ResultHasInvalidateMethod<IRUnitT, typename PassT::Result>::Value>
ResultModelT;
@@ -363,7 +376,7 @@ public:
const detail::AnalysisResultConcept<Module> &ResultConcept =
getResultImpl(PassT::ID(), M);
typedef detail::AnalysisResultModel<
- Module, typename PassT::Result,
+ Module, PassT, typename PassT::Result,
detail::ResultHasInvalidateMethod<
Module, typename PassT::Result>::Value> ResultModelT;
return static_cast<const ResultModelT &>(ResultConcept).Result;
@@ -447,7 +460,7 @@ public:
const detail::AnalysisResultConcept<Function> &ResultConcept =
getResultImpl(PassT::ID(), F);
typedef detail::AnalysisResultModel<
- Function, typename PassT::Result,
+ Function, PassT, typename PassT::Result,
detail::ResultHasInvalidateMethod<
Function, typename PassT::Result>::Value> ResultModelT;
return static_cast<const ResultModelT &>(ResultConcept).Result;
@@ -591,7 +604,16 @@ public:
~Result();
/// \brief Handler for invalidation of the module.
- bool invalidate(Module *M);
+ ///
+ /// If this analysis itself is preserved, then we assume that the set of \c
+ /// Function objects in the \c Module hasn't changed and thus we don't need
+ /// to invalidate *all* cached data associated with a \c Function* in the \c
+ /// FunctionAnalysisManager.
+ ///
+ /// Regardless of whether this analysis is marked as preserved, all of the
+ /// analyses in the \c FunctionAnalysisManager are potentially invalidated
+ /// based on the set of preserved analyses.
+ bool invalidate(Module *M, const PreservedAnalyses &PA);
private:
FunctionAnalysisManager &FAM;
@@ -623,6 +645,9 @@ public:
PreservedAnalyses PassPA = Pass.run(I);
PA.intersect(llvm_move(PassPA));
}
+
+ // By definition we preserve the proxy.
+ PA.preserve<FunctionAnalysisModuleProxy>();
return PA;
}