Index: include/llvm/Analysis/AliasAnalysis.h =================================================================== --- include/llvm/Analysis/AliasAnalysis.h +++ include/llvm/Analysis/AliasAnalysis.h @@ -889,23 +889,20 @@ friend AnalysisInfoMixin; static char PassID; - SmallVector ResultGetters; + SmallVector + ResultGetters; template - static void getFunctionAAResultImpl(Function &F, - FunctionAnalysisManager &AM, + static void getFunctionAAResultImpl(Function &F, AnalysisManager &AM, AAResults &AAResults) { AAResults.addAAResult(AM.template getResult(F)); } template - static void getModuleAAResultImpl(Function &F, FunctionAnalysisManager &AM, + static void getModuleAAResultImpl(Function &F, AnalysisManager &AM, AAResults &AAResults) { - auto &MAM = - AM.getResult(F).getManager(); - if (auto *R = MAM.template getCachedResult(*F.getParent())) + if (auto *R = AM.template getCachedResult(*F.getParent())) AAResults.addAAResult(*R); } }; Index: include/llvm/Analysis/CGSCCPassManager.h =================================================================== --- include/llvm/Analysis/CGSCCPassManager.h +++ include/llvm/Analysis/CGSCCPassManager.h @@ -34,35 +34,11 @@ /// typedef serves as a convenient way to refer to this construct. typedef PassManager CGSCCPassManager; -extern template class AnalysisManager; -/// \brief The CGSCC analysis manager. -/// -/// See the documentation for the AnalysisManager template for detail -/// documentation. This typedef serves as a convenient way to refer to this -/// construct in the adaptors and proxies used to integrate this into the larger -/// pass manager infrastructure. -typedef AnalysisManager CGSCCAnalysisManager; - -extern template class InnerAnalysisManagerProxy; -/// A proxy from a \c CGSCCAnalysisManager to a \c Module. -typedef InnerAnalysisManagerProxy - CGSCCAnalysisManagerModuleProxy; - -extern template class OuterAnalysisManagerProxy; -/// A proxy from a \c ModuleAnalysisManager to an \c SCC. -typedef OuterAnalysisManagerProxy - ModuleAnalysisManagerCGSCCProxy; - /// \brief The core module pass which does a post-order walk of the SCCs and /// runs a CGSCC pass over each one. /// /// Designed to allow composition of a CGSCCPass(Manager) and -/// a ModulePassManager. Note that this pass must be run with a module analysis -/// manager as it uses the LazyCallGraph analysis. It will also run the -/// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC -/// pass over the module to enable a \c FunctionAnalysisManager to be used -/// within this run safely. +/// a ModulePassManager. template class ModuleToPostOrderCGSCCPassAdaptor : public PassInfoMixin> { @@ -89,11 +65,7 @@ } /// \brief Runs the CGSCC pass across every SCC in the module. - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { - // Setup the CGSCC analysis manager from its proxy. - CGSCCAnalysisManager &CGAM = - AM.getResult(M).getManager(); - + PreservedAnalyses run(Module &M, AnalysisManager &AM) { // Get the call graph for this module. LazyCallGraph &CG = AM.getResult(M); @@ -103,7 +75,7 @@ dbgs() << "Running an SCC pass across the RefSCC: " << RC << "\n"; for (LazyCallGraph::SCC &C : RC) { - PreservedAnalyses PassPA = Pass.run(C, CGAM); + PreservedAnalyses PassPA = Pass.run(C, AM); // We know that the CGSCC pass couldn't have invalidated any other // SCC's analyses (that's the contract of a CGSCC pass), so @@ -113,7 +85,7 @@ // FIXME: This isn't quite correct. We need to handle the case where the // pass updated the CG, particularly some child of the current SCC, and // invalidate its analyses. - PassPA = CGAM.invalidate(C, std::move(PassPA)); + PassPA = AM.invalidate(C, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -121,11 +93,6 @@ } } - // By definition we preserve the proxy. This precludes *any* invalidation - // of CGSCC analyses by the proxy, but that's OK because we've taken - // care to invalidate analyses in the CGSCC analysis manager - // incrementally above. - PA.preserve(); return PA; } @@ -142,25 +109,10 @@ return ModuleToPostOrderCGSCCPassAdaptor(std::move(Pass), DebugLogging); } -extern template class InnerAnalysisManagerProxy; -/// A proxy from a \c FunctionAnalysisManager to an \c SCC. -typedef InnerAnalysisManagerProxy - FunctionAnalysisManagerCGSCCProxy; - -extern template class OuterAnalysisManagerProxy; -/// A proxy from a \c CGSCCAnalysisManager to a \c Function. -typedef OuterAnalysisManagerProxy - CGSCCAnalysisManagerFunctionProxy; - /// \brief Adaptor that maps from a SCC to its functions. /// /// Designed to allow composition of a FunctionPass(Manager) and -/// a CGSCCPassManager. Note that if this pass is constructed with a pointer -/// to a \c CGSCCAnalysisManager it will run the -/// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function -/// pass over the SCC to enable a \c FunctionAnalysisManager to be used -/// within this run safely. +/// a CGSCCPassManager. template class CGSCCToFunctionPassAdaptor : public PassInfoMixin> { @@ -185,37 +137,28 @@ } /// \brief Runs the function pass across every function in the module. - PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM) { - // Setup the function analysis manager from its proxy. - FunctionAnalysisManager &FAM = - AM.getResult(C).getManager(); - + PreservedAnalyses run(LazyCallGraph::SCC &C, AnalysisManager &AM) { if (DebugLogging) dbgs() << "Running function passes across an SCC: " << C << "\n"; PreservedAnalyses PA = PreservedAnalyses::all(); for (LazyCallGraph::Node &N : C) { - PreservedAnalyses PassPA = Pass.run(N.getFunction(), FAM); + PreservedAnalyses PassPA = Pass.run(N.getFunction(), AM); // 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. // Also, update the preserved analyses to reflect that once invalidated // these can again be preserved. - PassPA = FAM.invalidate(N.getFunction(), std::move(PassPA)); + PassPA = AM.invalidate(N.getFunction(), std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. PA.intersect(std::move(PassPA)); } - // 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. // FIXME: We need to update the call graph here to account for any deleted // edges! - PA.preserve(); return PA; } @@ -224,6 +167,18 @@ bool DebugLogging; }; +static inline IRUnitKind getIRUnitKindID(LazyCallGraph::SCC *) { + return IRK_CGSCC; +} +static inline Module *getStaticParentIRUnit(LazyCallGraph::SCC &C) { + assert(C.size() != 0 && "Empty SCC?"); + return C.begin()->getFunction().getParent(); +} +extern template struct ParentIRUnitTrackingAnalysis; + +// FIXME: Temporary typedef to avoid needing as much source churn. +typedef AnalysisManager CGSCCAnalysisManager; + /// \brief A function to deduce a function pass type and wrap it in the /// templated adaptor. template Index: include/llvm/Analysis/CallGraph.h =================================================================== --- include/llvm/Analysis/CallGraph.h +++ include/llvm/Analysis/CallGraph.h @@ -291,10 +291,6 @@ }; /// \brief An analysis pass to compute the \c CallGraph for a \c Module. -/// -/// This class implements the concept of an analysis pass used by the \c -/// ModuleAnalysisManager to run an analysis over a module and cache the -/// resulting data. class CallGraphAnalysis : public AnalysisInfoMixin { friend AnalysisInfoMixin; static char PassID; @@ -306,7 +302,7 @@ /// \brief Compute the \c CallGraph for the module \c M. /// /// The real work here is done in the \c CallGraph constructor. - CallGraph run(Module &M, ModuleAnalysisManager &) { return CallGraph(M); } + CallGraph run(Module &M, AnalysisManager &) { return CallGraph(M); } }; /// \brief Printer pass for the \c CallGraphAnalysis results. Index: include/llvm/Analysis/LoopInfo.h =================================================================== --- include/llvm/Analysis/LoopInfo.h +++ include/llvm/Analysis/LoopInfo.h @@ -846,7 +846,7 @@ PrintLoopPass(); PrintLoopPass(raw_ostream &OS, const std::string &Banner = ""); - PreservedAnalyses run(Loop &L, AnalysisManager &); + PreservedAnalyses run(Loop &L, AnalysisManager &); }; } // End llvm namespace Index: include/llvm/Analysis/LoopPassManager.h =================================================================== --- include/llvm/Analysis/LoopPassManager.h +++ include/llvm/Analysis/LoopPassManager.h @@ -29,35 +29,13 @@ /// typedef serves as a convenient way to refer to this construct. typedef PassManager LoopPassManager; -extern template class AnalysisManager; -/// \brief The loop analysis manager. -/// -/// See the documentation for the AnalysisManager template for detail -/// documentation. This typedef serves as a convenient way to refer to this -/// construct in the adaptors and proxies used to integrate this into the larger -/// pass manager infrastructure. -typedef AnalysisManager LoopAnalysisManager; - -extern template class InnerAnalysisManagerProxy; -/// A proxy from a \c LoopAnalysisManager to a \c Function. -typedef InnerAnalysisManagerProxy - LoopAnalysisManagerFunctionProxy; - -extern template class OuterAnalysisManagerProxy; -/// A proxy from a \c FunctionAnalysisManager to a \c Loop. -typedef OuterAnalysisManagerProxy - FunctionAnalysisManagerLoopProxy; - /// Returns the minimum set of Analyses that all loop passes must preserve. PreservedAnalyses getLoopPassPreservedAnalyses(); /// \brief Adaptor that maps from a function to its loops. /// /// Designed to allow composition of a LoopPass(Manager) and a -/// FunctionPassManager. Note that if this pass is constructed with a \c -/// FunctionAnalysisManager it will run the \c LoopAnalysisManagerFunctionProxy -/// analysis prior to running the loop passes over the function to enable a \c -/// LoopAnalysisManager to be used within this run safely. +/// FunctionPassManager. template class FunctionToLoopPassAdaptor : public PassInfoMixin> { @@ -81,10 +59,7 @@ } /// \brief Runs the loop passes across every loop in the function. - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { - // Setup the loop analysis manager from its proxy. - LoopAnalysisManager &LAM = - AM.getResult(F).getManager(); + PreservedAnalyses run(Function &F, AnalysisManager &AM) { // Get the loop structure for this function LoopInfo &LI = AM.getResult(F); @@ -103,7 +78,7 @@ // Now pop each element off of the stack to visit the loops in reverse // post-order. for (auto *L : reverse(Loops)) { - PreservedAnalyses PassPA = Pass.run(*L, LAM); + PreservedAnalyses PassPA = Pass.run(*L, AM); assert(PassPA.preserved(getLoopPassPreservedAnalyses()) && "Loop passes must preserve all relevant analyses"); @@ -112,17 +87,12 @@ // loop analysis manager's invalidation here. Also, update the // preserved analyses to reflect that once invalidated these can again // be preserved. - PassPA = LAM.invalidate(*L, std::move(PassPA)); + PassPA = AM.invalidate(*L, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. PA.intersect(std::move(PassPA)); } - - // By definition we preserve the proxy. This precludes *any* invalidation of - // loop analyses by the proxy, but that's OK because we've taken care to - // invalidate analyses in the loop analysis manager incrementally above. - PA.preserve(); return PA; } @@ -130,6 +100,15 @@ LoopPassT Pass; }; +static inline IRUnitKind getIRUnitKindID(Loop *) { return IRK_Loop; } +static inline Function *getStaticParentIRUnit(Loop &L) { + return L.getHeader()->getParent(); +} +extern template struct ParentIRUnitTrackingAnalysis; + +// FIXME: Temporary typedef to avoid needing as much source churn. +typedef AnalysisManager LoopAnalysisManager; + /// \brief A function to deduce a loop pass type and wrap it in the templated /// adaptor. template Index: include/llvm/IR/IRPrintingPasses.h =================================================================== --- include/llvm/IR/IRPrintingPasses.h +++ include/llvm/IR/IRPrintingPasses.h @@ -30,7 +30,7 @@ class ModulePass; class PreservedAnalyses; class raw_ostream; -template class AnalysisManager; +class AnalysisManager; /// \brief Create and return a pass that writes the module to the specified /// \c raw_ostream. @@ -68,7 +68,7 @@ PrintModulePass(raw_ostream &OS, const std::string &Banner = "", bool ShouldPreserveUseListOrder = false); - PreservedAnalyses run(Module &M, AnalysisManager &); + PreservedAnalyses run(Module &M, AnalysisManager &); static StringRef name() { return "PrintModulePass"; } }; @@ -85,7 +85,7 @@ PrintFunctionPass(); PrintFunctionPass(raw_ostream &OS, const std::string &Banner = ""); - PreservedAnalyses run(Function &F, AnalysisManager &); + PreservedAnalyses run(Function &F, AnalysisManager &); static StringRef name() { return "PrintFunctionPass"; } }; Index: include/llvm/IR/PassManager.h =================================================================== --- include/llvm/IR/PassManager.h +++ include/llvm/IR/PassManager.h @@ -170,8 +170,31 @@ SmallPtrSet PreservedPassIDs; }; -// Forward declare the analysis manager template. -template class AnalysisManager; +// The key used for holding analyses registered in the analysis manager. +struct AnalysisKey { + void *AnalysisID; + IRUnitKind IRUnitKindID; +}; + +static inline IRUnitKind getIRUnitKindID(Function *) { return IRK_Function; } +static inline IRUnitKind getIRUnitKindID(Module *) { return IRK_Module; } +static inline Module *getStaticParentIRUnit(Function &F) { return F.getParent(); } +static inline Module *getStaticParentIRUnit(Module &M) { return nullptr; } + +// Provide DenseMapInfo for AnalysisKey +template <> struct DenseMapInfo { + static inline AnalysisKey getEmptyKey() { return {nullptr, IRK_Module}; } + static inline AnalysisKey getTombstoneKey() { + return {nullptr, IRK_Function}; + } + static unsigned getHashValue(const AnalysisKey &Val) { + return hash_combine(Val.AnalysisID, Val.IRUnitKindID); + } + static bool isEqual(const AnalysisKey &LHS, const AnalysisKey &RHS) { + return LHS.AnalysisID == RHS.AnalysisID && + LHS.IRUnitKindID == RHS.IRUnitKindID; + } +}; /// A CRTP mix-in to automatically provide informational APIs needed for /// passes. @@ -211,17 +234,472 @@ static void *ID() { return (void *)&DerivedT::PassID; } }; +class AnalysisManager; + +// This is used internally by the analysis manager to track dependencies on +// parent IRUnit's. +template +struct ParentIRUnitTrackingAnalysis + : public AnalysisInfoMixin> { + typedef int Result; // Dummy. + Result run(IRUnitT &, AnalysisManager &) { return 0; } + static char PassID; +}; +template char ParentIRUnitTrackingAnalysis::PassID; +extern template struct ParentIRUnitTrackingAnalysis; +extern template struct ParentIRUnitTrackingAnalysis; + +namespace detail { + +/// \brief A CRTP base used to implement analysis managers. +/// +/// This class template serves as the boiler plate of an analysis manager. Any +/// analysis manager can be implemented on top of this base class. Any +/// implementation will be required to provide specific hooks: +/// +/// - getResultImpl +/// - getCachedResultImpl +/// - invalidateImpl +/// +/// The details of the call pattern are within. +/// +/// Note that there is also a generic analysis manager template which implements +/// the above required functions along with common datastructures used for +/// managing analyses. This base class is factored so that if you need to +/// customize the handling of a specific IR unit, you can do so without +/// replicating *all* of the boilerplate. +template +class AnalysisManagerBase { + DerivedT *derived_this() { return static_cast(this); } + const DerivedT *derived_this() const { + return static_cast(this); + } + + AnalysisManagerBase(const AnalysisManagerBase &) = delete; + AnalysisManagerBase &operator=(const AnalysisManagerBase &) = delete; + +protected: + typedef detail::AnalysisResultConcept ResultConceptT; + typedef detail::AnalysisPassConcept PassConceptT; + + // FIXME: Provide template aliases for the models when we're using C++11 in + // a mode supporting them. + + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisManagerBase() {} + AnalysisManagerBase(AnalysisManagerBase &&Arg) + : AnalysisPasses(std::move(Arg.AnalysisPasses)) {} + AnalysisManagerBase &operator=(AnalysisManagerBase &&RHS) { + AnalysisPasses = std::move(RHS.AnalysisPasses); + return *this; + } + +public: + /// \brief Get the result of an analysis pass for this module. + /// + /// If there is not a valid cached result in the manager already, this will + /// re-run the analysis to produce a valid result. + template + typename PassT::Result &getResult(IRUnitT &IR) { + AnalysisKey AK = {PassT::ID(), getIRUnitKindID(&IR)}; + assert(AnalysisPasses.count(AK) && + "This analysis pass was not registered prior to being queried"); + + ResultConceptT &ResultConcept = derived_this()->getResultImpl(AK, IR); + typedef detail::AnalysisResultModel + ResultModelT; + return static_cast(ResultConcept).Result; + } + + /// \brief Get the cached result of an analysis pass for this module. + /// + /// This method never runs the analysis. + /// + /// \returns null if there is no cached result. + template + typename PassT::Result *getCachedResult(IRUnitT &IR) const { + AnalysisKey AK = {PassT::ID(), getIRUnitKindID(&IR)}; + assert(AnalysisPasses.count(AK) && + "This analysis pass was not registered prior to being queried"); + + ResultConceptT *ResultConcept = derived_this()->getCachedResultImpl(AK, IR); + if (!ResultConcept) + return nullptr; + + typedef detail::AnalysisResultModel + ResultModelT; + return &static_cast(ResultConcept)->Result; + } + + /// \brief Register an analysis pass with the manager. + /// + /// The argument is a callable whose result is a pass. This allows passing in + /// a lambda to construct the pass. + /// + /// The pass type registered is the result type of calling the argument. If + /// that pass has already been registered, then the argument will not be + /// called and this function will return false. Otherwise, the pass type + /// becomes registered, with the instance provided by calling the argument + /// once, and this function returns true. + /// + /// While this returns whether or not the pass type was already registered, + /// there in't an independent way to query that as that would be prone to + /// risky use when *querying* the analysis manager. Instead, the only + /// supported use case is avoiding duplicate registry of an analysis. This + /// interface also lends itself to minimizing the number of times we have to + /// do lookups for analyses or construct complex passes only to throw them + /// away. + template + bool registerPass(PassBuilderT PassBuilder) { + typedef decltype(PassBuilder()) PassT; + typedef detail::AnalysisPassModel PassModelT; + + AnalysisKey AK = {PassT::ID(), getIRUnitKindID((IRUnitT *)nullptr)}; + auto &PassPtr = AnalysisPasses[AK]; + if (PassPtr) + // Already registered this pass type! + return false; + + // Construct a new model around the instance returned by the builder. + PassPtr.reset(new PassModelT(PassBuilder())); + return true; + } + + /// \brief Invalidate a specific analysis pass for an IR module. + /// + /// Note that the analysis result can disregard invalidation. + template void invalidate(IRUnitT &IR) { + AnalysisKey AK = {PassT::ID(), getIRUnitKindID(&IR)}; + assert(AnalysisPasses.count(AK) && + "This analysis pass was not registered prior to being invalidated"); + derived_this()->invalidateImpl(AK, IR); + } + + /// \brief Invalidate analyses cached for an IR unit. + /// + /// Walk through all of the analyses pertaining to this unit of IR and + /// invalidate them unless they are preserved by the PreservedAnalyses set. + /// We accept the PreservedAnalyses set by value and update it with each + /// analyis pass which has been successfully invalidated and thus can be + /// preserved going forward. The updated set is returned. + template + PreservedAnalyses invalidate(IRUnitT &IR, PreservedAnalyses PA) { + return derived_this()->invalidateImpl(IR, std::move(PA)); + } + +protected: + /// \brief Lookup a registered analysis pass. + PassConceptT &lookupPass(AnalysisKey AK) { + typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(AK); + assert(PI != AnalysisPasses.end() && + "Analysis passes must be registered prior to being queried!"); + return *PI->second; + } + + /// \brief Lookup a registered analysis pass. + const PassConceptT &lookupPass(AnalysisKey AK) const { + typename AnalysisPassMapT::const_iterator PI = AnalysisPasses.find(AK); + assert(PI != AnalysisPasses.end() && + "Analysis passes must be registered prior to being queried!"); + return *PI->second; + } + +private: + /// \brief Map type from module analysis pass ID to pass concept pointer. + typedef DenseMap> AnalysisPassMapT; + + /// \brief Collection of module analysis passes, indexed by ID. + AnalysisPassMapT AnalysisPasses; +}; + +} // End namespace detail + +struct PerIRUnitAnalysisResultListElement; +struct DependentTrackingNode { + std::list::iterator Dependent; + + // This is a backpointer to allow deletion by somebody with just an + // iterator. + std::list &OwnerList; +}; +struct PerIRUnitAnalysisResultListElement { + PerIRUnitAnalysisResultListElement( + AnalysisKey AK_, + std::unique_ptr AnalysisResult_, + TypeErasedIRUnitID ID_) + : AK(AK_), Result(std::move(AnalysisResult_)), ID(ID_) {} + AnalysisKey AK; + std::unique_ptr Result; + std::list Dependents; + std::vector::iterator> + DependentTrackingNodesThatPointAtMe; + + // This is needed so that we can invalidate this analysis result with + // just an iterator to this struct. + TypeErasedIRUnitID ID; +}; + +/// \brief A generic analysis pass manager with lazy running and caching of +/// results. +/// +/// This analysis manager can be used for any IR unit where the address of the +/// IR unit sufficies as its identity. It manages the cache for a unit of IR via +/// the address of each unit of IR cached. +class AnalysisManager : public detail::AnalysisManagerBase { + friend class detail::AnalysisManagerBase; + typedef detail::AnalysisManagerBase BaseT; + typedef typename BaseT::ResultConceptT ResultConceptT; + typedef typename BaseT::PassConceptT PassConceptT; + +public: + // Most public APIs are inherited from the CRTP base class. + + /// \brief Construct an empty analysis manager. + /// + /// A flag can be passed to indicate that the manager should perform debug + /// logging. + AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} + + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisManager(AnalysisManager &&Arg) + : BaseT(std::move(static_cast(Arg))), + AnalysisResults(std::move(Arg.AnalysisResults)), + DebugLogging(std::move(Arg.DebugLogging)) {} + AnalysisManager &operator=(AnalysisManager &&RHS) { + BaseT::operator=(std::move(static_cast(RHS))); + AnalysisResults = std::move(RHS.AnalysisResults); + DebugLogging = std::move(RHS.DebugLogging); + return *this; + } + + /// \brief Returns true if the analysis manager has an empty results cache. + bool empty() const { + assert(AnalysisResults.empty() == AnalysisResultLists.empty() && + "The storage and index of analysis results disagree on how many " + "there are!"); + return AnalysisResults.empty(); + } + + /// \brief Clear the analysis result cache. + /// + /// This routine allows cleaning up when the set of IR units itself has + /// potentially changed, and thus we can't even look up a a result and + /// invalidate it directly. Notably, this does *not* call invalidate functions + /// as there is nothing to be done for them. + void clear() { + AnalysisResults.clear(); + AnalysisResultLists.clear(); + } + +private: + AnalysisManager(const AnalysisManager &) = delete; + AnalysisManager &operator=(const AnalysisManager &) = delete; + + /// \brief List of function analysis pass IDs and associated concept pointers. + /// + /// Requires iterators to be valid across appending new entries and arbitrary + /// erases. Provides both the pass ID and concept pointer such that it is + /// half of a bijection and provides storage for the actual result concept. + /// Also does dependency tracking. + typedef std::list AnalysisResultListT; + + + /// \brief Get an analysis result, running the pass if necessary. + template + ResultConceptT &getResultImpl(AnalysisKey AK, IRUnitT &IR) { + typename AnalysisResultMapT::iterator RI; + bool Inserted; + std::tie(RI, Inserted) = AnalysisResults.insert( + std::make_pair(std::make_pair(AK, static_cast(&IR)), + typename AnalysisResultListT::iterator())); + + AnalysisResultListT::iterator ThisResult = RI->second; + + // If we don't have a cached result for this function, look up the pass and + // run it to produce a result, which we then add to the cache. + if (Inserted) { + auto &P = this->lookupPass(AK); + if (DebugLogging) + dbgs() << "Running analysis: " << P.name() << "\n"; + std::unique_ptr &ResultListPtr = + AnalysisResultLists[static_cast(&IR)]; + if (!ResultListPtr) + ResultListPtr = make_unique(); + AnalysisResultListT &ResultList = *ResultListPtr; + ResultList.emplace_back( + AK, std::unique_ptr(nullptr), + static_cast(&IR)); + PerIRUnitAnalysisResultListElement &E = ResultList.back(); + ThisResult = std::prev(ResultList.end()); + RI->second = ThisResult; + InFlightAnalysesStack.push_back(ThisResult); + // Set up the parent IR unit tracking analysis. + // The dependency link will invalidate this result when invalidating + // analysis result for the parent IRUnit. + if (auto *P = getStaticParentIRUnit(IR)) { + typedef + typename std::remove_reference::type ParentIRUnitT; + this->getResult>(*P); + } + // Run the analysis and get the result. + E.Result = P.run(static_cast(&IR), *this); + InFlightAnalysesStack.pop_back(); + } + + // Add dependency tracking links. + if (!InFlightAnalysesStack.empty()) { + auto I = InFlightAnalysesStack.back(); + ThisResult->Dependents.push_back({I, ThisResult->Dependents}); + I->DependentTrackingNodesThatPointAtMe.push_back( + std::prev(ThisResult->Dependents.end())); + } + + return *ThisResult->Result; + } + + /// \brief Get a cached analysis result or return null. + template + ResultConceptT *getCachedResultImpl(AnalysisKey AK, IRUnitT &IR) const { + typename AnalysisResultMapT::const_iterator RI = AnalysisResults.find( + std::make_pair(AK, static_cast(&IR))); + bool Cached = RI != AnalysisResults.end(); + if (!Cached) + return nullptr; + AnalysisResultListT::iterator ThisResult = RI->second; + // Add dependency tracking links. + if (!InFlightAnalysesStack.empty()) { + auto I = InFlightAnalysesStack.back(); + ThisResult->Dependents.push_back({I, ThisResult->Dependents}); + I->DependentTrackingNodesThatPointAtMe.push_back( + std::prev(ThisResult->Dependents.end())); + } + return ThisResult->Result.get(); + } + + /// \brief Invalidate a function pass result. + template void invalidateImpl(AnalysisKey AK, IRUnitT &IR) { + invalidateImplImpl(AK, static_cast(&IR)); + } + + /// \brief Invalidate a function pass result. + /// This includes walking its dependencies and invalidating them. + /// + /// Returns an iterator to the next element in the list (after all + /// dependencies have been invalidated, which may have removed elements + /// from the list). + typename AnalysisResultListT::iterator + invalidateImplImpl(AnalysisKey AK, TypeErasedIRUnitID ID) { + auto MapKey = std::make_pair(AK, ID); + typename AnalysisResultMapT::iterator RI = AnalysisResults.find(MapKey); + if (RI == AnalysisResults.end()) + return typename AnalysisResultListT::iterator(); + + if (DebugLogging) + dbgs() << "Invalidating analysis: " << this->lookupPass(AK).name() + << "\n"; + auto I = RI->second; + auto &L = *AnalysisResultLists[ID]; + auto &D = I->Dependents; + // Invalidate all dependents. + while (!D.empty()) { + auto &Element = *D.front().Dependent; + // This recursive call will delete (at least) this element of `D`. + invalidateImplImpl(Element.AK, Element.ID); + } + // Remove any dependent tracking nodes that are tracking a dependency + // on this analysis result. + // This analysis result is about to be erased and those pointers can't + // be allowed to dangle. + for (auto DepNodeIt : I->DependentTrackingNodesThatPointAtMe) + DepNodeIt->OwnerList.erase(DepNodeIt); + + auto Ret = L.erase(I); // This returns the iterator to the next element. + AnalysisResults.erase(MapKey); // RI may have been invalidated, so use the key. + return Ret; + } + + /// \brief Invalidate the results for a function.. + template + PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) { + // Short circuit for a common case of all analyses being preserved. + if (PA.areAllPreserved()) + return PA; + + if (DebugLogging) + dbgs() << "Invalidating all non-preserved analyses for: " << IR.getName() + << "\n"; + + // Clear all the invalidated results associated specifically with this + // function. + SmallVector InvalidatedAnalysisKeys; + std::unique_ptr &ResultsListPtr = + AnalysisResultLists[static_cast(&IR)]; + if (!ResultsListPtr) + ResultsListPtr = make_unique(); + AnalysisResultListT &ResultsList = *ResultsListPtr; + for (typename AnalysisResultListT::iterator I = ResultsList.begin(), + E = ResultsList.end(); + I != E;) { + AnalysisKey AK = I->AK; + + // Pass the invalidation down to the pass itself to see if it thinks it is + // necessary. The analysis pass can return false if no action on the part + // of the analysis manager is required for this invalidation event. + if (I->Result->invalidate(static_cast(&IR), PA)) + I = invalidateImplImpl(AK, static_cast(&IR)); + else + ++I; + + // After handling each pass, we mark it as preserved. Once we've + // invalidated any stale results, the rest of the system is allowed to + // start preserving this analysis again. + PA.preserve(AK.AnalysisID); + } + if (ResultsList.empty()) + AnalysisResultLists.erase(static_cast(&IR)); + + return PA; + } + + /// \brief Map type from function pointer to our custom list type. + typedef DenseMap> + AnalysisResultListMapT; + + /// \brief Map from function to a list of function analysis results. + /// + /// Provides linear time removal of all analysis results for a function and + /// the ultimate storage for a particular cached analysis result. + AnalysisResultListMapT AnalysisResultLists; + + /// \brief Map type from a pair of analysis ID and function pointer to an + /// iterator into a particular result list. + typedef DenseMap, + typename AnalysisResultListT::iterator> + AnalysisResultMapT; + + /// \brief Map from an analysis ID and function to a particular cached + /// analysis result. + AnalysisResultMapT AnalysisResults; + + /// \brief A stack of analyses currently being computed. + SmallVector InFlightAnalysesStack; + + /// \brief A flag indicating whether debug logging is enabled. + bool DebugLogging; +}; + +// FIXME: Temporary typedef's to avoid needing as much source churn. +typedef AnalysisManager FunctionAnalysisManager; +typedef AnalysisManager ModuleAnalysisManager; + /// \brief Manages a sequence of passes over units of IR. /// /// A pass manager contains a sequence of passes to run over units of IR. It is /// itself a valid pass over that unit of IR, and when over some given IR will /// run each pass in sequence. This is the primary and most basic building /// block of a pass pipeline. -/// -/// If it is run with an \c AnalysisManager argument, it will propagate -/// that analysis manager to each pass it runs, as well as calling the analysis -/// manager's invalidation routine with the PreservedAnalyses of each pass it -/// runs. template class PassManager : public PassInfoMixin> { public: @@ -241,7 +719,7 @@ } /// \brief Run all of the passes in this manager over the IR. - PreservedAnalyses run(IRUnitT &IR, AnalysisManager &AM) { + PreservedAnalyses run(IRUnitT &IR, AnalysisManager &AM) { PreservedAnalyses PA = PreservedAnalyses::all(); if (DebugLogging) @@ -302,554 +780,11 @@ /// \brief Convenience typedef for a pass manager over functions. typedef PassManager FunctionPassManager; -namespace detail { - -/// \brief A CRTP base used to implement analysis managers. -/// -/// This class template serves as the boiler plate of an analysis manager. Any -/// analysis manager can be implemented on top of this base class. Any -/// implementation will be required to provide specific hooks: -/// -/// - getResultImpl -/// - getCachedResultImpl -/// - invalidateImpl -/// -/// The details of the call pattern are within. -/// -/// Note that there is also a generic analysis manager template which implements -/// the above required functions along with common datastructures used for -/// managing analyses. This base class is factored so that if you need to -/// customize the handling of a specific IR unit, you can do so without -/// replicating *all* of the boilerplate. -template class AnalysisManagerBase { - DerivedT *derived_this() { return static_cast(this); } - const DerivedT *derived_this() const { - return static_cast(this); - } - - AnalysisManagerBase(const AnalysisManagerBase &) = delete; - AnalysisManagerBase &operator=(const AnalysisManagerBase &) = delete; - -protected: - typedef detail::AnalysisResultConcept ResultConceptT; - typedef detail::AnalysisPassConcept PassConceptT; - - // FIXME: Provide template aliases for the models when we're using C++11 in - // a mode supporting them. - - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisManagerBase() {} - AnalysisManagerBase(AnalysisManagerBase &&Arg) - : AnalysisPasses(std::move(Arg.AnalysisPasses)) {} - AnalysisManagerBase &operator=(AnalysisManagerBase &&RHS) { - AnalysisPasses = std::move(RHS.AnalysisPasses); - return *this; - } - -public: - /// \brief Get the result of an analysis pass for this module. - /// - /// If there is not a valid cached result in the manager already, this will - /// re-run the analysis to produce a valid result. - template typename PassT::Result &getResult(IRUnitT &IR) { - assert(AnalysisPasses.count(PassT::ID()) && - "This analysis pass was not registered prior to being queried"); - - ResultConceptT &ResultConcept = - derived_this()->getResultImpl(PassT::ID(), IR); - typedef detail::AnalysisResultModel - ResultModelT; - return static_cast(ResultConcept).Result; - } - - /// \brief Get the cached result of an analysis pass for this module. - /// - /// This method never runs the analysis. - /// - /// \returns null if there is no cached result. - template - typename PassT::Result *getCachedResult(IRUnitT &IR) const { - assert(AnalysisPasses.count(PassT::ID()) && - "This analysis pass was not registered prior to being queried"); - - ResultConceptT *ResultConcept = - derived_this()->getCachedResultImpl(PassT::ID(), IR); - if (!ResultConcept) - return nullptr; - - typedef detail::AnalysisResultModel - ResultModelT; - return &static_cast(ResultConcept)->Result; - } - - /// \brief Register an analysis pass with the manager. - /// - /// The argument is a callable whose result is a pass. This allows passing in - /// a lambda to construct the pass. - /// - /// The pass type registered is the result type of calling the argument. If - /// that pass has already been registered, then the argument will not be - /// called and this function will return false. Otherwise, the pass type - /// becomes registered, with the instance provided by calling the argument - /// once, and this function returns true. - /// - /// While this returns whether or not the pass type was already registered, - /// there in't an independent way to query that as that would be prone to - /// risky use when *querying* the analysis manager. Instead, the only - /// supported use case is avoiding duplicate registry of an analysis. This - /// interface also lends itself to minimizing the number of times we have to - /// do lookups for analyses or construct complex passes only to throw them - /// away. - template bool registerPass(PassBuilderT PassBuilder) { - typedef decltype(PassBuilder()) PassT; - typedef detail::AnalysisPassModel PassModelT; - - auto &PassPtr = AnalysisPasses[PassT::ID()]; - if (PassPtr) - // Already registered this pass type! - return false; - - // Construct a new model around the instance returned by the builder. - PassPtr.reset(new PassModelT(PassBuilder())); - return true; - } - - /// \brief Invalidate a specific analysis pass for an IR module. - /// - /// Note that the analysis result can disregard invalidation. - template void invalidate(IRUnitT &IR) { - assert(AnalysisPasses.count(PassT::ID()) && - "This analysis pass was not registered prior to being invalidated"); - derived_this()->invalidateImpl(PassT::ID(), IR); - } - - /// \brief Invalidate analyses cached for an IR unit. - /// - /// Walk through all of the analyses pertaining to this unit of IR and - /// invalidate them unless they are preserved by the PreservedAnalyses set. - /// We accept the PreservedAnalyses set by value and update it with each - /// analyis pass which has been successfully invalidated and thus can be - /// preserved going forward. The updated set is returned. - PreservedAnalyses invalidate(IRUnitT &IR, PreservedAnalyses PA) { - return derived_this()->invalidateImpl(IR, std::move(PA)); - } - -protected: - /// \brief Lookup a registered analysis pass. - PassConceptT &lookupPass(void *PassID) { - typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(PassID); - assert(PI != AnalysisPasses.end() && - "Analysis passes must be registered prior to being queried!"); - return *PI->second; - } - - /// \brief Lookup a registered analysis pass. - const PassConceptT &lookupPass(void *PassID) const { - typename AnalysisPassMapT::const_iterator PI = AnalysisPasses.find(PassID); - assert(PI != AnalysisPasses.end() && - "Analysis passes must be registered prior to being queried!"); - return *PI->second; - } - -private: - /// \brief Map type from module analysis pass ID to pass concept pointer. - typedef DenseMap> AnalysisPassMapT; - - /// \brief Collection of module analysis passes, indexed by ID. - AnalysisPassMapT AnalysisPasses; -}; - -} // End namespace detail - -/// \brief A generic analysis pass manager with lazy running and caching of -/// results. -/// -/// This analysis manager can be used for any IR unit where the address of the -/// IR unit sufficies as its identity. It manages the cache for a unit of IR via -/// the address of each unit of IR cached. -template -class AnalysisManager - : public detail::AnalysisManagerBase, IRUnitT> { - friend class detail::AnalysisManagerBase, IRUnitT>; - typedef detail::AnalysisManagerBase, IRUnitT> BaseT; - typedef typename BaseT::ResultConceptT ResultConceptT; - typedef typename BaseT::PassConceptT PassConceptT; - -public: - // Most public APIs are inherited from the CRTP base class. - - /// \brief Construct an empty analysis manager. - /// - /// A flag can be passed to indicate that the manager should perform debug - /// logging. - AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} - - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisManager(AnalysisManager &&Arg) - : BaseT(std::move(static_cast(Arg))), - AnalysisResults(std::move(Arg.AnalysisResults)), - DebugLogging(std::move(Arg.DebugLogging)) {} - AnalysisManager &operator=(AnalysisManager &&RHS) { - BaseT::operator=(std::move(static_cast(RHS))); - AnalysisResults = std::move(RHS.AnalysisResults); - DebugLogging = std::move(RHS.DebugLogging); - return *this; - } - - /// \brief Returns true if the analysis manager has an empty results cache. - bool empty() const { - assert(AnalysisResults.empty() == AnalysisResultLists.empty() && - "The storage and index of analysis results disagree on how many " - "there are!"); - return AnalysisResults.empty(); - } - - /// \brief Clear the analysis result cache. - /// - /// This routine allows cleaning up when the set of IR units itself has - /// potentially changed, and thus we can't even look up a a result and - /// invalidate it directly. Notably, this does *not* call invalidate functions - /// as there is nothing to be done for them. - void clear() { - AnalysisResults.clear(); - AnalysisResultLists.clear(); - } - -private: - AnalysisManager(const AnalysisManager &) = delete; - AnalysisManager &operator=(const AnalysisManager &) = delete; - - /// \brief Get an analysis result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) { - typename AnalysisResultMapT::iterator RI; - bool Inserted; - std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair( - std::make_pair(PassID, &IR), typename AnalysisResultListT::iterator())); - - // If we don't have a cached result for this function, look up the pass and - // run it to produce a result, which we then add to the cache. - if (Inserted) { - auto &P = this->lookupPass(PassID); - if (DebugLogging) - dbgs() << "Running analysis: " << P.name() << "\n"; - AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; - ResultList.emplace_back(PassID, P.run(IR, *this)); - - // P.run may have inserted elements into AnalysisResults and invalidated - // RI. - RI = AnalysisResults.find(std::make_pair(PassID, &IR)); - assert(RI != AnalysisResults.end() && "we just inserted it!"); - - RI->second = std::prev(ResultList.end()); - } - - return *RI->second->second; - } - - /// \brief Get a cached analysis result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, IRUnitT &IR) const { - typename AnalysisResultMapT::const_iterator RI = - AnalysisResults.find(std::make_pair(PassID, &IR)); - return RI == AnalysisResults.end() ? nullptr : &*RI->second->second; - } - - /// \brief Invalidate a function pass result. - void invalidateImpl(void *PassID, IRUnitT &IR) { - typename AnalysisResultMapT::iterator RI = - AnalysisResults.find(std::make_pair(PassID, &IR)); - if (RI == AnalysisResults.end()) - return; - - if (DebugLogging) - dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() - << "\n"; - AnalysisResultLists[&IR].erase(RI->second); - AnalysisResults.erase(RI); - } - - /// \brief Invalidate the results for a function.. - PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) { - // Short circuit for a common case of all analyses being preserved. - if (PA.areAllPreserved()) - return PA; - - if (DebugLogging) - dbgs() << "Invalidating all non-preserved analyses for: " << IR.getName() - << "\n"; - - // Clear all the invalidated results associated specifically with this - // function. - SmallVector InvalidatedPassIDs; - AnalysisResultListT &ResultsList = AnalysisResultLists[&IR]; - for (typename AnalysisResultListT::iterator I = ResultsList.begin(), - E = ResultsList.end(); - I != E;) { - void *PassID = I->first; - - // Pass the invalidation down to the pass itself to see if it thinks it is - // necessary. The analysis pass can return false if no action on the part - // of the analysis manager is required for this invalidation event. - if (I->second->invalidate(IR, PA)) { - if (DebugLogging) - dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() - << "\n"; - - InvalidatedPassIDs.push_back(I->first); - I = ResultsList.erase(I); - } else { - ++I; - } - - // After handling each pass, we mark it as preserved. Once we've - // invalidated any stale results, the rest of the system is allowed to - // start preserving this analysis again. - PA.preserve(PassID); - } - while (!InvalidatedPassIDs.empty()) - AnalysisResults.erase( - std::make_pair(InvalidatedPassIDs.pop_back_val(), &IR)); - if (ResultsList.empty()) - AnalysisResultLists.erase(&IR); - - return PA; - } - - /// \brief List of function analysis pass IDs and associated concept pointers. - /// - /// Requires iterators to be valid across appending new entries and arbitrary - /// erases. Provides both the pass ID and concept pointer such that it is - /// half of a bijection and provides storage for the actual result concept. - typedef std::list>>> - AnalysisResultListT; - - /// \brief Map type from function pointer to our custom list type. - typedef DenseMap AnalysisResultListMapT; - - /// \brief Map from function to a list of function analysis results. - /// - /// Provides linear time removal of all analysis results for a function and - /// the ultimate storage for a particular cached analysis result. - AnalysisResultListMapT AnalysisResultLists; - - /// \brief Map type from a pair of analysis ID and function pointer to an - /// iterator into a particular result list. - typedef DenseMap, - typename AnalysisResultListT::iterator> - AnalysisResultMapT; - - /// \brief Map from an analysis ID and function to a particular cached - /// analysis result. - AnalysisResultMapT AnalysisResults; - - /// \brief A flag indicating whether debug logging is enabled. - bool DebugLogging; -}; - -extern template class AnalysisManager; -/// \brief Convenience typedef for the Module analysis manager. -typedef AnalysisManager ModuleAnalysisManager; - -extern template class AnalysisManager; -/// \brief Convenience typedef for the Function analysis manager. -typedef AnalysisManager FunctionAnalysisManager; - -/// \brief A module analysis which acts as a proxy for a function analysis -/// manager. -/// -/// This primarily proxies invalidation information from the module analysis -/// manager and module pass manager to a function analysis manager. You should -/// never use a function 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 FunctionAnalysisManager it -/// provides. -template -class InnerAnalysisManagerProxy - : public AnalysisInfoMixin< - InnerAnalysisManagerProxy> { -public: - 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; - - // 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. - 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; - } - - /// \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(IRUnitT &IR, AnalysisManager &) { return Result(*AM); } - -private: - friend AnalysisInfoMixin< - InnerAnalysisManagerProxy>; - static char PassID; - - AnalysisManagerT *AM; -}; - -template -char InnerAnalysisManagerProxy::PassID; - -extern template class InnerAnalysisManagerProxy; -/// Provide the \c FunctionAnalysisManager to \c Module proxy. -typedef InnerAnalysisManagerProxy - FunctionAnalysisManagerModuleProxy; - -/// \brief A function analysis which acts as a proxy for a module analysis -/// manager. -/// -/// This primarily provides an accessor to a parent module analysis manager to -/// function passes. Only the const interface of the module analysis manager is -/// provided to indicate that once inside of a function 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. -template -class OuterAnalysisManagerProxy - : public AnalysisInfoMixin< - OuterAnalysisManagerProxy> { -public: - /// \brief Result proxy object for \c OuterAnalysisManagerProxy. - class Result { - public: - 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) : AM(Arg.AM) {} - Result(Result &&Arg) : AM(std::move(Arg.AM)) {} - Result &operator=(Result RHS) { - std::swap(AM, RHS.AM); - return *this; - } - - const AnalysisManagerT &getManager() const { return *AM; } - - /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(IRUnitT &) { return false; } - - private: - const AnalysisManagerT *AM; - }; - - OuterAnalysisManagerProxy(const AnalysisManagerT &AM) : AM(&AM) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - 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 AM reference into the - /// result. - Result run(IRUnitT &, AnalysisManager &) { return Result(*AM); } - -private: - friend AnalysisInfoMixin< - OuterAnalysisManagerProxy>; - static char PassID; - - const AnalysisManagerT *AM; -}; - -template -char OuterAnalysisManagerProxy::PassID; - -extern template class OuterAnalysisManagerProxy; -/// Provide the \c ModuleAnalysisManager to \c Fucntion proxy. -typedef OuterAnalysisManagerProxy - ModuleAnalysisManagerFunctionProxy; /// \brief Trivial adaptor that maps from a module to its functions. /// /// Designed to allow composition of a FunctionPass(Manager) and -/// a ModulePassManager. Note that if this pass is constructed with a pointer -/// to a \c ModuleAnalysisManager it will run the -/// \c FunctionAnalysisManagerModuleProxy analysis prior to running the function -/// pass over the module to enable a \c FunctionAnalysisManager to be used -/// within this run safely. +/// a ModulePassManager. /// /// 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 @@ -887,35 +822,27 @@ } /// \brief Runs the function pass across every function in the module. - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { - // Setup the function analysis manager from its proxy. - FunctionAnalysisManager &FAM = - AM.getResult(M).getManager(); - + PreservedAnalyses run(Module &M, AnalysisManager &AM) { PreservedAnalyses PA = PreservedAnalyses::all(); for (Function &F : M) { if (F.isDeclaration()) continue; - PreservedAnalyses PassPA = Pass.run(F, FAM); + PreservedAnalyses PassPA = Pass.run(F, AM); // 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 and // update our preserved set to reflect that these have already been // handled. - PassPA = FAM.invalidate(F, std::move(PassPA)); + PassPA = AM.invalidate(F, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. PA.intersect(std::move(PassPA)); } - // 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(); + PA.preserve>(); return PA; } @@ -944,7 +871,7 @@ /// created, these methods can be instantiated to satisfy whatever the /// context requires. template - PreservedAnalyses run(IRUnitT &Arg, AnalysisManager &AM) { + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager &AM) { (void)AM.template getResult(Arg); return PreservedAnalyses::all(); @@ -966,7 +893,7 @@ /// created, these methods can be instantiated to satisfy whatever the /// context requires. template - PreservedAnalyses run(IRUnitT &Arg, AnalysisManager &AM) { + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager &AM) { // We have to directly invalidate the analysis result as we can't // enumerate all other analyses and use the preserved set to control it. AM.template invalidate(Arg); @@ -982,7 +909,7 @@ struct InvalidateAllAnalysesPass : PassInfoMixin { /// \brief Run this pass over some unit of IR. template - PreservedAnalyses run(IRUnitT &, AnalysisManager &) { + PreservedAnalyses run(IRUnitT &, AnalysisManager &) { return PreservedAnalyses::none(); } }; @@ -1010,8 +937,7 @@ } template - PreservedAnalyses run(IRUnitT &Arg, AnalysisManager &AM, - Ts... Args) { + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager &AM, Ts... Args) { auto PA = PreservedAnalyses::all(); for (int i = 0; i < Count; ++i) PA.intersect(P.run(Arg, AM, Args...)); Index: include/llvm/IR/PassManagerInternal.h =================================================================== --- include/llvm/IR/PassManagerInternal.h +++ include/llvm/IR/PassManagerInternal.h @@ -23,7 +23,12 @@ namespace llvm { -template class AnalysisManager; +/// More semantically meaningful name for opaque handle type. +typedef void *TypeErasedIRUnitID; + +enum IRUnitKind { IRK_Loop, IRK_Function, IRK_CGSCC, IRK_Module }; + +class AnalysisManager; class PreservedAnalyses; /// \brief Implementation details of the pass manager interfaces. @@ -36,7 +41,7 @@ virtual ~PassConcept() {} /// \brief The polymorphic API which runs the pass over a given IR entity. - virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager &AM) = 0; + virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager &AM) = 0; /// \brief Polymorphic method to access the name of a pass. virtual StringRef name() = 0; @@ -45,7 +50,7 @@ /// \brief A template wrapper used to implement the polymorphic API. /// /// Can be instantiated for any object which provides a \c run method accepting -/// an \c IRUnitT& and an \c AnalysisManager&. It requires the pass to +/// an \c IRUnitT& and an \c AnalysisManager&. It requires the pass to /// be a copyable object. template @@ -64,7 +69,7 @@ return *this; } - PreservedAnalysesT run(IRUnitT &IR, AnalysisManager &AM) override { + PreservedAnalysesT run(IRUnitT &IR, AnalysisManager &AM) override { return Pass.run(IR, AM); } StringRef name() override { return PassT::name(); } @@ -75,7 +80,7 @@ /// /// This concept is parameterized over the IR unit that this result pertains /// to. -template struct AnalysisResultConcept { +struct AnalysisResultConcept { virtual ~AnalysisResultConcept() {} /// \brief Method to try and mark a result as invalid. @@ -88,7 +93,8 @@ /// 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; + virtual bool invalidate(TypeErasedIRUnitID IR, + const PreservedAnalyses &PA) = 0; }; /// \brief SFINAE metafunction for computing whether \c ResultT provides an @@ -126,7 +132,7 @@ template struct AnalysisResultModel - : AnalysisResultConcept { + : AnalysisResultConcept { explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. @@ -147,7 +153,8 @@ // 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. - bool invalidate(IRUnitT &, const PreservedAnalysesT &PA) override { + bool invalidate(TypeErasedIRUnitID IR, + const PreservedAnalysesT &PA) override { return !PA.preserved(PassT::ID()); } @@ -159,7 +166,7 @@ template struct AnalysisResultModel - : AnalysisResultConcept { + : AnalysisResultConcept { explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. @@ -176,8 +183,9 @@ } /// \brief The model delegates to the \c ResultT method. - bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA) override { - return Result.invalidate(IR, PA); + bool invalidate(TypeErasedIRUnitID IR, + const PreservedAnalysesT &PA) override { + return Result.invalidate(*(IRUnitT *)IR, PA); } ResultT Result; @@ -187,14 +195,14 @@ /// /// This concept is parameterized over the IR unit that it can run over and /// produce an analysis result. -template struct AnalysisPassConcept { +struct AnalysisPassConcept { virtual ~AnalysisPassConcept() {} /// \brief Method to run this analysis over a unit of IR. /// \returns A unique_ptr to the analysis result object to be queried by /// users. - virtual std::unique_ptr> - run(IRUnitT &IR, AnalysisManager &AM) = 0; + virtual std::unique_ptr + run(TypeErasedIRUnitID IR, AnalysisManager &AM) = 0; /// \brief Polymorphic method to access the name of a pass. virtual StringRef name() = 0; @@ -203,10 +211,10 @@ /// \brief Wrapper to model the analysis pass concept. /// /// Can wrap any type which implements a suitable \c run method. The method -/// must accept an \c IRUnitT& and an \c AnalysisManager& as arguments +/// must accept an \c IRUnitT& and an \c AnalysisManager& as arguments /// and produce an object which can be wrapped in a \c AnalysisResultModel. template -struct AnalysisPassModel : AnalysisPassConcept { +struct AnalysisPassModel : AnalysisPassConcept { explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. @@ -228,9 +236,9 @@ /// \brief The model delegates to the \c PassT::run method. /// /// The return is wrapped in an \c AnalysisResultModel. - std::unique_ptr> - run(IRUnitT &IR, AnalysisManager &AM) override { - return make_unique(Pass.run(IR, AM)); + std::unique_ptr run(TypeErasedIRUnitID IR, + AnalysisManager &AM) override { + return make_unique(Pass.run(*(IRUnitT *)IR, AM)); } /// \brief The model delegates to a static \c PassT::name method. Index: include/llvm/Passes/PassBuilder.h =================================================================== --- include/llvm/Passes/PassBuilder.h +++ include/llvm/Passes/PassBuilder.h @@ -125,45 +125,36 @@ explicit PassBuilder(TargetMachine *TM = nullptr) : TM(TM) {} - /// \brief Cross register the analysis managers through their proxies. - /// - /// This is an interface that can be used to cross register each - // AnalysisManager with all the others analysis managers. - void crossRegisterProxies(LoopAnalysisManager &LAM, - FunctionAnalysisManager &FAM, - CGSCCAnalysisManager &CGAM, - ModuleAnalysisManager &MAM); - /// \brief Registers all available module analysis passes. /// - /// This is an interface that can be used to populate a \c - /// ModuleAnalysisManager with all registered module analyses. Callers can + /// This is an interface that can be used to populate an \c + /// AnalysisManager with all registered module analyses. Callers can /// still manually register any additional analyses. Callers can also /// pre-register analyses and this will not override those. - void registerModuleAnalyses(ModuleAnalysisManager &MAM); + void registerModuleAnalyses(AnalysisManager &AM); /// \brief Registers all available CGSCC analysis passes. /// - /// This is an interface that can be used to populate a \c CGSCCAnalysisManager + /// This is an interface that can be used to populate an \c AnalysisManager /// with all registered CGSCC analyses. Callers can still manually register any /// additional analyses. Callers can also pre-register analyses and this will /// not override those. - void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM); + void registerCGSCCAnalyses(AnalysisManager &AM); /// \brief Registers all available function analysis passes. /// - /// This is an interface that can be used to populate a \c - /// FunctionAnalysisManager with all registered function analyses. Callers can + /// This is an interface that can be used to populate an \c + /// AnalysisManager with all registered function analyses. Callers can /// still manually register any additional analyses. Callers can also /// pre-register analyses and this will not override those. - void registerFunctionAnalyses(FunctionAnalysisManager &FAM); + void registerFunctionAnalyses(AnalysisManager &AM); /// \brief Registers all available loop analysis passes. /// - /// This is an interface that can be used to populate a \c LoopAnalysisManager + /// This is an interface that can be used to populate an \c AnalysisManager /// with all registered loop analyses. Callers can still manually register any /// additional analyses. - void registerLoopAnalyses(LoopAnalysisManager &LAM); + void registerLoopAnalyses(AnalysisManager &AM); /// \brief Add a per-module default optimization pipeline to a pass manager. /// Index: lib/Analysis/CGSCCPassManager.cpp =================================================================== --- lib/Analysis/CGSCCPassManager.cpp +++ lib/Analysis/CGSCCPassManager.cpp @@ -11,14 +11,8 @@ using namespace llvm; -// Explicit instantiations for the core proxy templates. +// Explicit instantiations for the pass manager. namespace llvm { template class PassManager; -template class AnalysisManager; -template class InnerAnalysisManagerProxy; -template class OuterAnalysisManagerProxy; -template class InnerAnalysisManagerProxy; -template class OuterAnalysisManagerProxy; +template struct ParentIRUnitTrackingAnalysis; } Index: lib/Analysis/IVUsers.cpp =================================================================== --- lib/Analysis/IVUsers.cpp +++ lib/Analysis/IVUsers.cpp @@ -36,18 +36,16 @@ char IVUsersAnalysis::PassID; -IVUsers IVUsersAnalysis::run(Loop &L, LoopAnalysisManager &AM) { - const auto &FAM = - AM.getResult(L).getManager(); +IVUsers IVUsersAnalysis::run(Loop &L, AnalysisManager &AM) { Function *F = L.getHeader()->getParent(); - return IVUsers(&L, FAM.getCachedResult(*F), - FAM.getCachedResult(*F), - FAM.getCachedResult(*F), - FAM.getCachedResult(*F)); + return IVUsers(&L, AM.getCachedResult(*F), + AM.getCachedResult(*F), + AM.getCachedResult(*F), + AM.getCachedResult(*F)); } -PreservedAnalyses IVUsersPrinterPass::run(Loop &L, LoopAnalysisManager &AM) { +PreservedAnalyses IVUsersPrinterPass::run(Loop &L, AnalysisManager &AM) { AM.getResult(L).print(OS); return PreservedAnalyses::all(); } Index: lib/Analysis/LoopAccessAnalysis.cpp =================================================================== --- lib/Analysis/LoopAccessAnalysis.cpp +++ lib/Analysis/LoopAccessAnalysis.cpp @@ -2030,15 +2030,13 @@ char LoopAccessAnalysis::PassID; -LoopAccessInfo LoopAccessAnalysis::run(Loop &L, LoopAnalysisManager &AM) { - const FunctionAnalysisManager &FAM = - AM.getResult(L).getManager(); +LoopAccessInfo LoopAccessAnalysis::run(Loop &L, AnalysisManager &AM) { Function &F = *L.getHeader()->getParent(); - auto *SE = FAM.getCachedResult(F); - auto *TLI = FAM.getCachedResult(F); - auto *AA = FAM.getCachedResult(F); - auto *DT = FAM.getCachedResult(F); - auto *LI = FAM.getCachedResult(F); + auto *SE = AM.getCachedResult(F); + auto *TLI = AM.getCachedResult(F); + auto *AA = AM.getCachedResult(F); + auto *DT = AM.getCachedResult(F); + auto *LI = AM.getCachedResult(F); if (!SE) report_fatal_error( "ScalarEvolution must have been cached at a higher level"); Index: lib/Analysis/LoopInfo.cpp =================================================================== --- lib/Analysis/LoopInfo.cpp +++ lib/Analysis/LoopInfo.cpp @@ -673,7 +673,7 @@ PrintLoopPass::PrintLoopPass(raw_ostream &OS, const std::string &Banner) : OS(OS), Banner(Banner) {} -PreservedAnalyses PrintLoopPass::run(Loop &L, AnalysisManager &) { +PreservedAnalyses PrintLoopPass::run(Loop &L, AnalysisManager &) { OS << Banner; for (auto *Block : L.blocks()) if (Block) Index: lib/Analysis/LoopPassManager.cpp =================================================================== --- lib/Analysis/LoopPassManager.cpp +++ lib/Analysis/LoopPassManager.cpp @@ -20,9 +20,7 @@ // Explicit instantiations for core typedef'ed templates. namespace llvm { template class PassManager; -template class AnalysisManager; -template class InnerAnalysisManagerProxy; -template class OuterAnalysisManagerProxy; +template struct ParentIRUnitTrackingAnalysis; } PreservedAnalyses llvm::getLoopPassPreservedAnalyses() { Index: lib/IR/PassManager.cpp =================================================================== --- lib/IR/PassManager.cpp +++ lib/IR/PassManager.cpp @@ -17,8 +17,7 @@ namespace llvm { template class PassManager; template class PassManager; -template class AnalysisManager; -template class AnalysisManager; -template class InnerAnalysisManagerProxy; -template class OuterAnalysisManagerProxy; + +template struct ParentIRUnitTrackingAnalysis; +template struct ParentIRUnitTrackingAnalysis; } Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -219,27 +219,27 @@ } // End anonymous namespace. -void PassBuilder::registerModuleAnalyses(ModuleAnalysisManager &MAM) { +void PassBuilder::registerModuleAnalyses(AnalysisManager &AM) { #define MODULE_ANALYSIS(NAME, CREATE_PASS) \ - MAM.registerPass([&] { return CREATE_PASS; }); + AM.registerPass([&] { return CREATE_PASS; }); #include "PassRegistry.def" } -void PassBuilder::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) { +void PassBuilder::registerCGSCCAnalyses(AnalysisManager &AM) { #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ - CGAM.registerPass([&] { return CREATE_PASS; }); + AM.registerPass([&] { return CREATE_PASS; }); #include "PassRegistry.def" } -void PassBuilder::registerFunctionAnalyses(FunctionAnalysisManager &FAM) { +void PassBuilder::registerFunctionAnalyses(AnalysisManager &AM) { #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ - FAM.registerPass([&] { return CREATE_PASS; }); + AM.registerPass([&] { return CREATE_PASS; }); #include "PassRegistry.def" } -void PassBuilder::registerLoopAnalyses(LoopAnalysisManager &LAM) { +void PassBuilder::registerLoopAnalyses(AnalysisManager &AM) { #define LOOP_ANALYSIS(NAME, CREATE_PASS) \ - LAM.registerPass([&] { return CREATE_PASS; }); + AM.registerPass([&] { return CREATE_PASS; }); #include "PassRegistry.def" } @@ -751,20 +751,6 @@ return true; } -void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM, - FunctionAnalysisManager &FAM, - CGSCCAnalysisManager &CGAM, - ModuleAnalysisManager &MAM) { - MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); - MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); }); - CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(FAM); }); - CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); }); - FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); }); - FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); - FAM.registerPass([&] { return LoopAnalysisManagerFunctionProxy(LAM); }); - LAM.registerPass([&] { return FunctionAnalysisManagerLoopProxy(FAM); }); -} - bool PassBuilder::parseModulePassPipeline(ModulePassManager &MPM, ArrayRef Pipeline, bool VerifyEachPass, Index: lib/Passes/PassRegistry.def =================================================================== --- lib/Passes/PassRegistry.def +++ lib/Passes/PassRegistry.def @@ -24,6 +24,8 @@ MODULE_ANALYSIS("no-op-module", NoOpModuleAnalysis()) MODULE_ANALYSIS("profile-summary", ProfileSummaryAnalysis()) MODULE_ANALYSIS("targetlibinfo", TargetLibraryAnalysis()) +MODULE_ANALYSIS("parent-irunit-tracking", + ParentIRUnitTrackingAnalysis()) MODULE_ANALYSIS("verify", VerifierAnalysis()) #ifndef MODULE_ALIAS_ANALYSIS @@ -75,6 +77,8 @@ #define CGSCC_ANALYSIS(NAME, CREATE_PASS) #endif CGSCC_ANALYSIS("no-op-cgscc", NoOpCGSCCAnalysis()) +CGSCC_ANALYSIS("parent-irunit-tracking", + ParentIRUnitTrackingAnalysis()) #undef CGSCC_ANALYSIS #ifndef CGSCC_PASS @@ -109,6 +113,8 @@ FUNCTION_ANALYSIS("targetir", TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis()) FUNCTION_ANALYSIS("verify", VerifierAnalysis()) +FUNCTION_ANALYSIS("parent-irunit-tracking", + ParentIRUnitTrackingAnalysis()) #ifndef FUNCTION_ALIAS_ANALYSIS #define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ @@ -192,6 +198,7 @@ LOOP_ANALYSIS("no-op-loop", NoOpLoopAnalysis()) LOOP_ANALYSIS("access-info", LoopAccessAnalysis()) LOOP_ANALYSIS("ivusers", IVUsersAnalysis()) +LOOP_ANALYSIS("parent-irunit-tracking", ParentIRUnitTrackingAnalysis()) #undef LOOP_ANALYSIS #ifndef LOOP_PASS Index: lib/Transforms/IPO/FunctionAttrs.cpp =================================================================== --- lib/Transforms/IPO/FunctionAttrs.cpp +++ lib/Transforms/IPO/FunctionAttrs.cpp @@ -1035,14 +1035,11 @@ } PreservedAnalyses PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C, - CGSCCAnalysisManager &AM) { - FunctionAnalysisManager &FAM = - AM.getResult(C).getManager(); - + AnalysisManager &AM) { // We pass a lambda into functions to wire them up to the analysis manager // for getting function analyses. auto AARGetter = [&](Function &F) -> AAResults & { - return FAM.getResult(F); + return AM.getResult(F); }; // Fill SCCNodes with the elements of the SCC. Also track whether there are Index: lib/Transforms/IPO/GlobalOpt.cpp =================================================================== --- lib/Transforms/IPO/GlobalOpt.cpp +++ lib/Transforms/IPO/GlobalOpt.cpp @@ -2565,13 +2565,11 @@ return Changed; } -PreservedAnalyses GlobalOptPass::run(Module &M, ModuleAnalysisManager &AM) { +PreservedAnalyses GlobalOptPass::run(Module &M, AnalysisManager &AM) { auto &DL = M.getDataLayout(); auto &TLI = AM.getResult(M); - auto &FAM = - AM.getResult(M).getManager(); - auto LookupDomTree = [&FAM](Function &F) -> DominatorTree &{ - return FAM.getResult(F); + auto LookupDomTree = [&AM](Function &F) -> DominatorTree & { + return AM.getResult(F); }; if (!optimizeGlobalsInModule(M, DL, &TLI, LookupDomTree)) return PreservedAnalyses::all(); Index: lib/Transforms/IPO/PartialInlining.cpp =================================================================== --- lib/Transforms/IPO/PartialInlining.cpp +++ lib/Transforms/IPO/PartialInlining.cpp @@ -210,12 +210,10 @@ return new PartialInlinerLegacyPass(); } -PreservedAnalyses PartialInlinerPass::run(Module &M, - ModuleAnalysisManager &AM) { - auto &FAM = AM.getResult(M).getManager(); +PreservedAnalyses PartialInlinerPass::run(Module &M, AnalysisManager &AM) { std::function GetAssumptionCache = - [&FAM](Function &F) -> AssumptionCache & { - return FAM.getResult(F); + [&](Function &F) -> AssumptionCache & { + return AM.getResult(F); }; InlineFunctionInfo IFI(nullptr, &GetAssumptionCache); if (PartialInlinerImpl(IFI).run(M)) Index: lib/Transforms/Instrumentation/PGOInstrumentation.cpp =================================================================== --- lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -964,15 +964,13 @@ } PreservedAnalyses PGOInstrumentationGen::run(Module &M, - ModuleAnalysisManager &AM) { - - auto &FAM = AM.getResult(M).getManager(); - auto LookupBPI = [&FAM](Function &F) { - return &FAM.getResult(F); + AnalysisManager &AM) { + auto LookupBPI = [&AM](Function &F) { + return &AM.getResult(F); }; - auto LookupBFI = [&FAM](Function &F) { - return &FAM.getResult(F); + auto LookupBFI = [&AM](Function &F) { + return &AM.getResult(F); }; if (!InstrumentAllFunctions(M, LookupBPI, LookupBFI)) @@ -1056,15 +1054,13 @@ } PreservedAnalyses PGOInstrumentationUse::run(Module &M, - ModuleAnalysisManager &AM) { - - auto &FAM = AM.getResult(M).getManager(); - auto LookupBPI = [&FAM](Function &F) { - return &FAM.getResult(F); + AnalysisManager &AM) { + auto LookupBPI = [&AM](Function &F) { + return &AM.getResult(F); }; - auto LookupBFI = [&FAM](Function &F) { - return &FAM.getResult(F); + auto LookupBFI = [&AM](Function &F) { + return &AM.getResult(F); }; if (!annotateAllFunctions(M, ProfileFileName, LookupBPI, LookupBFI)) Index: lib/Transforms/Scalar/IndVarSimplify.cpp =================================================================== --- lib/Transforms/Scalar/IndVarSimplify.cpp +++ lib/Transforms/Scalar/IndVarSimplify.cpp @@ -2213,21 +2213,20 @@ return Changed; } -PreservedAnalyses IndVarSimplifyPass::run(Loop &L, LoopAnalysisManager &AM) { - auto &FAM = AM.getResult(L).getManager(); +PreservedAnalyses IndVarSimplifyPass::run(Loop &L, AnalysisManager &AM) { Function *F = L.getHeader()->getParent(); const DataLayout &DL = F->getParent()->getDataLayout(); - auto *LI = FAM.getCachedResult(*F); - auto *SE = FAM.getCachedResult(*F); - auto *DT = FAM.getCachedResult(*F); + auto *LI = AM.getCachedResult(*F); + auto *SE = AM.getCachedResult(*F); + auto *DT = AM.getCachedResult(*F); assert((LI && SE && DT) && "Analyses required for indvarsimplify not available!"); // Optional analyses. - auto *TTI = FAM.getCachedResult(*F); - auto *TLI = FAM.getCachedResult(*F); + auto *TTI = AM.getCachedResult(*F); + auto *TLI = AM.getCachedResult(*F); IndVarSimplify IVS(LI, SE, DT, DL, TLI, TTI); if (!IVS.run(&L)) Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -173,16 +173,14 @@ }; } -PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM) { - const auto &FAM = - AM.getResult(L).getManager(); +PreservedAnalyses LICMPass::run(Loop &L, AnalysisManager &AM) { Function *F = L.getHeader()->getParent(); - auto *AA = FAM.getCachedResult(*F); - auto *LI = FAM.getCachedResult(*F); - auto *DT = FAM.getCachedResult(*F); - auto *TLI = FAM.getCachedResult(*F); - auto *SE = FAM.getCachedResult(*F); + auto *AA = AM.getCachedResult(*F); + auto *LI = AM.getCachedResult(*F); + auto *DT = AM.getCachedResult(*F); + auto *TLI = AM.getCachedResult(*F); + auto *SE = AM.getCachedResult(*F); assert((AA && LI && DT && TLI && SE) && "Analyses for LICM not available"); LoopInvariantCodeMotion LICM; Index: lib/Transforms/Scalar/LoopDeletion.cpp =================================================================== --- lib/Transforms/Scalar/LoopDeletion.cpp +++ lib/Transforms/Scalar/LoopDeletion.cpp @@ -215,13 +215,12 @@ return Changed; } -PreservedAnalyses LoopDeletionPass::run(Loop &L, LoopAnalysisManager &AM) { - auto &FAM = AM.getResult(L).getManager(); +PreservedAnalyses LoopDeletionPass::run(Loop &L, AnalysisManager &AM) { Function *F = L.getHeader()->getParent(); - auto &DT = *FAM.getCachedResult(*F); - auto &SE = *FAM.getCachedResult(*F); - auto &LI = *FAM.getCachedResult(*F); + auto &DT = *AM.getCachedResult(*F); + auto &SE = *AM.getCachedResult(*F); + auto &LI = *AM.getCachedResult(*F); bool Changed = runImpl(&L, DT, SE, LI); if (!Changed) Index: lib/Transforms/Scalar/LoopDistribute.cpp =================================================================== --- lib/Transforms/Scalar/LoopDistribute.cpp +++ lib/Transforms/Scalar/LoopDistribute.cpp @@ -955,10 +955,9 @@ auto &SE = AM.getResult(F); auto &ORE = AM.getResult(F); - auto &LAM = AM.getResult(F).getManager(); std::function GetLAA = [&](Loop &L) -> const LoopAccessInfo & { - return LAM.getResult(L); + return AM.getResult(L); }; bool Changed = runImpl(F, &LI, &DT, &SE, &ORE, GetLAA, ProcessAllLoops); Index: lib/Transforms/Scalar/LoopIdiomRecognize.cpp =================================================================== --- lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -172,18 +172,16 @@ } // End anonymous namespace. PreservedAnalyses LoopIdiomRecognizePass::run(Loop &L, - LoopAnalysisManager &AM) { - const auto &FAM = - AM.getResult(L).getManager(); + AnalysisManager &AM) { Function *F = L.getHeader()->getParent(); // Use getCachedResult because Loop pass cannot trigger a function analysis. - auto *AA = FAM.getCachedResult(*F); - auto *DT = FAM.getCachedResult(*F); - auto *LI = FAM.getCachedResult(*F); - auto *SE = FAM.getCachedResult(*F); - auto *TLI = FAM.getCachedResult(*F); - const auto *TTI = FAM.getCachedResult(*F); + auto *AA = AM.getCachedResult(*F); + auto *DT = AM.getCachedResult(*F); + auto *LI = AM.getCachedResult(*F); + auto *SE = AM.getCachedResult(*F); + auto *TLI = AM.getCachedResult(*F); + const auto *TTI = AM.getCachedResult(*F); const auto *DL = &L.getHeader()->getModule()->getDataLayout(); assert((AA && DT && LI && SE && TLI && TTI && DL) && "Analyses for Loop Idiom Recognition not available"); Index: lib/Transforms/Scalar/LoopInstSimplify.cpp =================================================================== --- lib/Transforms/Scalar/LoopInstSimplify.cpp +++ lib/Transforms/Scalar/LoopInstSimplify.cpp @@ -184,16 +184,14 @@ } PreservedAnalyses LoopInstSimplifyPass::run(Loop &L, - LoopAnalysisManager &AM) { - const auto &FAM = - AM.getResult(L).getManager(); + AnalysisManager &AM) { Function *F = L.getHeader()->getParent(); // Use getCachedResult because Loop pass cannot trigger a function analysis. - auto *DT = FAM.getCachedResult(*F); - auto *LI = FAM.getCachedResult(*F); - auto *AC = FAM.getCachedResult(*F); - const auto *TLI = FAM.getCachedResult(*F); + auto *DT = AM.getCachedResult(*F); + auto *LI = AM.getCachedResult(*F); + auto *AC = AM.getCachedResult(*F); + const auto *TLI = AM.getCachedResult(*F); assert((LI && AC && TLI) && "Analyses for Loop Inst Simplify not available"); if (!SimplifyLoopInst(&L, DT, LI, AC, TLI)) Index: lib/Transforms/Scalar/LoopRotation.cpp =================================================================== --- lib/Transforms/Scalar/LoopRotation.cpp +++ lib/Transforms/Scalar/LoopRotation.cpp @@ -619,18 +619,17 @@ LoopRotatePass::LoopRotatePass() {} -PreservedAnalyses LoopRotatePass::run(Loop &L, LoopAnalysisManager &AM) { - auto &FAM = AM.getResult(L).getManager(); +PreservedAnalyses LoopRotatePass::run(Loop &L, AnalysisManager &AM) { Function *F = L.getHeader()->getParent(); - auto *LI = FAM.getCachedResult(*F); - const auto *TTI = FAM.getCachedResult(*F); - auto *AC = FAM.getCachedResult(*F); + auto *LI = AM.getCachedResult(*F); + const auto *TTI = AM.getCachedResult(*F); + auto *AC = AM.getCachedResult(*F); assert((LI && TTI && AC) && "Analyses for loop rotation not available"); // Optional analyses. - auto *DT = FAM.getCachedResult(*F); - auto *SE = FAM.getCachedResult(*F); + auto *DT = AM.getCachedResult(*F); + auto *SE = AM.getCachedResult(*F); LoopRotate LR(DefaultRotationThreshold, LI, TTI, AC, DT, SE); bool Changed = LR.processLoop(&L); Index: lib/Transforms/Scalar/LoopSimplifyCFG.cpp =================================================================== --- lib/Transforms/Scalar/LoopSimplifyCFG.cpp +++ lib/Transforms/Scalar/LoopSimplifyCFG.cpp @@ -64,13 +64,11 @@ return Changed; } -PreservedAnalyses LoopSimplifyCFGPass::run(Loop &L, LoopAnalysisManager &AM) { - const auto &FAM = - AM.getResult(L).getManager(); +PreservedAnalyses LoopSimplifyCFGPass::run(Loop &L, AnalysisManager &AM) { Function *F = L.getHeader()->getParent(); - auto *LI = FAM.getCachedResult(*F); - auto *DT = FAM.getCachedResult(*F); + auto *LI = AM.getCachedResult(*F); + auto *DT = AM.getCachedResult(*F); assert((LI && DT) && "Analyses for LoopSimplifyCFG not available"); if (!simplifyLoopCFG(L, *DT, *LI)) Index: lib/Transforms/Scalar/LoopStrengthReduce.cpp =================================================================== --- lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -5023,16 +5023,14 @@ } PreservedAnalyses LoopStrengthReducePass::run(Loop &L, - LoopAnalysisManager &AM) { - const auto &FAM = - AM.getResult(L).getManager(); + AnalysisManager &AM) { Function *F = L.getHeader()->getParent(); auto &IU = AM.getResult(L); - auto *SE = FAM.getCachedResult(*F); - auto *DT = FAM.getCachedResult(*F); - auto *LI = FAM.getCachedResult(*F); - auto *TTI = FAM.getCachedResult(*F); + auto *SE = AM.getCachedResult(*F); + auto *DT = AM.getCachedResult(*F); + auto *LI = AM.getCachedResult(*F); + auto *TTI = AM.getCachedResult(*F); assert((SE && DT && LI && TTI) && "Analyses for Loop Strength Reduce not available"); Index: lib/Transforms/Scalar/LoopUnrollPass.cpp =================================================================== --- lib/Transforms/Scalar/LoopUnrollPass.cpp +++ lib/Transforms/Scalar/LoopUnrollPass.cpp @@ -1058,18 +1058,16 @@ return llvm::createLoopUnrollPass(-1, -1, 0, 0); } -PreservedAnalyses LoopUnrollPass::run(Loop &L, LoopAnalysisManager &AM) { - const auto &FAM = - AM.getResult(L).getManager(); +PreservedAnalyses LoopUnrollPass::run(Loop &L, AnalysisManager &AM) { Function *F = L.getHeader()->getParent(); - DominatorTree *DT = FAM.getCachedResult(*F); - LoopInfo *LI = FAM.getCachedResult(*F); - ScalarEvolution *SE = FAM.getCachedResult(*F); - auto *TTI = FAM.getCachedResult(*F); - auto *AC = FAM.getCachedResult(*F); - auto *ORE = FAM.getCachedResult(*F); + DominatorTree *DT = AM.getCachedResult(*F); + LoopInfo *LI = AM.getCachedResult(*F); + ScalarEvolution *SE = AM.getCachedResult(*F); + auto *TTI = AM.getCachedResult(*F); + auto *AC = AM.getCachedResult(*F); + auto *ORE = AM.getCachedResult(*F); if (!DT) report_fatal_error("LoopUnrollPass: DominatorTreeAnalysis not cached at a higher level"); if (!LI) Index: lib/Transforms/Vectorize/LoopVectorize.cpp =================================================================== --- lib/Transforms/Vectorize/LoopVectorize.cpp +++ lib/Transforms/Vectorize/LoopVectorize.cpp @@ -6829,10 +6829,9 @@ auto &DB = AM.getResult(F); auto &ORE = AM.getResult(F); - auto &LAM = AM.getResult(F).getManager(); std::function GetLAA = [&](Loop &L) -> const LoopAccessInfo & { - return LAM.getResult(L); + return AM.getResult(L); }; bool Changed = runImpl(F, SE, LI, TTI, DT, BFI, TLI, DB, AA, AC, GetLAA, ORE); Index: test/Other/analysis-manager/transitive-invalidation.ll =================================================================== --- /dev/null +++ test/Other/analysis-manager/transitive-invalidation.ll @@ -0,0 +1,30 @@ +; RUN: opt '-passes=require,invalidate' -aa-pipeline=basic-aa \ +; RUN: -debug-pass-manager -disable-output < %s 2>&1 | FileCheck %s + +; CHECK: Running pass: InvalidateAnalysisPass +; CHECK-NEXT: Invalidating analysis: BasicAA +; CHECK-NEXT: Invalidating analysis: AAManager +; CHECK: Running pass: InvalidateAnalysisPass +; CHECK-NEXT: Invalidating analysis: BasicAA +; CHECK-NEXT: Invalidating analysis: AAManager + +; RUN: opt '-passes=require,function(require),invalidate' -aa-pipeline=globals-aa \ +; RUN: -debug-pass-manager -disable-output < %s 2>&1 | FileCheck %s --check-prefix=GLOBALS-AA +; GLOBALS-AA: Running pass: InvalidateAnalysisPass +; GLOBALS-AA-NEXT: Invalidating analysis: GlobalsAA +; GLOBALS-AA-NEXT: Invalidating analysis: AAManager +; GLOBALS-AA-NEXT: Invalidating analysis: AAManager + + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @foo() { +entry: + ret void +} + +define void @bar() { +entry: + ret void +} Index: test/Other/new-pass-manager.ll =================================================================== --- test/Other/new-pass-manager.ll +++ test/Other/new-pass-manager.ll @@ -20,7 +20,6 @@ ; 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: InnerAnalysisManagerProxy<{{.*}}> ; CHECK-CGSCC-PASS-NEXT: Running analysis: LazyCallGraphAnalysis ; CHECK-CGSCC-PASS-NEXT: Running an SCC pass across the RefSCC: [(foo)] ; CHECK-CGSCC-PASS-NEXT: Starting llvm::LazyCallGraph::SCC pass manager run @@ -36,7 +35,6 @@ ; 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: InnerAnalysisManagerProxy<{{.*}}> ; 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 @@ -66,7 +64,6 @@ ; 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: InnerAnalysisManagerProxy<{{.*}}> ; CHECK-FUNCTION-PRINT: Starting llvm::Function pass manager run ; CHECK-FUNCTION-PRINT: Running pass: PrintFunctionPass ; CHECK-FUNCTION-PRINT-NOT: ModuleID @@ -389,7 +386,6 @@ ; RUN: | FileCheck %s --check-prefix=CHECK-REPEAT-CGSCC-PASS ; CHECK-REPEAT-CGSCC-PASS: Starting llvm::Module pass manager run ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor -; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: LazyCallGraphAnalysis ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running an SCC pass across the RefSCC: [(foo)] ; CHECK-REPEAT-CGSCC-PASS-NEXT: Starting llvm::LazyCallGraph::SCC pass manager run @@ -411,7 +407,6 @@ ; RUN: | FileCheck %s --check-prefix=CHECK-REPEAT-FUNCTION-PASS ; CHECK-REPEAT-FUNCTION-PASS: Starting llvm::Module pass manager run ; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running pass: ModuleToFunctionPassAdaptor -; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> ; CHECK-REPEAT-FUNCTION-PASS-NEXT: Starting llvm::Function pass manager run ; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running pass: RepeatedPass ; CHECK-REPEAT-FUNCTION-PASS-NEXT: Starting llvm::Function pass manager run @@ -431,11 +426,10 @@ ; RUN: | FileCheck %s --check-prefix=CHECK-REPEAT-LOOP-PASS ; CHECK-REPEAT-LOOP-PASS: Starting llvm::Module pass manager run ; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: ModuleToFunctionPassAdaptor -; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> ; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Function pass manager run ; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: FunctionToLoopPassAdaptor -; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: LoopAnalysis +; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: ParentIRUnitTrackingAnalysis ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: DominatorTreeAnalysis ; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Loop pass manager run ; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: RepeatedPass Index: tools/opt/NewPMDriver.cpp =================================================================== --- tools/opt/NewPMDriver.cpp +++ tools/opt/NewPMDriver.cpp @@ -63,20 +63,16 @@ return false; } - LoopAnalysisManager LAM(DebugPM); - FunctionAnalysisManager FAM(DebugPM); - CGSCCAnalysisManager CGAM(DebugPM); - ModuleAnalysisManager MAM(DebugPM); + AnalysisManager AM(DebugPM); // Register the AA manager first so that our version is the one used. - FAM.registerPass([&] { return std::move(AA); }); + AM.registerPass([&] { return std::move(AA); }); // Register all the basic analyses with the managers. - PB.registerModuleAnalyses(MAM); - PB.registerCGSCCAnalyses(CGAM); - PB.registerFunctionAnalyses(FAM); - PB.registerLoopAnalyses(LAM); - PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); + PB.registerModuleAnalyses(AM); + PB.registerCGSCCAnalyses(AM); + PB.registerFunctionAnalyses(AM); + PB.registerLoopAnalyses(AM); ModulePassManager MPM(DebugPM); if (VK > VK_NoVerifier) @@ -109,7 +105,7 @@ cl::PrintOptionValues(); // Now that we have all of the passes ready, run them. - MPM.run(M, MAM); + MPM.run(M, AM); // Declare success. if (OK != OK_NoOutput) Index: unittests/Analysis/CGSCCPassManagerTest.cpp =================================================================== --- unittests/Analysis/CGSCCPassManagerTest.cpp +++ unittests/Analysis/CGSCCPassManagerTest.cpp @@ -34,7 +34,7 @@ TestModuleAnalysis(int &Runs) : Runs(Runs) {} - Result run(Module &M, ModuleAnalysisManager &AM) { + Result run(Module &M, AnalysisManager &AM) { ++Runs; return Result(M.size()); } @@ -59,7 +59,7 @@ TestSCCAnalysis(int &Runs) : Runs(Runs) {} - Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM) { + Result run(LazyCallGraph::SCC &C, AnalysisManager &AM) { ++Runs; return Result(C.size()); } @@ -84,7 +84,7 @@ TestFunctionAnalysis(int &Runs) : Runs(Runs) {} - Result run(Function &F, FunctionAnalysisManager &AM) { + Result run(Function &F, AnalysisManager &AM) { ++Runs; int Count = 0; for (Instruction &I : instructions(F)) { @@ -113,7 +113,7 @@ TestImmutableFunctionAnalysis(int &Runs) : Runs(Runs) {} - Result run(Function &F, FunctionAnalysisManager &AM) { + Result run(Function &F, AnalysisManager &AM) { ++Runs; return Result(); } @@ -129,7 +129,7 @@ struct TestModulePass { TestModulePass(int &RunCount) : RunCount(RunCount) {} - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { + PreservedAnalyses run(Module &M, AnalysisManager &AM) { ++RunCount; (void)AM.getResult(M); return PreservedAnalyses::all(); @@ -149,15 +149,11 @@ AnalyzedModuleFunctionCount(AnalyzedModuleFunctionCount), OnlyUseCachedResults(OnlyUseCachedResults) {} - PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM) { + PreservedAnalyses run(LazyCallGraph::SCC &C, AnalysisManager &AM) { ++RunCount; - const ModuleAnalysisManager &MAM = - AM.getResult(C).getManager(); - FunctionAnalysisManager &FAM = - AM.getResult(C).getManager(); if (TestModuleAnalysis::Result *TMA = - MAM.getCachedResult( + AM.getCachedResult( *C.begin()->getFunction().getParent())) AnalyzedModuleFunctionCount += TMA->FunctionCount; @@ -167,7 +163,7 @@ AnalyzedSCCFunctionCount += AR->FunctionCount; for (LazyCallGraph::Node &N : C) if (TestFunctionAnalysis::Result *FAR = - FAM.getCachedResult(N.getFunction())) + AM.getCachedResult(N.getFunction())) AnalyzedInstrCount += FAR->InstructionCount; } else { // Typical path just runs the analysis as needed. @@ -175,11 +171,11 @@ AnalyzedSCCFunctionCount += AR.FunctionCount; for (LazyCallGraph::Node &N : C) { TestFunctionAnalysis::Result &FAR = - FAM.getResult(N.getFunction()); + AM.getResult(N.getFunction()); AnalyzedInstrCount += FAR.InstructionCount; // Just ensure we get the immutable results. - (void)FAM.getResult(N.getFunction()); + (void)AM.getResult(N.getFunction()); } } @@ -198,7 +194,7 @@ struct TestFunctionPass { TestFunctionPass(int &RunCount) : RunCount(RunCount) {} - PreservedAnalyses run(Function &F, FunctionAnalysisManager &) { + PreservedAnalyses run(Function &F, AnalysisManager &) { ++RunCount; return PreservedAnalyses::none(); } @@ -250,29 +246,30 @@ "entry:\n" " ret void\n" "}\n"); - FunctionAnalysisManager FAM(/*DebugLogging*/ true); + AnalysisManager AM(/*DebugLogging*/ true); + AM.registerPass( + [&] { return ParentIRUnitTrackingAnalysis(); }); + AM.registerPass( + [&] { return ParentIRUnitTrackingAnalysis(); }); + AM.registerPass( + [&] { return ParentIRUnitTrackingAnalysis(); }); + int FunctionAnalysisRuns = 0; - FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); + AM.registerPass( + [&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); int ImmutableFunctionAnalysisRuns = 0; - FAM.registerPass([&] { + AM.registerPass([&] { return TestImmutableFunctionAnalysis(ImmutableFunctionAnalysisRuns); }); - CGSCCAnalysisManager CGAM(/*DebugLogging*/ true); int SCCAnalysisRuns = 0; - CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); + AM.registerPass( + [&] { return TestSCCAnalysis(SCCAnalysisRuns); }); - ModuleAnalysisManager MAM(/*DebugLogging*/ true); int ModuleAnalysisRuns = 0; - MAM.registerPass([&] { return LazyCallGraphAnalysis(); }); - MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); - - MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); - MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); }); - CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(FAM); }); - CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); }); - FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); }); - FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); + AM.registerPass([&] { return LazyCallGraphAnalysis(); }); + AM.registerPass( + [&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); ModulePassManager MPM(/*DebugLogging*/ true); int ModulePassRunCount1 = 0; @@ -293,7 +290,7 @@ CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); - MPM.run(*M, MAM); + MPM.run(*M, AM); EXPECT_EQ(1, ModulePassRunCount1); Index: unittests/Analysis/LoopPassManagerTest.cpp =================================================================== --- unittests/Analysis/LoopPassManagerTest.cpp +++ unittests/Analysis/LoopPassManagerTest.cpp @@ -144,20 +144,20 @@ } while (0) TEST_F(LoopPassManagerTest, Basic) { - LoopAnalysisManager LAM(true); + AnalysisManager AM(true); + AM.registerPass( + [&] { return ParentIRUnitTrackingAnalysis(); }); + AM.registerPass( + [&] { return ParentIRUnitTrackingAnalysis(); }); + AM.registerPass( + [&] { return ParentIRUnitTrackingAnalysis(); }); + int LoopAnalysisRuns = 0; - LAM.registerPass([&] { return TestLoopAnalysis(LoopAnalysisRuns); }); + AM.registerPass([&] { return TestLoopAnalysis(LoopAnalysisRuns); }); - FunctionAnalysisManager FAM(true); // We need DominatorTreeAnalysis for LoopAnalysis. - FAM.registerPass([&] { return DominatorTreeAnalysis(); }); - FAM.registerPass([&] { return LoopAnalysis(); }); - FAM.registerPass([&] { return LoopAnalysisManagerFunctionProxy(LAM); }); - LAM.registerPass([&] { return FunctionAnalysisManagerLoopProxy(FAM); }); - - ModuleAnalysisManager MAM(true); - MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); - FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); + AM.registerPass([&] { return DominatorTreeAnalysis(); }); + AM.registerPass([&] { return LoopAnalysis(); }); ModulePassManager MPM(true); FunctionPassManager FPM(true); @@ -185,7 +185,7 @@ } MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); - MPM.run(*M, MAM); + MPM.run(*M, AM); StringRef ExpectedLoops[] = {"loop.0.0", "loop.0.1", "loop.0", "loop.g.0"}; Index: unittests/IR/PassManagerTest.cpp =================================================================== --- unittests/IR/PassManagerTest.cpp +++ unittests/IR/PassManagerTest.cpp @@ -86,20 +86,20 @@ }; struct TestPreservingModulePass : PassInfoMixin { - PreservedAnalyses run(Module &M, ModuleAnalysisManager &) { + PreservedAnalyses run(Module &M, AnalysisManager &) { return PreservedAnalyses::all(); } }; struct TestMinPreservingModulePass : PassInfoMixin { - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { + PreservedAnalyses run(Module &M, AnalysisManager &AM) { PreservedAnalyses PA; // Force running an analysis. (void)AM.getResult(M); - PA.preserve(); + PA.preserve>(); return PA; } }; @@ -112,13 +112,11 @@ AnalyzedFunctionCount(AnalyzedFunctionCount), OnlyUseCachedResults(OnlyUseCachedResults) {} - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { + PreservedAnalyses run(Function &F, AnalysisManager &AM) { ++RunCount; - const ModuleAnalysisManager &MAM = - AM.getResult(F).getManager(); if (TestModuleAnalysis::Result *TMA = - MAM.getCachedResult(*F.getParent())) + AM.getCachedResult(*F.getParent())) AnalyzedFunctionCount += TMA->FunctionCount; if (OnlyUseCachedResults) { @@ -215,17 +213,19 @@ } TEST_F(PassManagerTest, Basic) { - FunctionAnalysisManager FAM; + AnalysisManager AM(true); + AM.registerPass( + [&] { return ParentIRUnitTrackingAnalysis(); }); + int FunctionAnalysisRuns = 0; - FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); + AM.registerPass( + [&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); - ModuleAnalysisManager MAM; int ModuleAnalysisRuns = 0; - MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); - MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); - FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); + AM.registerPass( + [&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); - ModulePassManager MPM; + ModulePassManager MPM(true); // Count the runs over a Function. int FunctionPassRunCount1 = 0; @@ -233,11 +233,11 @@ int AnalyzedFunctionCount1 = 0; { // Pointless scoped copy to test move assignment. - ModulePassManager NestedMPM; - FunctionPassManager FPM; + ModulePassManager NestedMPM(true); + FunctionPassManager FPM(true); { // Pointless scope to test move assignment. - FunctionPassManager NestedFPM; + FunctionPassManager NestedFPM(true); NestedFPM.addPass(TestFunctionPass( FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1)); FPM = std::move(NestedFPM); @@ -255,7 +255,7 @@ int AnalyzedInstrCount2 = 0; int AnalyzedFunctionCount2 = 0; { - FunctionPassManager FPM; + FunctionPassManager FPM(true); FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2, AnalyzedFunctionCount2)); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); @@ -268,7 +268,7 @@ int AnalyzedInstrCount3 = 0; int AnalyzedFunctionCount3 = 0; { - FunctionPassManager FPM; + FunctionPassManager FPM(true); FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3, AnalyzedFunctionCount3)); FPM.addPass(TestInvalidationFunctionPass("f")); @@ -281,7 +281,7 @@ int AnalyzedInstrCount4 = 0; int AnalyzedFunctionCount4 = 0; { - FunctionPassManager FPM; + FunctionPassManager FPM(true); FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4, AnalyzedFunctionCount4)); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); @@ -292,7 +292,7 @@ int AnalyzedInstrCount5 = 0; int AnalyzedFunctionCount5 = 0; { - FunctionPassManager FPM; + FunctionPassManager FPM(true); FPM.addPass(TestInvalidationFunctionPass("f")); FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5, AnalyzedFunctionCount5, @@ -300,7 +300,7 @@ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } - MPM.run(*M, MAM); + MPM.run(*M, AM); // Validate module pass counters. EXPECT_EQ(1, ModulePassRunCount); Index: unittests/IR/VerifierTest.cpp =================================================================== --- unittests/IR/VerifierTest.cpp +++ unittests/IR/VerifierTest.cpp @@ -192,9 +192,9 @@ ModulePassManager MPM(true); MPM.addPass(VerifierPass(false)); - ModuleAnalysisManager MAM(true); - MAM.registerPass([&] { return VerifierAnalysis(); }); - MPM.run(M, MAM); + AnalysisManager AM(true); + AM.registerPass([&] { return VerifierAnalysis(); }); + MPM.run(M, AM); EXPECT_FALSE(verifyModule(M)); } #endif