/// \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.
/// 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;
};
///
/// 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;
};
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(...);
// 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;
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;
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;
~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;
PreservedAnalyses PassPA = Pass.run(I);
PA.intersect(llvm_move(PassPA));
}
+
+ // By definition we preserve the proxy.
+ PA.preserve<FunctionAnalysisModuleProxy>();
return PA;
}