[PM] Edit comments on PM Proxy and utility classes.

Reviewers: chandlerc

Subscribers: mehdi_amini, llvm-commits

Differential Revision: https://reviews.llvm.org/D27502

llvm-svn: 291301
This commit is contained in:
Justin Lebar 2017-01-06 23:32:02 +00:00
parent 7f873070c4
commit 5331bfcda0
1 changed files with 60 additions and 67 deletions

View File

@ -879,18 +879,22 @@ extern template class AnalysisManager<Function>;
/// \brief Convenience typedef for the Function analysis manager. /// \brief Convenience typedef for the Function analysis manager.
typedef AnalysisManager<Function> FunctionAnalysisManager; typedef AnalysisManager<Function> FunctionAnalysisManager;
/// \brief A module analysis which acts as a proxy for a function analysis /// \brief An analysis over an "outer" IR unit that provides access to an
/// manager. /// analysis manager over an "inner" IR unit. The inner unit must be contained
/// in the outer unit.
/// ///
/// This primarily proxies invalidation information from the module analysis /// Fore example, InnerAnalysisManagerProxy<FunctionAnalysisManager, Module> is
/// manager and module pass manager to a function analysis manager. You should /// an analysis over Modules (the "outer" unit) that provides access to a
/// never use a function analysis manager from within (transitively) a module /// Function analysis manager. The FunctionAnalysisManager is the "inner"
/// pass manager unless your parent module pass has received a proxy result /// manager being proxied, and Functions are the "inner" unit. The inner/outer
/// object for it. /// relationship is valid because each Function is contained in one Module.
/// ///
/// Note that the proxy's result is a move-only object and represents ownership /// If you're (transitively) within a pass manager for an IR unit U that
/// of the validity of the analyses in the \c FunctionAnalysisManager it /// contains IR unit V, you should never use an analysis manager over V, except
/// provides. /// via one of these proxies.
///
/// Note that the proxy's result is a move-only RAII object. The validity of
/// the analyses in the inner analysis manager is tied to its lifetime.
template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs> template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
class InnerAnalysisManagerProxy class InnerAnalysisManagerProxy
: public AnalysisInfoMixin< : public AnalysisInfoMixin<
@ -926,23 +930,16 @@ public:
/// \brief Accessor for the analysis manager. /// \brief Accessor for the analysis manager.
AnalysisManagerT &getManager() { return *InnerAM; } AnalysisManagerT &getManager() { return *InnerAM; }
/// \brief Handler for invalidation of the outer IR unit. /// \brief Handler for invalidation of the outer IR unit, \c IRUnitT.
/// ///
/// If this analysis itself is preserved, then we assume that the set of \c /// If the proxy analysis itself is not preserved, we assume that the set of
/// IR units that the inner analysis manager controls hasn't changed and /// inner IR objects contained in IRUnit may have changed. In this case,
/// thus we don't need to invalidate *all* cached data associated with any /// we have to call \c clear() on the inner analysis manager, as it may now
/// \c IRUnitT* in the \c AnalysisManagerT. /// have stale pointers to its inner IR objects.
/// ///
/// Regardless of whether this analysis is marked as preserved, all of the /// Regardless of whether the proxy analysis is marked as preserved, all of
/// analyses in the \c AnalysisManagerT are potentially invalidated (for /// the analyses in the inner analysis manager are potentially invalidated
/// the relevant inner set of their IR units) based on the set of preserved /// based on the set of preserved analyses.
/// analyses.
///
/// Because this needs to understand the mapping from one IR unit to an
/// inner IR unit, this method isn't defined in the primary template.
/// Instead, each specialization of this template will need to provide an
/// explicit specialization of this method to handle that particular pair
/// of IR unit and inner AnalysisManagerT.
bool invalidate( bool invalidate(
IRUnitT &IR, const PreservedAnalyses &PA, IRUnitT &IR, const PreservedAnalyses &PA,
typename AnalysisManager<IRUnitT, ExtraArgTs...>::Invalidator &Inv); typename AnalysisManager<IRUnitT, ExtraArgTs...>::Invalidator &Inv);
@ -956,13 +953,9 @@ public:
/// \brief Run the analysis pass and create our proxy result object. /// \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 /// 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 /// proxy result object into the outer analysis cache so that we can proxy
/// invalidation to the function analysis manager. /// invalidation to the inner 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(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM, Result run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
ExtraArgTs...) { ExtraArgTs...) {
return Result(*InnerAM); return Result(*InnerAM);
@ -996,22 +989,24 @@ bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager, extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager,
Module>; Module>;
/// \brief A function analysis which acts as a proxy for a module analysis /// \brief An analysis over an "inner" IR unit that provides access to an
/// manager. /// analysis manager over a "outer" IR unit. The inner unit must be contained
/// in the outer unit.
/// ///
/// This primarily provides an accessor to a parent module analysis manager to /// For example OuterAnalysisManagerProxy<ModuleAnalysisManager, Function> is an
/// function passes. Only the const interface of the module analysis manager is /// analysis over Functions (the "inner" unit) which provides access to a Module
/// provided to indicate that once inside of a function analysis pass you /// analysis manager. The ModuleAnalysisManager is the "outer" manager being
/// cannot request a module analysis to actually run. Instead, the user must /// proxied, and Modules are the "outer" IR unit. The inner/outer relationship
/// rely on the \c getCachedResult API. /// is valid because each Function is contained in one Module.
/// ///
/// The invalidation provided by this proxy involves tracking when an /// This proxy only exposes the const interface of the outer analysis manager,
/// invalidation event in the outer analysis manager needs to trigger an /// to indicate that you cannot cause an outer analysis to run from within an
/// invalidation of a particular analysis on this IR unit. /// inner pass. Instead, you must rely on the \c getCachedResult API.
/// ///
/// Because outer analyses aren't invalidated while these IR units are being /// This proxy doesn't manage invalidation in any way -- that is handled by the
/// precessed, we have to register and handle these as deferred invalidation /// recursive return path of each layer of the pass manager. A consequence of
/// events. /// this is the outer analyses may be stale. We invalidate the outer analyses
/// only when we're done running passes over the inner IR units.
template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs> template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
class OuterAnalysisManagerProxy class OuterAnalysisManagerProxy
: public AnalysisInfoMixin< : public AnalysisInfoMixin<
@ -1024,7 +1019,7 @@ public:
const AnalysisManagerT &getManager() const { return *AM; } const AnalysisManagerT &getManager() const { return *AM; }
/// \brief Handle invalidation by ignoring it, this pass is immutable. /// \brief Handle invalidation by ignoring it; this pass is immutable.
bool invalidate( bool invalidate(
IRUnitT &, const PreservedAnalyses &, IRUnitT &, const PreservedAnalyses &,
typename AnalysisManager<IRUnitT, ExtraArgTs...>::Invalidator &) { typename AnalysisManager<IRUnitT, ExtraArgTs...>::Invalidator &) {
@ -1089,18 +1084,15 @@ AnalysisKey
extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager, extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
Function>; Function>;
/// Provide the \c ModuleAnalysisManager to \c Fucntion proxy. /// Provide the \c ModuleAnalysisManager to \c Function proxy.
typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, Function> typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>
ModuleAnalysisManagerFunctionProxy; ModuleAnalysisManagerFunctionProxy;
/// \brief Trivial adaptor that maps from a module to its functions. /// \brief Trivial adaptor that maps from a module to its functions.
/// ///
/// Designed to allow composition of a FunctionPass(Manager) and /// Designed to allow composition of a FunctionPass(Manager) and
/// a ModulePassManager. Note that if this pass is constructed with a pointer /// a ModulePassManager, by running the FunctionPass(Manager) over every
/// to a \c ModuleAnalysisManager it will run the /// function in the module.
/// \c FunctionAnalysisManagerModuleProxy analysis prior to running the function
/// pass over the module to enable a \c FunctionAnalysisManager to be used
/// within this run safely.
/// ///
/// Function passes run within this adaptor can rely on having exclusive access /// Function passes run within this adaptor can rely on having exclusive access
/// to the function they are run over. They should not read or modify any other /// to the function they are run over. They should not read or modify any other
@ -1115,6 +1107,10 @@ typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>
/// module. /// module.
/// FIXME: Make the above true for all of LLVM's actual passes, some still /// FIXME: Make the above true for all of LLVM's actual passes, some still
/// violate this principle. /// violate this principle.
///
/// Note that although function passes can access module analyses, module
/// analyses are not invalidated while the function passes are running, so they
/// may be stale. Function analyses will not be stale.
template <typename FunctionPassT> template <typename FunctionPassT>
class ModuleToFunctionPassAdaptor class ModuleToFunctionPassAdaptor
: public PassInfoMixin<ModuleToFunctionPassAdaptor<FunctionPassT>> { : public PassInfoMixin<ModuleToFunctionPassAdaptor<FunctionPassT>> {
@ -1124,7 +1120,6 @@ public:
/// \brief Runs the function pass across every function in the module. /// \brief Runs the function pass across every function in the module.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
// Setup the function analysis manager from its proxy.
FunctionAnalysisManager &FAM = FunctionAnalysisManager &FAM =
AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
@ -1145,10 +1140,11 @@ public:
PA.intersect(std::move(PassPA)); PA.intersect(std::move(PassPA));
} }
// By definition we preserve the proxy. We also preserve all analyses on // The FunctionAnalysisManagerModuleProxy is preserved because (we assume)
// Function units. This precludes *any* invalidation of function analyses // the function passes we ran didn't add or remove any functions.
// by the proxy, but that's OK because we've taken care to invalidate //
// analyses in the function analysis manager incrementally above. // We also preserve all analyses on Functions, because we did all the
// invalidation we needed to do above.
PA.preserveSet<AllAnalysesOn<Function>>(); PA.preserveSet<AllAnalysesOn<Function>>();
PA.preserve<FunctionAnalysisManagerModuleProxy>(); PA.preserve<FunctionAnalysisManagerModuleProxy>();
return PA; return PA;
@ -1166,7 +1162,7 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) {
return ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)); return ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass));
} }
/// \brief A template utility pass to force an analysis result to be available. /// \brief A utility pass template to force an analysis result to be available.
/// ///
/// If there are extra arguments at the pass's run level there may also be /// If there are extra arguments at the pass's run level there may also be
/// extra arguments to the analysis manager's \c getResult routine. We can't /// extra arguments to the analysis manager's \c getResult routine. We can't
@ -1196,17 +1192,14 @@ struct RequireAnalysisPass
} }
}; };
/// \brief A template utility pass to force an analysis result to be /// \brief A no-op pass template which simply forces a specific analysis result
/// invalidated. /// to be invalidated.
///
/// This is a no-op pass which simply forces a specific analysis result to be
/// invalidated when it is run.
template <typename AnalysisT> template <typename AnalysisT>
struct InvalidateAnalysisPass struct InvalidateAnalysisPass
: PassInfoMixin<InvalidateAnalysisPass<AnalysisT>> { : PassInfoMixin<InvalidateAnalysisPass<AnalysisT>> {
/// \brief Run this pass over some unit of IR. /// \brief Run this pass over some unit of IR.
/// ///
/// This pass can be run over any unit of IR and use any analysis manager /// This pass can be run over any unit of IR and use any analysis manager,
/// provided they satisfy the basic API requirements. When this pass is /// provided they satisfy the basic API requirements. When this pass is
/// created, these methods can be instantiated to satisfy whatever the /// created, these methods can be instantiated to satisfy whatever the
/// context requires. /// context requires.
@ -1218,10 +1211,10 @@ struct InvalidateAnalysisPass
} }
}; };
/// \brief A utility pass that does nothing but preserves no analyses. /// \brief A utility pass that does nothing, but preserves no analyses.
/// ///
/// As a consequence fo not preserving any analyses, this pass will force all /// Because this preserves no analyses, any analysis passes queried after this
/// analysis passes to be re-run to produce fresh results if any are needed. /// pass runs will recompute fresh results.
struct InvalidateAllAnalysesPass : PassInfoMixin<InvalidateAllAnalysesPass> { struct InvalidateAllAnalysesPass : PassInfoMixin<InvalidateAllAnalysesPass> {
/// \brief Run this pass over some unit of IR. /// \brief Run this pass over some unit of IR.
template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs> template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>