mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-27 21:50:40 +00:00
[PM] Provide two templates for the two directionalities of analysis
manager proxies and use those rather than repeating their definition four times. There are real differences between the two directions: outer AMs are const and don't need to have invalidation tracked. But every proxy in a particular direction is identical except for the analysis manager type and the IR unit they proxy into. This makes them prime candidates for nice templates. I've started introducing explicit template instantiation declarations and definitions as well because we really shouldn't be emitting all this everywhere. I'm going to go back and add the same for the other templates like this in a follow-up patch. I've left the analysis manager as an opaque type rather than using two IR units and requiring it to be an AnalysisManager template specialization. I think its important that users retain the ability to provide their own custom analysis management layer and provided it has the appropriate API everything should Just Work. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@262127 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f51a2196a5
commit
500af85bd1
@ -41,146 +41,16 @@ typedef PassManager<LazyCallGraph::SCC> CGSCCPassManager;
|
||||
/// pass manager infrastructure.
|
||||
typedef AnalysisManager<LazyCallGraph::SCC> CGSCCAnalysisManager;
|
||||
|
||||
/// \brief A module analysis which acts as a proxy for a CGSCC analysis
|
||||
/// manager.
|
||||
///
|
||||
/// This primarily proxies invalidation information from the module analysis
|
||||
/// manager and module pass manager to a CGSCC analysis manager. You should
|
||||
/// never use a CGSCC analysis manager from within (transitively) a module
|
||||
/// pass manager unless your parent module pass has received a proxy result
|
||||
/// object for it.
|
||||
///
|
||||
/// Note that the proxy's result is a move-only object and represents ownership
|
||||
/// of the validity of the analyses in the \c CGSCCAnalysisManager it provides.
|
||||
class CGSCCAnalysisManagerModuleProxy
|
||||
: public AnalysisBase<CGSCCAnalysisManagerModuleProxy> {
|
||||
public:
|
||||
class Result {
|
||||
public:
|
||||
explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
|
||||
Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {
|
||||
// We have to null out the analysis manager in the moved-from state
|
||||
// because we are taking ownership of its responsibilty to clear the
|
||||
// analysis state.
|
||||
Arg.CGAM = nullptr;
|
||||
}
|
||||
Result &operator=(Result &&RHS) {
|
||||
CGAM = RHS.CGAM;
|
||||
// We have to null out the analysis manager in the moved-from state
|
||||
// because we are taking ownership of its responsibilty to clear the
|
||||
// analysis state.
|
||||
RHS.CGAM = nullptr;
|
||||
return *this;
|
||||
}
|
||||
~Result();
|
||||
extern template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;
|
||||
/// A proxy from a \c CGSCCAnalysisManager to a \c Module.
|
||||
typedef InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>
|
||||
CGSCCAnalysisManagerModuleProxy;
|
||||
|
||||
/// \brief Accessor for the \c CGSCCAnalysisManager.
|
||||
CGSCCAnalysisManager &getManager() { return *CGAM; }
|
||||
|
||||
/// \brief Handler for invalidation of the module.
|
||||
///
|
||||
/// If this analysis itself is preserved, then we assume that the call
|
||||
/// graph of the module hasn't changed and thus we don't need to invalidate
|
||||
/// *all* cached data associated with a \c SCC* in the \c
|
||||
/// CGSCCAnalysisManager.
|
||||
///
|
||||
/// Regardless of whether this analysis is marked as preserved, all of the
|
||||
/// analyses in the \c CGSCCAnalysisManager are potentially invalidated
|
||||
/// based on the set of preserved analyses.
|
||||
bool invalidate(Module &M, const PreservedAnalyses &PA);
|
||||
|
||||
private:
|
||||
CGSCCAnalysisManager *CGAM;
|
||||
};
|
||||
|
||||
explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM)
|
||||
: CGAM(&CGAM) {}
|
||||
// We have to explicitly define all the special member functions because MSVC
|
||||
// refuses to generate them.
|
||||
CGSCCAnalysisManagerModuleProxy(const CGSCCAnalysisManagerModuleProxy &Arg)
|
||||
: CGAM(Arg.CGAM) {}
|
||||
CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg)
|
||||
: CGAM(std::move(Arg.CGAM)) {}
|
||||
CGSCCAnalysisManagerModuleProxy &
|
||||
operator=(CGSCCAnalysisManagerModuleProxy RHS) {
|
||||
std::swap(CGAM, RHS.CGAM);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Run the analysis pass and create our proxy result object.
|
||||
///
|
||||
/// This doesn't do any interesting work, it is primarily used to insert our
|
||||
/// proxy result object into the module analysis cache so that we can proxy
|
||||
/// invalidation to the CGSCC analysis manager.
|
||||
///
|
||||
/// In debug builds, it will also assert that the analysis manager is empty
|
||||
/// as no queries should arrive at the CGSCC analysis manager prior to
|
||||
/// this analysis being requested.
|
||||
Result run(Module &M);
|
||||
|
||||
private:
|
||||
CGSCCAnalysisManager *CGAM;
|
||||
};
|
||||
|
||||
/// \brief A CGSCC analysis which acts as a proxy for a module analysis
|
||||
/// manager.
|
||||
///
|
||||
/// This primarily provides an accessor to a parent module analysis manager to
|
||||
/// CGSCC passes. Only the const interface of the module analysis manager is
|
||||
/// provided to indicate that once inside of a CGSCC analysis pass you
|
||||
/// cannot request a module analysis to actually run. Instead, the user must
|
||||
/// rely on the \c getCachedResult API.
|
||||
///
|
||||
/// This proxy *doesn't* manage the invalidation in any way. That is handled by
|
||||
/// the recursive return path of each layer of the pass manager and the
|
||||
/// returned PreservedAnalysis set.
|
||||
class ModuleAnalysisManagerCGSCCProxy
|
||||
: public AnalysisBase<ModuleAnalysisManagerCGSCCProxy> {
|
||||
public:
|
||||
/// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy.
|
||||
class Result {
|
||||
public:
|
||||
explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {}
|
||||
// We have to explicitly define all the special member functions because
|
||||
// MSVC refuses to generate them.
|
||||
Result(const Result &Arg) : MAM(Arg.MAM) {}
|
||||
Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {}
|
||||
Result &operator=(Result RHS) {
|
||||
std::swap(MAM, RHS.MAM);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const ModuleAnalysisManager &getManager() const { return *MAM; }
|
||||
|
||||
/// \brief Handle invalidation by ignoring it, this pass is immutable.
|
||||
bool invalidate(LazyCallGraph::SCC &) { return false; }
|
||||
|
||||
private:
|
||||
const ModuleAnalysisManager *MAM;
|
||||
};
|
||||
|
||||
ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM)
|
||||
: MAM(&MAM) {}
|
||||
// We have to explicitly define all the special member functions because MSVC
|
||||
// refuses to generate them.
|
||||
ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManagerCGSCCProxy &Arg)
|
||||
: MAM(Arg.MAM) {}
|
||||
ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg)
|
||||
: MAM(std::move(Arg.MAM)) {}
|
||||
ModuleAnalysisManagerCGSCCProxy &
|
||||
operator=(ModuleAnalysisManagerCGSCCProxy RHS) {
|
||||
std::swap(MAM, RHS.MAM);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Run the analysis pass and create our proxy result object.
|
||||
/// Nothing to see here, it just forwards the \c MAM reference into the
|
||||
/// result.
|
||||
Result run(LazyCallGraph::SCC &) { return Result(*MAM); }
|
||||
|
||||
private:
|
||||
const ModuleAnalysisManager *MAM;
|
||||
};
|
||||
extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
|
||||
LazyCallGraph::SCC>;
|
||||
/// A proxy from a \c ModuleAnalysisManager to an \c SCC.
|
||||
typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, LazyCallGraph::SCC>
|
||||
ModuleAnalysisManagerCGSCCProxy;
|
||||
|
||||
/// \brief The core module pass which does a post-order walk of the SCCs and
|
||||
/// runs a CGSCC pass over each one.
|
||||
@ -266,149 +136,16 @@ createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
|
||||
return ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass));
|
||||
}
|
||||
|
||||
/// \brief A CGSCC analysis which acts as a proxy for a function analysis
|
||||
/// manager.
|
||||
///
|
||||
/// This primarily proxies invalidation information from the CGSCC analysis
|
||||
/// manager and CGSCC pass manager to a function analysis manager. You should
|
||||
/// never use a function analysis manager from within (transitively) a CGSCC
|
||||
/// pass manager unless your parent CGSCC pass has received a proxy result
|
||||
/// object for it.
|
||||
///
|
||||
/// Note that the proxy's result is a move-only object and represents ownership
|
||||
/// of the validity of the analyses in the \c FunctionAnalysisManager it
|
||||
/// provides.
|
||||
class FunctionAnalysisManagerCGSCCProxy
|
||||
: public AnalysisBase<FunctionAnalysisManagerCGSCCProxy> {
|
||||
public:
|
||||
class Result {
|
||||
public:
|
||||
explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
|
||||
Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {
|
||||
// We have to null out the analysis manager in the moved-from state
|
||||
// because we are taking ownership of the responsibilty to clear the
|
||||
// analysis state.
|
||||
Arg.FAM = nullptr;
|
||||
}
|
||||
Result &operator=(Result &&RHS) {
|
||||
FAM = RHS.FAM;
|
||||
// We have to null out the analysis manager in the moved-from state
|
||||
// because we are taking ownership of the responsibilty to clear the
|
||||
// analysis state.
|
||||
RHS.FAM = nullptr;
|
||||
return *this;
|
||||
}
|
||||
~Result();
|
||||
extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager,
|
||||
LazyCallGraph::SCC>;
|
||||
/// A proxy from a \c FunctionAnalysisManager to an \c SCC.
|
||||
typedef InnerAnalysisManagerProxy<FunctionAnalysisManager, LazyCallGraph::SCC>
|
||||
FunctionAnalysisManagerCGSCCProxy;
|
||||
|
||||
/// \brief Accessor for the \c FunctionAnalysisManager.
|
||||
FunctionAnalysisManager &getManager() { return *FAM; }
|
||||
|
||||
/// \brief Handler for invalidation of the SCC.
|
||||
///
|
||||
/// If this analysis itself is preserved, then we assume that the set of \c
|
||||
/// Function objects in the \c SCC 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(LazyCallGraph::SCC &C, const PreservedAnalyses &PA);
|
||||
|
||||
private:
|
||||
FunctionAnalysisManager *FAM;
|
||||
};
|
||||
|
||||
explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM)
|
||||
: FAM(&FAM) {}
|
||||
// We have to explicitly define all the special member functions because MSVC
|
||||
// refuses to generate them.
|
||||
FunctionAnalysisManagerCGSCCProxy(
|
||||
const FunctionAnalysisManagerCGSCCProxy &Arg)
|
||||
: FAM(Arg.FAM) {}
|
||||
FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy &&Arg)
|
||||
: FAM(std::move(Arg.FAM)) {}
|
||||
FunctionAnalysisManagerCGSCCProxy &
|
||||
operator=(FunctionAnalysisManagerCGSCCProxy RHS) {
|
||||
std::swap(FAM, RHS.FAM);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Run the analysis pass and create our proxy result object.
|
||||
///
|
||||
/// This doesn't do any interesting work, it is primarily used to insert our
|
||||
/// proxy result object into the module analysis cache so that we can proxy
|
||||
/// invalidation to the function analysis manager.
|
||||
///
|
||||
/// In debug builds, it will also assert that the analysis manager is empty
|
||||
/// as no queries should arrive at the function analysis manager prior to
|
||||
/// this analysis being requested.
|
||||
Result run(LazyCallGraph::SCC &C);
|
||||
|
||||
private:
|
||||
FunctionAnalysisManager *FAM;
|
||||
};
|
||||
|
||||
/// \brief A function analysis which acts as a proxy for a CGSCC analysis
|
||||
/// manager.
|
||||
///
|
||||
/// This primarily provides an accessor to a parent CGSCC analysis manager to
|
||||
/// function passes. Only the const interface of the CGSCC analysis manager is
|
||||
/// provided to indicate that once inside of a function analysis pass you
|
||||
/// cannot request a CGSCC analysis to actually run. Instead, the user must
|
||||
/// rely on the \c getCachedResult API.
|
||||
///
|
||||
/// This proxy *doesn't* manage the invalidation in any way. That is handled by
|
||||
/// the recursive return path of each layer of the pass manager and the
|
||||
/// returned PreservedAnalysis set.
|
||||
class CGSCCAnalysisManagerFunctionProxy
|
||||
: public AnalysisBase<CGSCCAnalysisManagerFunctionProxy> {
|
||||
public:
|
||||
/// \brief Result proxy object for \c CGSCCAnalysisManagerFunctionProxy.
|
||||
class Result {
|
||||
public:
|
||||
explicit Result(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
|
||||
// We have to explicitly define all the special member functions because
|
||||
// MSVC refuses to generate them.
|
||||
Result(const Result &Arg) : CGAM(Arg.CGAM) {}
|
||||
Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
|
||||
Result &operator=(Result RHS) {
|
||||
std::swap(CGAM, RHS.CGAM);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const CGSCCAnalysisManager &getManager() const { return *CGAM; }
|
||||
|
||||
/// \brief Handle invalidation by ignoring it, this pass is immutable.
|
||||
bool invalidate(Function &) { return false; }
|
||||
|
||||
private:
|
||||
const CGSCCAnalysisManager *CGAM;
|
||||
};
|
||||
|
||||
CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM)
|
||||
: CGAM(&CGAM) {}
|
||||
// We have to explicitly define all the special member functions because MSVC
|
||||
// refuses to generate them.
|
||||
CGSCCAnalysisManagerFunctionProxy(
|
||||
const CGSCCAnalysisManagerFunctionProxy &Arg)
|
||||
: CGAM(Arg.CGAM) {}
|
||||
CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy &&Arg)
|
||||
: CGAM(std::move(Arg.CGAM)) {}
|
||||
CGSCCAnalysisManagerFunctionProxy &
|
||||
operator=(CGSCCAnalysisManagerFunctionProxy RHS) {
|
||||
std::swap(CGAM, RHS.CGAM);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Run the analysis pass and create our proxy result object.
|
||||
/// Nothing to see here, it just forwards the \c CGAM reference into the
|
||||
/// result.
|
||||
Result run(Function &) { return Result(*CGAM); }
|
||||
|
||||
private:
|
||||
const CGSCCAnalysisManager *CGAM;
|
||||
};
|
||||
extern template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;
|
||||
/// A proxy from a \c CGSCCAnalysisManager to a \c Function.
|
||||
typedef OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>
|
||||
CGSCCAnalysisManagerFunctionProxy;
|
||||
|
||||
/// \brief Adaptor that maps from a SCC to its functions.
|
||||
///
|
||||
|
@ -36,136 +36,15 @@ typedef PassManager<Loop> LoopPassManager;
|
||||
/// pass manager infrastructure.
|
||||
typedef AnalysisManager<Loop> LoopAnalysisManager;
|
||||
|
||||
/// \brief A function analysis which acts as a proxy for a loop analysis
|
||||
/// manager.
|
||||
///
|
||||
/// This primarily proxies invalidation information from the function analysis
|
||||
/// manager and function pass manager to a loop analysis manager. You should
|
||||
/// never use a loop analysis manager from within (transitively) a function
|
||||
/// pass manager unless your parent function pass has received a proxy result
|
||||
/// object for it.
|
||||
class LoopAnalysisManagerFunctionProxy
|
||||
: public AnalysisBase<LoopAnalysisManagerFunctionProxy> {
|
||||
public:
|
||||
class Result {
|
||||
public:
|
||||
explicit Result(LoopAnalysisManager &LAM) : LAM(&LAM) {}
|
||||
// We have to explicitly define all the special member functions because
|
||||
// MSVC refuses to generate them.
|
||||
Result(const Result &Arg) : LAM(Arg.LAM) {}
|
||||
Result(Result &&Arg) : LAM(std::move(Arg.LAM)) {}
|
||||
Result &operator=(Result RHS) {
|
||||
std::swap(LAM, RHS.LAM);
|
||||
return *this;
|
||||
}
|
||||
~Result();
|
||||
extern template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>;
|
||||
/// A proxy from a \c LoopAnalysisManager to a \c Function.
|
||||
typedef InnerAnalysisManagerProxy<LoopAnalysisManager, Function>
|
||||
LoopAnalysisManagerFunctionProxy;
|
||||
|
||||
/// \brief Accessor for the \c LoopAnalysisManager.
|
||||
LoopAnalysisManager &getManager() { return *LAM; }
|
||||
|
||||
/// \brief Handler for invalidation of the function.
|
||||
///
|
||||
/// If this analysis itself is preserved, then we assume that the function
|
||||
/// hasn't changed and thus we don't need to invalidate *all* cached data
|
||||
/// associated with a \c Loop* in the \c LoopAnalysisManager.
|
||||
///
|
||||
/// Regardless of whether this analysis is marked as preserved, all of the
|
||||
/// analyses in the \c LoopAnalysisManager are potentially invalidated based
|
||||
/// on the set of preserved analyses.
|
||||
bool invalidate(Function &F, const PreservedAnalyses &PA);
|
||||
|
||||
private:
|
||||
LoopAnalysisManager *LAM;
|
||||
};
|
||||
|
||||
explicit LoopAnalysisManagerFunctionProxy(LoopAnalysisManager &LAM)
|
||||
: LAM(&LAM) {}
|
||||
// We have to explicitly define all the special member functions because MSVC
|
||||
// refuses to generate them.
|
||||
LoopAnalysisManagerFunctionProxy(const LoopAnalysisManagerFunctionProxy &Arg)
|
||||
: LAM(Arg.LAM) {}
|
||||
LoopAnalysisManagerFunctionProxy(LoopAnalysisManagerFunctionProxy &&Arg)
|
||||
: LAM(std::move(Arg.LAM)) {}
|
||||
LoopAnalysisManagerFunctionProxy &
|
||||
operator=(LoopAnalysisManagerFunctionProxy RHS) {
|
||||
std::swap(LAM, RHS.LAM);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Run the analysis pass and create our proxy result object.
|
||||
///
|
||||
/// This doesn't do any interesting work, it is primarily used to insert our
|
||||
/// proxy result object into the function analysis cache so that we can proxy
|
||||
/// invalidation to the loop analysis manager.
|
||||
///
|
||||
/// In debug builds, it will also assert that the analysis manager is empty as
|
||||
/// no queries should arrive at the loop analysis manager prior to this
|
||||
/// analysis being requested.
|
||||
Result run(Function &F);
|
||||
|
||||
private:
|
||||
LoopAnalysisManager *LAM;
|
||||
};
|
||||
|
||||
/// \brief A loop analysis which acts as a proxy for a function analysis
|
||||
/// manager.
|
||||
///
|
||||
/// This primarily provides an accessor to a parent function analysis manager to
|
||||
/// loop passes. Only the const interface of the function analysis manager is
|
||||
/// provided to indicate that once inside of a loop analysis pass you cannot
|
||||
/// request a function analysis to actually run. Instead, the user must rely on
|
||||
/// the \c getCachedResult API.
|
||||
///
|
||||
/// This proxy *doesn't* manage the invalidation in any way. That is handled by
|
||||
/// the recursive return path of each layer of the pass manager and the
|
||||
/// returned PreservedAnalysis set.
|
||||
class FunctionAnalysisManagerLoopProxy
|
||||
: public AnalysisBase<FunctionAnalysisManagerLoopProxy> {
|
||||
public:
|
||||
/// \brief Result proxy object for \c FunctionAnalysisManagerLoopProxy.
|
||||
class Result {
|
||||
public:
|
||||
explicit Result(const FunctionAnalysisManager &FAM) : FAM(&FAM) {}
|
||||
// We have to explicitly define all the special member functions because
|
||||
// MSVC refuses to generate them.
|
||||
Result(const Result &Arg) : FAM(Arg.FAM) {}
|
||||
Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {}
|
||||
Result &operator=(Result RHS) {
|
||||
std::swap(FAM, RHS.FAM);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const FunctionAnalysisManager &getManager() const { return *FAM; }
|
||||
|
||||
/// \brief Handle invalidation by ignoring it, this pass is immutable.
|
||||
bool invalidate(Function &) { return false; }
|
||||
|
||||
private:
|
||||
const FunctionAnalysisManager *FAM;
|
||||
};
|
||||
|
||||
FunctionAnalysisManagerLoopProxy(const FunctionAnalysisManager &FAM)
|
||||
: FAM(&FAM) {}
|
||||
// We have to explicitly define all the special member functions because MSVC
|
||||
// refuses to generate them.
|
||||
FunctionAnalysisManagerLoopProxy(const FunctionAnalysisManagerLoopProxy &Arg)
|
||||
: FAM(Arg.FAM) {}
|
||||
FunctionAnalysisManagerLoopProxy(FunctionAnalysisManagerLoopProxy &&Arg)
|
||||
: FAM(std::move(Arg.FAM)) {}
|
||||
FunctionAnalysisManagerLoopProxy &
|
||||
operator=(FunctionAnalysisManagerLoopProxy RHS) {
|
||||
std::swap(FAM, RHS.FAM);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Run the analysis pass and create our proxy result object.
|
||||
/// Nothing to see here, it just forwards the \c FAM reference into the
|
||||
/// result.
|
||||
Result run(Loop &) { return Result(*FAM); }
|
||||
|
||||
private:
|
||||
const FunctionAnalysisManager *FAM;
|
||||
};
|
||||
extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>;
|
||||
/// A proxy from a \c FunctionAnalysisManager to a \c Loop.
|
||||
typedef OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>
|
||||
FunctionAnalysisManagerLoopProxy;
|
||||
|
||||
/// \brief Adaptor that maps from a function to its loops.
|
||||
///
|
||||
|
@ -651,23 +651,76 @@ typedef AnalysisManager<Function> FunctionAnalysisManager;
|
||||
/// Note that the proxy's result is a move-only object and represents ownership
|
||||
/// of the validity of the analyses in the \c FunctionAnalysisManager it
|
||||
/// provides.
|
||||
class FunctionAnalysisManagerModuleProxy
|
||||
: public AnalysisBase<FunctionAnalysisManagerModuleProxy> {
|
||||
template <typename AnalysisManagerT, typename IRUnitT>
|
||||
class InnerAnalysisManagerProxy
|
||||
: public AnalysisBase<
|
||||
InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> {
|
||||
public:
|
||||
class Result;
|
||||
class Result {
|
||||
public:
|
||||
explicit Result(AnalysisManagerT &AM) : AM(&AM) {}
|
||||
Result(Result &&Arg) : AM(std::move(Arg.AM)) {
|
||||
// We have to null out the analysis manager in the moved-from state
|
||||
// because we are taking ownership of the responsibilty to clear the
|
||||
// analysis state.
|
||||
Arg.AM = nullptr;
|
||||
}
|
||||
Result &operator=(Result &&RHS) {
|
||||
AM = RHS.AM;
|
||||
// We have to null out the analysis manager in the moved-from state
|
||||
// because we are taking ownership of the responsibilty to clear the
|
||||
// analysis state.
|
||||
RHS.AM = nullptr;
|
||||
return *this;
|
||||
}
|
||||
~Result() {
|
||||
// AM is cleared in a moved from state where there is nothing to do.
|
||||
if (!AM)
|
||||
return;
|
||||
|
||||
explicit FunctionAnalysisManagerModuleProxy(FunctionAnalysisManager &FAM)
|
||||
: FAM(&FAM) {}
|
||||
// Clear out the analysis manager if we're being destroyed -- it means we
|
||||
// didn't even see an invalidate call when we got invalidated.
|
||||
AM->clear();
|
||||
}
|
||||
|
||||
/// \brief Accessor for the analysis manager.
|
||||
AnalysisManagerT &getManager() { return *AM; }
|
||||
|
||||
/// \brief Handler for invalidation of the module.
|
||||
///
|
||||
/// 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(IRUnitT &IR, const PreservedAnalyses &PA) {
|
||||
// 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(InnerAnalysisManagerProxy::ID()))
|
||||
AM->clear();
|
||||
|
||||
// Return false to indicate that this result is still a valid proxy.
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
AnalysisManagerT *AM;
|
||||
};
|
||||
|
||||
explicit InnerAnalysisManagerProxy(AnalysisManagerT &AM) : AM(&AM) {}
|
||||
// We have to explicitly define all the special member functions because MSVC
|
||||
// refuses to generate them.
|
||||
FunctionAnalysisManagerModuleProxy(
|
||||
const FunctionAnalysisManagerModuleProxy &Arg)
|
||||
: FAM(Arg.FAM) {}
|
||||
FunctionAnalysisManagerModuleProxy(FunctionAnalysisManagerModuleProxy &&Arg)
|
||||
: FAM(std::move(Arg.FAM)) {}
|
||||
FunctionAnalysisManagerModuleProxy &
|
||||
operator=(FunctionAnalysisManagerModuleProxy RHS) {
|
||||
std::swap(FAM, RHS.FAM);
|
||||
InnerAnalysisManagerProxy(const InnerAnalysisManagerProxy &Arg)
|
||||
: AM(Arg.AM) {}
|
||||
InnerAnalysisManagerProxy(InnerAnalysisManagerProxy &&Arg)
|
||||
: AM(std::move(Arg.AM)) {}
|
||||
InnerAnalysisManagerProxy &operator=(InnerAnalysisManagerProxy RHS) {
|
||||
std::swap(AM, RHS.AM);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -680,53 +733,17 @@ public:
|
||||
/// In debug builds, it will also assert that the analysis manager is empty
|
||||
/// as no queries should arrive at the function analysis manager prior to
|
||||
/// this analysis being requested.
|
||||
Result run(Module &M);
|
||||
Result run(IRUnitT &IR) { return Result(*AM); }
|
||||
|
||||
private:
|
||||
FunctionAnalysisManager *FAM;
|
||||
AnalysisManagerT *AM;
|
||||
};
|
||||
|
||||
/// \brief The result proxy object for the
|
||||
/// \c FunctionAnalysisManagerModuleProxy.
|
||||
///
|
||||
/// See its documentation for more information.
|
||||
class FunctionAnalysisManagerModuleProxy::Result {
|
||||
public:
|
||||
explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
|
||||
Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {
|
||||
// We have to null out the analysis manager in the moved-from state
|
||||
// because we are taking ownership of the responsibilty to clear the
|
||||
// analysis state.
|
||||
Arg.FAM = nullptr;
|
||||
}
|
||||
Result &operator=(Result &&RHS) {
|
||||
FAM = RHS.FAM;
|
||||
// We have to null out the analysis manager in the moved-from state
|
||||
// because we are taking ownership of the responsibilty to clear the
|
||||
// analysis state.
|
||||
RHS.FAM = nullptr;
|
||||
return *this;
|
||||
}
|
||||
~Result();
|
||||
|
||||
/// \brief Accessor for the \c FunctionAnalysisManager.
|
||||
FunctionAnalysisManager &getManager() { return *FAM; }
|
||||
|
||||
/// \brief Handler for invalidation of the module.
|
||||
///
|
||||
/// 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;
|
||||
};
|
||||
extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager,
|
||||
Module>;
|
||||
/// Provide the \c FunctionAnalysisManager to \c Module proxy.
|
||||
typedef InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>
|
||||
FunctionAnalysisManagerModuleProxy;
|
||||
|
||||
/// \brief A function analysis which acts as a proxy for a module analysis
|
||||
/// manager.
|
||||
@ -740,55 +757,60 @@ private:
|
||||
/// This proxy *doesn't* manage the invalidation in any way. That is handled by
|
||||
/// the recursive return path of each layer of the pass manager and the
|
||||
/// returned PreservedAnalysis set.
|
||||
class ModuleAnalysisManagerFunctionProxy
|
||||
: public AnalysisBase<ModuleAnalysisManagerFunctionProxy> {
|
||||
template <typename AnalysisManagerT, typename IRUnitT>
|
||||
class OuterAnalysisManagerProxy
|
||||
: public AnalysisBase<
|
||||
OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> {
|
||||
public:
|
||||
/// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy.
|
||||
/// \brief Result proxy object for \c OuterAnalysisManagerProxy.
|
||||
class Result {
|
||||
public:
|
||||
explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {}
|
||||
explicit Result(const AnalysisManagerT &AM) : AM(&AM) {}
|
||||
// We have to explicitly define all the special member functions because
|
||||
// MSVC refuses to generate them.
|
||||
Result(const Result &Arg) : MAM(Arg.MAM) {}
|
||||
Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {}
|
||||
Result(const Result &Arg) : AM(Arg.AM) {}
|
||||
Result(Result &&Arg) : AM(std::move(Arg.AM)) {}
|
||||
Result &operator=(Result RHS) {
|
||||
std::swap(MAM, RHS.MAM);
|
||||
std::swap(AM, RHS.AM);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const ModuleAnalysisManager &getManager() const { return *MAM; }
|
||||
const AnalysisManagerT &getManager() const { return *AM; }
|
||||
|
||||
/// \brief Handle invalidation by ignoring it, this pass is immutable.
|
||||
bool invalidate(Function &) { return false; }
|
||||
bool invalidate(IRUnitT &) { return false; }
|
||||
|
||||
private:
|
||||
const ModuleAnalysisManager *MAM;
|
||||
const AnalysisManagerT *AM;
|
||||
};
|
||||
|
||||
ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM)
|
||||
: MAM(&MAM) {}
|
||||
OuterAnalysisManagerProxy(const AnalysisManagerT &AM) : AM(&AM) {}
|
||||
// We have to explicitly define all the special member functions because MSVC
|
||||
// refuses to generate them.
|
||||
ModuleAnalysisManagerFunctionProxy(
|
||||
const ModuleAnalysisManagerFunctionProxy &Arg)
|
||||
: MAM(Arg.MAM) {}
|
||||
ModuleAnalysisManagerFunctionProxy(ModuleAnalysisManagerFunctionProxy &&Arg)
|
||||
: MAM(std::move(Arg.MAM)) {}
|
||||
ModuleAnalysisManagerFunctionProxy &
|
||||
operator=(ModuleAnalysisManagerFunctionProxy RHS) {
|
||||
std::swap(MAM, RHS.MAM);
|
||||
OuterAnalysisManagerProxy(const OuterAnalysisManagerProxy &Arg)
|
||||
: AM(Arg.AM) {}
|
||||
OuterAnalysisManagerProxy(OuterAnalysisManagerProxy &&Arg)
|
||||
: AM(std::move(Arg.AM)) {}
|
||||
OuterAnalysisManagerProxy &operator=(OuterAnalysisManagerProxy RHS) {
|
||||
std::swap(AM, RHS.AM);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Run the analysis pass and create our proxy result object.
|
||||
/// Nothing to see here, it just forwards the \c MAM reference into the
|
||||
/// Nothing to see here, it just forwards the \c AM reference into the
|
||||
/// result.
|
||||
Result run(Function &) { return Result(*MAM); }
|
||||
Result run(IRUnitT &) { return Result(*AM); }
|
||||
|
||||
private:
|
||||
const ModuleAnalysisManager *MAM;
|
||||
const AnalysisManagerT *AM;
|
||||
};
|
||||
|
||||
extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
|
||||
Function>;
|
||||
/// Provide the \c ModuleAnalysisManager to \c Fucntion proxy.
|
||||
typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>
|
||||
ModuleAnalysisManagerFunctionProxy;
|
||||
|
||||
/// \brief Trivial adaptor that maps from a module to its functions.
|
||||
///
|
||||
/// Designed to allow composition of a FunctionPass(Manager) and
|
||||
|
@ -13,59 +13,12 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
CGSCCAnalysisManagerModuleProxy::Result
|
||||
CGSCCAnalysisManagerModuleProxy::run(Module &M) {
|
||||
assert(CGAM->empty() && "CGSCC analyses ran prior to the module proxy!");
|
||||
return Result(*CGAM);
|
||||
}
|
||||
|
||||
CGSCCAnalysisManagerModuleProxy::Result::~Result() {
|
||||
// CGAM is cleared in a moved from state where there is nothing to do.
|
||||
if (!CGAM)
|
||||
return;
|
||||
|
||||
// Clear out the analysis manager if we're being destroyed -- it means we
|
||||
// didn't even see an invalidate call when we got invalidated.
|
||||
CGAM->clear();
|
||||
}
|
||||
|
||||
bool CGSCCAnalysisManagerModuleProxy::Result::invalidate(
|
||||
Module &M, const PreservedAnalyses &PA) {
|
||||
// If this proxy isn't marked as preserved, then we can't even invalidate
|
||||
// individual CGSCC analyses, there may be an invalid set of SCC objects in
|
||||
// the cache making it impossible to incrementally preserve them.
|
||||
// Just clear the entire manager.
|
||||
if (!PA.preserved(ID()))
|
||||
CGAM->clear();
|
||||
|
||||
// Return false to indicate that this result is still a valid proxy.
|
||||
return false;
|
||||
}
|
||||
|
||||
FunctionAnalysisManagerCGSCCProxy::Result
|
||||
FunctionAnalysisManagerCGSCCProxy::run(LazyCallGraph::SCC &C) {
|
||||
return Result(*FAM);
|
||||
}
|
||||
|
||||
FunctionAnalysisManagerCGSCCProxy::Result::~Result() {
|
||||
// FAM is cleared in a moved from state where there is nothing to do.
|
||||
if (!FAM)
|
||||
return;
|
||||
|
||||
// Clear out the analysis manager if we're being destroyed -- it means we
|
||||
// didn't even see an invalidate call when we got invalidated.
|
||||
FAM->clear();
|
||||
}
|
||||
|
||||
bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(
|
||||
LazyCallGraph::SCC &C, const PreservedAnalyses &PA) {
|
||||
// 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 to indicate that this result is still a valid proxy.
|
||||
return false;
|
||||
// Explicit instantiations for the core proxy templates.
|
||||
namespace llvm {
|
||||
template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;
|
||||
template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
|
||||
LazyCallGraph::SCC>;
|
||||
template class InnerAnalysisManagerProxy<FunctionAnalysisManager,
|
||||
LazyCallGraph::SCC>;
|
||||
template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;
|
||||
}
|
||||
|
@ -11,31 +11,8 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
LoopAnalysisManagerFunctionProxy::Result
|
||||
LoopAnalysisManagerFunctionProxy::run(Function &F) {
|
||||
// TODO: In FunctionAnalysisManagerModuleProxy we assert that the
|
||||
// AnalysisManager is empty, but if we do that here we run afoul of the fact
|
||||
// that we still have results for previous functions alive. Should we be
|
||||
// clearing those when we finish a function?
|
||||
//assert(LAM->empty() && "Loop analyses ran prior to the function proxy!");
|
||||
return Result(*LAM);
|
||||
}
|
||||
|
||||
LoopAnalysisManagerFunctionProxy::Result::~Result() {
|
||||
// Clear out the analysis manager if we're being destroyed -- it means we
|
||||
// didn't even see an invalidate call when we got invalidated.
|
||||
LAM->clear();
|
||||
}
|
||||
|
||||
bool LoopAnalysisManagerFunctionProxy::Result::invalidate(
|
||||
Function &F, const PreservedAnalyses &PA) {
|
||||
// If this proxy isn't marked as preserved, then we can't even invalidate
|
||||
// individual loop analyses, there may be an invalid set of Loops in the cache
|
||||
// making it impossible to incrementally preserve them. Just clear the entire
|
||||
// manager.
|
||||
if (!PA.preserved(ID()))
|
||||
LAM->clear();
|
||||
|
||||
// Return false to indicate that this result is still a valid proxy.
|
||||
return false;
|
||||
// Explicit instantiations for core typedef'ed templates.
|
||||
namespace llvm {
|
||||
template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>;
|
||||
template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>;
|
||||
}
|
||||
|
@ -13,31 +13,8 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
FunctionAnalysisManagerModuleProxy::Result
|
||||
FunctionAnalysisManagerModuleProxy::run(Module &M) {
|
||||
assert(FAM->empty() && "Function analyses ran prior to the module proxy!");
|
||||
return Result(*FAM);
|
||||
}
|
||||
|
||||
FunctionAnalysisManagerModuleProxy::Result::~Result() {
|
||||
// FAM is cleared in a moved from state where there is nothing to do.
|
||||
if (!FAM)
|
||||
return;
|
||||
|
||||
// Clear out the analysis manager if we're being destroyed -- it means we
|
||||
// didn't even see an invalidate call when we got invalidated.
|
||||
FAM->clear();
|
||||
}
|
||||
|
||||
bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
|
||||
Module &M, const PreservedAnalyses &PA) {
|
||||
// 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 to indicate that this result is still a valid proxy.
|
||||
return false;
|
||||
// Explicit template instantiations for core template typedefs.
|
||||
namespace llvm {
|
||||
template class InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>;
|
||||
template class OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
; RUN: | FileCheck %s --check-prefix=CHECK-CGSCC-PASS
|
||||
; CHECK-CGSCC-PASS: Starting llvm::Module pass manager run
|
||||
; CHECK-CGSCC-PASS-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor
|
||||
; CHECK-CGSCC-PASS-NEXT: Running analysis: CGSCCAnalysisManagerModuleProxy
|
||||
; CHECK-CGSCC-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<CGSCCAnalysisManager, llvm::Module>
|
||||
; CHECK-CGSCC-PASS-NEXT: Running analysis: LazyCallGraphAnalysis
|
||||
; CHECK-CGSCC-PASS-NEXT: Starting llvm::LazyCallGraph::SCC pass manager run
|
||||
; CHECK-CGSCC-PASS-NEXT: Running pass: NoOpCGSCCPass
|
||||
@ -35,7 +35,7 @@
|
||||
; RUN: | FileCheck %s --check-prefix=CHECK-FUNCTION-PASS
|
||||
; CHECK-FUNCTION-PASS: Starting llvm::Module pass manager run
|
||||
; CHECK-FUNCTION-PASS-NEXT: Running pass: ModuleToFunctionPassAdaptor
|
||||
; CHECK-FUNCTION-PASS-NEXT: Running analysis: FunctionAnalysisManagerModuleProxy
|
||||
; CHECK-FUNCTION-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<FunctionAnalysisManager, llvm::Module>
|
||||
; CHECK-FUNCTION-PASS-NEXT: Starting llvm::Function pass manager run
|
||||
; CHECK-FUNCTION-PASS-NEXT: Running pass: NoOpFunctionPass
|
||||
; CHECK-FUNCTION-PASS-NEXT: Finished llvm::Function pass manager run
|
||||
@ -65,7 +65,7 @@
|
||||
; CHECK-FUNCTION-PRINT: Starting llvm::Module pass manager run
|
||||
; CHECK-FUNCTION-PRINT: Running pass: VerifierPass
|
||||
; CHECK-FUNCTION-PRINT: Running pass: ModuleToFunctionPassAdaptor
|
||||
; CHECK-FUNCTION-PRINT: Running analysis: FunctionAnalysisManagerModuleProxy
|
||||
; CHECK-FUNCTION-PRINT: Running analysis: InnerAnalysisManagerProxy<FunctionAnalysisManager, llvm::Module>
|
||||
; CHECK-FUNCTION-PRINT: Starting llvm::Function pass manager run
|
||||
; CHECK-FUNCTION-PRINT: Running pass: PrintFunctionPass
|
||||
; CHECK-FUNCTION-PRINT-NOT: ModuleID
|
||||
|
Loading…
Reference in New Issue
Block a user