1dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines//===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===// 2dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// 3dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// The LLVM Compiler Infrastructure 4dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// 5dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// This file is distributed under the University of Illinois Open Source 6dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// License. See LICENSE.TXT for details. 7dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// 8dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines//===----------------------------------------------------------------------===// 9dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \file 10dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// 11dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// This header provides classes for managing passes over SCCs of the call 12dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// graph. These passes form an important component of LLVM's interprocedural 13dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// optimizations. Because they operate on the SCCs of the call graph, and they 14dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// wtraverse the graph in post order, they can effectively do pair-wise 15dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// interprocedural optimizations for all call edges in the program. At each 16dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// call site edge, the callee has already been optimized as much as is 17dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// possible. This in turn allows very accurate analysis of it for IPO. 18dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// 19dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines//===----------------------------------------------------------------------===// 20dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 21dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#ifndef LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H 22dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H 23dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 24dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/IR/PassManager.h" 25dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/Analysis/LazyCallGraph.h" 26dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 27dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesnamespace llvm { 28dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 29dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass CGSCCAnalysisManager; 30dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 31dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass CGSCCPassManager { 32dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinespublic: 33dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We have to explicitly define all the special member functions because MSVC 34dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // refuses to generate them. 35dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCPassManager() {} 36dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {} 37dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCPassManager &operator=(CGSCCPassManager &&RHS) { 38dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Passes = std::move(RHS.Passes); 39dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 40dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 41dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Run all of the CGSCC passes in this pass manager over a SCC. 43dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PreservedAnalyses run(LazyCallGraph::SCC *C, 44dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManager *AM = nullptr); 45dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 46dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines template <typename CGSCCPassT> void addPass(CGSCCPassT Pass) { 47dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Passes.emplace_back(new CGSCCPassModel<CGSCCPassT>(std::move(Pass))); 48dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 49dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 50dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static StringRef name() { return "CGSCCPassManager"; } 51dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 52dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesprivate: 53dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Pull in the concept type and model template specialized for SCCs. 54dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines typedef detail::PassConcept<LazyCallGraph::SCC *, CGSCCAnalysisManager> 55dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCPassConcept; 56dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines template <typename PassT> 57dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines struct CGSCCPassModel 58dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT> { 59dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCPassModel(PassT Pass) 60dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT>( 61dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::move(Pass)) {} 62dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines }; 63dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 64dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; 65dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; 66dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 67dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::vector<std::unique_ptr<CGSCCPassConcept>> Passes; 68dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}; 69dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 70dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \brief A function analysis manager to coordinate and cache analyses run over 71dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// a module. 72dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass CGSCCAnalysisManager : public detail::AnalysisManagerBase< 73dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManager, LazyCallGraph::SCC *> { 74dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines friend class detail::AnalysisManagerBase<CGSCCAnalysisManager, 75dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LazyCallGraph::SCC *>; 76dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines typedef detail::AnalysisManagerBase<CGSCCAnalysisManager, 77dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LazyCallGraph::SCC *> BaseT; 78dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines typedef BaseT::ResultConceptT ResultConceptT; 79dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines typedef BaseT::PassConceptT PassConceptT; 80dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 81dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinespublic: 82dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Most public APIs are inherited from the CRTP base class. 83dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 84dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We have to explicitly define all the special member functions because MSVC 85dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // refuses to generate them. 86dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManager() {} 87dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManager(CGSCCAnalysisManager &&Arg) 88dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : BaseT(std::move(static_cast<BaseT &>(Arg))), 89dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {} 90dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) { 91dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); 92dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisResults = std::move(RHS.CGSCCAnalysisResults); 93dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 94dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 95dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 96dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Returns true if the analysis manager has an empty results cache. 97dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines bool empty() const; 98dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 99dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Clear the function analysis result cache. 100dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// 101dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// This routine allows cleaning up when the set of functions itself has 102dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// potentially changed, and thus we can't even look up a a result and 103dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// invalidate it directly. Notably, this does *not* call invalidate 104dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// functions as there is nothing to be done for them. 105dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines void clear(); 106dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 107dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesprivate: 108dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManager(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; 109dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManager & 110dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines operator=(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; 111dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 112dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Get a function pass result, running the pass if necessary. 113dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ResultConceptT &getResultImpl(void *PassID, LazyCallGraph::SCC *C); 114dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 115dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Get a cached function pass result or return null. 116dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ResultConceptT *getCachedResultImpl(void *PassID, 117dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LazyCallGraph::SCC *C) const; 118dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 119dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Invalidate a function pass result. 120dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines void invalidateImpl(void *PassID, LazyCallGraph::SCC *C); 121dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 122dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Invalidate the results for a function.. 123dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines void invalidateImpl(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); 124dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 125dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief List of function analysis pass IDs and associated concept pointers. 126dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// 127dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// Requires iterators to be valid across appending new entries and arbitrary 128dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// erases. Provides both the pass ID and concept pointer such that it is 129dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// half of a bijection and provides storage for the actual result concept. 130dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines typedef std::list< 131dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::pair<void *, std::unique_ptr<detail::AnalysisResultConcept< 132dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LazyCallGraph::SCC *>>>> CGSCCAnalysisResultListT; 133dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 134dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Map type from function pointer to our custom list type. 135dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines typedef DenseMap<LazyCallGraph::SCC *, CGSCCAnalysisResultListT> 136dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisResultListMapT; 137dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 138dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Map from function to a list of function analysis results. 139dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// 140dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// Provides linear time removal of all analysis results for a function and 141dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// the ultimate storage for a particular cached analysis result. 142dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisResultListMapT CGSCCAnalysisResultLists; 143dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 144dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Map type from a pair of analysis ID and function pointer to an 145dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// iterator into a particular result list. 146dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines typedef DenseMap<std::pair<void *, LazyCallGraph::SCC *>, 147dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisResultListT::iterator> CGSCCAnalysisResultMapT; 148dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 149dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Map from an analysis ID and function to a particular cached 150dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// analysis result. 151dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisResultMapT CGSCCAnalysisResults; 152dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}; 153dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 154dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \brief A module analysis which acts as a proxy for a CGSCC analysis 155dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// manager. 156dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// 157dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// This primarily proxies invalidation information from the module analysis 158dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// manager and module pass manager to a CGSCC analysis manager. You should 159dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// never use a CGSCC analysis manager from within (transitively) a module 160dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// pass manager unless your parent module pass has received a proxy result 161dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// object for it. 162dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass CGSCCAnalysisManagerModuleProxy { 163dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinespublic: 164dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines class Result { 165dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines public: 166dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} 167dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We have to explicitly define all the special member functions because 168dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // MSVC refuses to generate them. 169dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result(const Result &Arg) : CGAM(Arg.CGAM) {} 170dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {} 171dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result &operator=(Result RHS) { 172dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::swap(CGAM, RHS.CGAM); 173dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 174dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 175dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ~Result(); 176dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 177dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Accessor for the \c CGSCCAnalysisManager. 178dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManager &getManager() { return *CGAM; } 179dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 180dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Handler for invalidation of the module. 181dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// 182dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// If this analysis itself is preserved, then we assume that the call 183dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// graph of the module hasn't changed and thus we don't need to invalidate 184dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// *all* cached data associated with a \c SCC* in the \c 185dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// CGSCCAnalysisManager. 186dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// 187dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// Regardless of whether this analysis is marked as preserved, all of the 188dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// analyses in the \c CGSCCAnalysisManager are potentially invalidated 189dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// based on the set of preserved analyses. 190dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines bool invalidate(Module *M, const PreservedAnalyses &PA); 191dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 192dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines private: 193dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManager *CGAM; 194dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines }; 195dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 196dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static void *ID() { return (void *)&PassID; } 197dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 198dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM) 199dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : CGAM(&CGAM) {} 200dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We have to explicitly define all the special member functions because MSVC 201dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // refuses to generate them. 202dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManagerModuleProxy( 203dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const CGSCCAnalysisManagerModuleProxy &Arg) 204dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : CGAM(Arg.CGAM) {} 205dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg) 206dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : CGAM(std::move(Arg.CGAM)) {} 207dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManagerModuleProxy & 208dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines operator=(CGSCCAnalysisManagerModuleProxy RHS) { 209dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::swap(CGAM, RHS.CGAM); 210dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 211dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 212dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 213dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Run the analysis pass and create our proxy result object. 214dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// 215dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// This doesn't do any interesting work, it is primarily used to insert our 216dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// proxy result object into the module analysis cache so that we can proxy 217dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// invalidation to the CGSCC analysis manager. 218dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// 219dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// In debug builds, it will also assert that the analysis manager is empty 220dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// as no queries should arrive at the CGSCC analysis manager prior to 221dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// this analysis being requested. 222dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result run(Module *M); 223dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 224dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesprivate: 225dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static char PassID; 226dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 227dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManager *CGAM; 228dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}; 229dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 230dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \brief A CGSCC analysis which acts as a proxy for a module analysis 231dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// manager. 232dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// 233dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// This primarily provides an accessor to a parent module analysis manager to 234dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// CGSCC passes. Only the const interface of the module analysis manager is 235dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// provided to indicate that once inside of a CGSCC analysis pass you 236dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// cannot request a module analysis to actually run. Instead, the user must 237dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// rely on the \c getCachedResult API. 238dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// 239dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// This proxy *doesn't* manage the invalidation in any way. That is handled by 240dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// the recursive return path of each layer of the pass manager and the 241dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// returned PreservedAnalysis set. 242dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass ModuleAnalysisManagerCGSCCProxy { 243dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinespublic: 244dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy. 245dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines class Result { 246dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines public: 247dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} 248dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We have to explicitly define all the special member functions because 249dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // MSVC refuses to generate them. 250dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result(const Result &Arg) : MAM(Arg.MAM) {} 251dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {} 252dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result &operator=(Result RHS) { 253dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::swap(MAM, RHS.MAM); 254dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 255dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 256dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 257dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const ModuleAnalysisManager &getManager() const { return *MAM; } 258dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 259dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Handle invalidation by ignoring it, this pass is immutable. 260dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines bool invalidate(LazyCallGraph::SCC *) { return false; } 261dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 262dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines private: 263dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const ModuleAnalysisManager *MAM; 264dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines }; 265dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 266dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static void *ID() { return (void *)&PassID; } 267dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 268dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM) 269dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : MAM(&MAM) {} 270dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We have to explicitly define all the special member functions because MSVC 271dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // refuses to generate them. 272dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ModuleAnalysisManagerCGSCCProxy( 273dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const ModuleAnalysisManagerCGSCCProxy &Arg) 274dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : MAM(Arg.MAM) {} 275dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg) 276dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : MAM(std::move(Arg.MAM)) {} 277dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ModuleAnalysisManagerCGSCCProxy & 278dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines operator=(ModuleAnalysisManagerCGSCCProxy RHS) { 279dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::swap(MAM, RHS.MAM); 280dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 281dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 282dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 283dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Run the analysis pass and create our proxy result object. 284dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// Nothing to see here, it just forwards the \c MAM reference into the 285dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// result. 286dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result run(LazyCallGraph::SCC *) { return Result(*MAM); } 287dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 288dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesprivate: 289dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static char PassID; 290dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 291dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const ModuleAnalysisManager *MAM; 292dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}; 293dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 294dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \brief The core module pass which does a post-order walk of the SCCs and 295dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// runs a CGSCC pass over each one. 296dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// 297dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// Designed to allow composition of a CGSCCPass(Manager) and 298dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// a ModulePassManager. Note that this pass must be run with a module analysis 299dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// manager as it uses the LazyCallGraph analysis. It will also run the 300dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC 301dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// pass over the module to enable a \c FunctionAnalysisManager to be used 302dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// within this run safely. 303dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinestemplate <typename CGSCCPassT> class ModuleToPostOrderCGSCCPassAdaptor { 304dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinespublic: 305dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) 306dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : Pass(std::move(Pass)) {} 307dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We have to explicitly define all the special member functions because MSVC 308dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // refuses to generate them. 309dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ModuleToPostOrderCGSCCPassAdaptor( 310dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const ModuleToPostOrderCGSCCPassAdaptor &Arg) 311dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : Pass(Arg.Pass) {} 312dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg) 313dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : Pass(std::move(Arg.Pass)) {} 314dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS, 315dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ModuleToPostOrderCGSCCPassAdaptor &RHS) { 316dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines using std::swap; 317dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines swap(LHS.Pass, RHS.Pass); 318dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 319dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ModuleToPostOrderCGSCCPassAdaptor & 320dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) { 321dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines swap(*this, RHS); 322dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 323dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 324dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 325dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Runs the CGSCC pass across every SCC in the module. 326dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { 327dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines assert(AM && "We need analyses to compute the call graph!"); 328dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 329dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Setup the CGSCC analysis manager from its proxy. 330dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManager &CGAM = 331dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines AM->getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager(); 332dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 333dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Get the call graph for this module. 334dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LazyCallGraph &CG = AM->getResult<LazyCallGraphAnalysis>(M); 335dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 336dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PreservedAnalyses PA = PreservedAnalyses::all(); 337dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines for (LazyCallGraph::SCC &C : CG.postorder_sccs()) { 338dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PreservedAnalyses PassPA = Pass.run(&C, &CGAM); 339dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 340dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We know that the CGSCC pass couldn't have invalidated any other 341dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // SCC's analyses (that's the contract of a CGSCC pass), so 342dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // directly handle the CGSCC analysis manager's invalidation here. 343dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // FIXME: This isn't quite correct. We need to handle the case where the 344dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // pass updated the CG, particularly some child of the current SCC, and 345dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // invalidate its analyses. 346dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGAM.invalidate(&C, PassPA); 347dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 348dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Then intersect the preserved set so that invalidation of module 349dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // analyses will eventually occur when the module pass completes. 350dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PA.intersect(std::move(PassPA)); 351dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 352dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 353dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // By definition we preserve the proxy. This precludes *any* invalidation 354dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // of CGSCC analyses by the proxy, but that's OK because we've taken 355dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // care to invalidate analyses in the CGSCC analysis manager 356dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // incrementally above. 357dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PA.preserve<CGSCCAnalysisManagerModuleProxy>(); 358dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return PA; 359dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 360dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 361dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static StringRef name() { return "ModuleToPostOrderCGSCCPassAdaptor"; } 362dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 363dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesprivate: 364dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCPassT Pass; 365dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}; 366dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 367dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \brief A function to deduce a function pass type and wrap it in the 368dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// templated adaptor. 369dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinestemplate <typename CGSCCPassT> 370dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT> 371dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinescreateModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) { 372dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return std::move( 373dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass))); 374dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} 375dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 376dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \brief A CGSCC analysis which acts as a proxy for a function analysis 377dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// manager. 378dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// 379dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// This primarily proxies invalidation information from the CGSCC analysis 380dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// manager and CGSCC pass manager to a function analysis manager. You should 381dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// never use a function analysis manager from within (transitively) a CGSCC 382dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// pass manager unless your parent CGSCC pass has received a proxy result 383dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// object for it. 384dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass FunctionAnalysisManagerCGSCCProxy { 385dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinespublic: 386dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines class Result { 387dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines public: 388dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {} 389dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We have to explicitly define all the special member functions because 390dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // MSVC refuses to generate them. 391dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result(const Result &Arg) : FAM(Arg.FAM) {} 392dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {} 393dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result &operator=(Result RHS) { 394dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::swap(FAM, RHS.FAM); 395dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 396dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 397dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ~Result(); 398dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 399dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Accessor for the \c FunctionAnalysisManager. 400dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines FunctionAnalysisManager &getManager() { return *FAM; } 401dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 402dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Handler for invalidation of the SCC. 403dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// 404dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// If this analysis itself is preserved, then we assume that the set of \c 405dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// Function objects in the \c SCC hasn't changed and thus we don't need 406dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// to invalidate *all* cached data associated with a \c Function* in the \c 407dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// FunctionAnalysisManager. 408dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// 409dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// Regardless of whether this analysis is marked as preserved, all of the 410dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// analyses in the \c FunctionAnalysisManager are potentially invalidated 411dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// based on the set of preserved analyses. 412dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines bool invalidate(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); 413dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 414dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines private: 415dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines FunctionAnalysisManager *FAM; 416dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines }; 417dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 418dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static void *ID() { return (void *)&PassID; } 419dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 420dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM) 421dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : FAM(&FAM) {} 422dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We have to explicitly define all the special member functions because MSVC 423dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // refuses to generate them. 424dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines FunctionAnalysisManagerCGSCCProxy( 425dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const FunctionAnalysisManagerCGSCCProxy &Arg) 426dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : FAM(Arg.FAM) {} 427dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy &&Arg) 428dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : FAM(std::move(Arg.FAM)) {} 429dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines FunctionAnalysisManagerCGSCCProxy & 430dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines operator=(FunctionAnalysisManagerCGSCCProxy RHS) { 431dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::swap(FAM, RHS.FAM); 432dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 433dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 434dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 435dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Run the analysis pass and create our proxy result object. 436dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// 437dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// This doesn't do any interesting work, it is primarily used to insert our 438dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// proxy result object into the module analysis cache so that we can proxy 439dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// invalidation to the function analysis manager. 440dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// 441dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// In debug builds, it will also assert that the analysis manager is empty 442dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// as no queries should arrive at the function analysis manager prior to 443dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// this analysis being requested. 444dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result run(LazyCallGraph::SCC *C); 445dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 446dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesprivate: 447dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static char PassID; 448dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 449dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines FunctionAnalysisManager *FAM; 450dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}; 451dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 452dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \brief A function analysis which acts as a proxy for a CGSCC analysis 453dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// manager. 454dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// 455dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// This primarily provides an accessor to a parent CGSCC analysis manager to 456dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// function passes. Only the const interface of the CGSCC analysis manager is 457dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// provided to indicate that once inside of a function analysis pass you 458dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// cannot request a CGSCC analysis to actually run. Instead, the user must 459dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// rely on the \c getCachedResult API. 460dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// 461dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// This proxy *doesn't* manage the invalidation in any way. That is handled by 462dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// the recursive return path of each layer of the pass manager and the 463dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// returned PreservedAnalysis set. 464dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass CGSCCAnalysisManagerFunctionProxy { 465dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinespublic: 466dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy. 467dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines class Result { 468dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines public: 469dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines explicit Result(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} 470dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We have to explicitly define all the special member functions because 471dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // MSVC refuses to generate them. 472dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result(const Result &Arg) : CGAM(Arg.CGAM) {} 473dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {} 474dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result &operator=(Result RHS) { 475dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::swap(CGAM, RHS.CGAM); 476dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 477dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 478dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 479dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const CGSCCAnalysisManager &getManager() const { return *CGAM; } 480dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 481dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Handle invalidation by ignoring it, this pass is immutable. 482dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines bool invalidate(Function *) { return false; } 483dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 484dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines private: 485dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const CGSCCAnalysisManager *CGAM; 486dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines }; 487dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 488dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static void *ID() { return (void *)&PassID; } 489dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 490dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM) 491dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : CGAM(&CGAM) {} 492dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We have to explicitly define all the special member functions because MSVC 493dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // refuses to generate them. 494dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManagerFunctionProxy( 495dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const CGSCCAnalysisManagerFunctionProxy &Arg) 496dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : CGAM(Arg.CGAM) {} 497dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy &&Arg) 498dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : CGAM(std::move(Arg.CGAM)) {} 499dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCAnalysisManagerFunctionProxy & 500dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines operator=(CGSCCAnalysisManagerFunctionProxy RHS) { 501dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::swap(CGAM, RHS.CGAM); 502dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 503dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 504dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 505dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Run the analysis pass and create our proxy result object. 506dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// Nothing to see here, it just forwards the \c CGAM reference into the 507dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// result. 508dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result run(Function *) { return Result(*CGAM); } 509dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 510dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesprivate: 511dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static char PassID; 512dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 513dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const CGSCCAnalysisManager *CGAM; 514dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}; 515dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 516dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \brief Adaptor that maps from a SCC to its functions. 517dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// 518dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// Designed to allow composition of a FunctionPass(Manager) and 519dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// a CGSCCPassManager. Note that if this pass is constructed with a pointer 520dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// to a \c CGSCCAnalysisManager it will run the 521dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function 522dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// pass over the SCC to enable a \c FunctionAnalysisManager to be used 523dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// within this run safely. 524dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinestemplate <typename FunctionPassT> class CGSCCToFunctionPassAdaptor { 525dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinespublic: 526dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass) 527dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : Pass(std::move(Pass)) {} 528dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We have to explicitly define all the special member functions because MSVC 529dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // refuses to generate them. 530dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg) 531dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : Pass(Arg.Pass) {} 532dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg) 533dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : Pass(std::move(Arg.Pass)) {} 534dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines friend void swap(CGSCCToFunctionPassAdaptor &LHS, CGSCCToFunctionPassAdaptor &RHS) { 535dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines using std::swap; 536dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines swap(LHS.Pass, RHS.Pass); 537dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 538dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) { 539dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines swap(*this, RHS); 540dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 541dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 542dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 543dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Runs the function pass across every function in the module. 544dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PreservedAnalyses run(LazyCallGraph::SCC *C, CGSCCAnalysisManager *AM) { 545dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines FunctionAnalysisManager *FAM = nullptr; 546dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (AM) 547dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Setup the function analysis manager from its proxy. 548dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines FAM = &AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager(); 549dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 550dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PreservedAnalyses PA = PreservedAnalyses::all(); 551dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines for (LazyCallGraph::Node *N : *C) { 552dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PreservedAnalyses PassPA = Pass.run(&N->getFunction(), FAM); 553dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 554dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // We know that the function pass couldn't have invalidated any other 555dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // function's analyses (that's the contract of a function pass), so 556dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // directly handle the function analysis manager's invalidation here. 557dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (FAM) 558dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines FAM->invalidate(&N->getFunction(), PassPA); 559dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 560dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Then intersect the preserved set so that invalidation of module 561dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // analyses will eventually occur when the module pass completes. 562dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PA.intersect(std::move(PassPA)); 563dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 564dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 565dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // By definition we preserve the proxy. This precludes *any* invalidation 566dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // of function analyses by the proxy, but that's OK because we've taken 567dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // care to invalidate analyses in the function analysis manager 568dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // incrementally above. 569dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // FIXME: We need to update the call graph here to account for any deleted 570dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // edges! 571dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 572dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return PA; 573dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 574dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 575dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static StringRef name() { return "CGSCCToFunctionPassAdaptor"; } 576dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 577dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesprivate: 578dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines FunctionPassT Pass; 579dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}; 580dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 581dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// \brief A function to deduce a function pass type and wrap it in the 582dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// templated adaptor. 583dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinestemplate <typename FunctionPassT> 584dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesCGSCCToFunctionPassAdaptor<FunctionPassT> 585dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinescreateCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { 586dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass))); 587dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} 588dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 589dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} 590dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 591dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#endif 592