//===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
/// \file
 
///
 
/// This header provides classes for managing passes over SCCs of the call
 
/// graph. These passes form an important component of LLVM's interprocedural
 
/// optimizations. Because they operate on the SCCs of the call graph, and they
 
/// traverse the graph in post-order, they can effectively do pair-wise
 
/// interprocedural optimizations for all call edges in the program while
 
/// incrementally refining it and improving the context of these pair-wise
 
/// optimizations. At each call site edge, the callee has already been
 
/// optimized as much as is possible. This in turn allows very accurate
 
/// analysis of it for IPO.
 
///
 
/// A secondary more general goal is to be able to isolate optimization on
 
/// unrelated parts of the IR module. This is useful to ensure our
 
/// optimizations are principled and don't miss oportunities where refinement
 
/// of one part of the module influences transformations in another part of the
 
/// module. But this is also useful if we want to parallelize the optimizations
 
/// across common large module graph shapes which tend to be very wide and have
 
/// large regions of unrelated cliques.
 
///
 
/// To satisfy these goals, we use the LazyCallGraph which provides two graphs
 
/// nested inside each other (and built lazily from the bottom-up): the call
 
/// graph proper, and a reference graph. The reference graph is super set of
 
/// the call graph and is a conservative approximation of what could through
 
/// scalar or CGSCC transforms *become* the call graph. Using this allows us to
 
/// ensure we optimize functions prior to them being introduced into the call
 
/// graph by devirtualization or other technique, and thus ensures that
 
/// subsequent pair-wise interprocedural optimizations observe the optimized
 
/// form of these functions. The (potentially transitive) reference
 
/// reachability used by the reference graph is a conservative approximation
 
/// that still allows us to have independent regions of the graph.
 
///
 
/// FIXME: There is one major drawback of the reference graph: in its naive
 
/// form it is quadratic because it contains a distinct edge for each
 
/// (potentially indirect) reference, even if are all through some common
 
/// global table of function pointers. This can be fixed in a number of ways
 
/// that essentially preserve enough of the normalization. While it isn't
 
/// expected to completely preclude the usability of this, it will need to be
 
/// addressed.
 
///
 
///
 
/// All of these issues are made substantially more complex in the face of
 
/// mutations to the call graph while optimization passes are being run. When
 
/// mutations to the call graph occur we want to achieve two different things:
 
///
 
/// - We need to update the call graph in-flight and invalidate analyses
 
///   cached on entities in the graph. Because of the cache-based analysis
 
///   design of the pass manager, it is essential to have stable identities for
 
///   the elements of the IR that passes traverse, and to invalidate any
 
///   analyses cached on these elements as the mutations take place.
 
///
 
/// - We want to preserve the incremental and post-order traversal of the
 
///   graph even as it is refined and mutated. This means we want optimization
 
///   to observe the most refined form of the call graph and to do so in
 
///   post-order.
 
///
 
/// To address this, the CGSCC manager uses both worklists that can be expanded
 
/// by passes which transform the IR, and provides invalidation tests to skip
 
/// entries that become dead. This extra data is provided to every SCC pass so
 
/// that it can carefully update the manager's traversal as the call graph
 
/// mutates.
 
///
 
/// We also provide support for running function passes within the CGSCC walk,
 
/// and there we provide automatic update of the call graph including of the
 
/// pass manager to reflect call graph changes that fall out naturally as part
 
/// of scalar transformations.
 
///
 
/// The patterns used to ensure the goals of post-order visitation of the fully
 
/// refined graph:
 
///
 
/// 1) Sink toward the "bottom" as the graph is refined. This means that any
 
///    iteration continues in some valid post-order sequence after the mutation
 
///    has altered the structure.
 
///
 
/// 2) Enqueue in post-order, including the current entity. If the current
 
///    entity's shape changes, it and everything after it in post-order needs
 
///    to be visited to observe that shape.
 
///
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H
 
#define LLVM_ANALYSIS_CGSCCPASSMANAGER_H
 
 
 
#include "llvm/ADT/MapVector.h"
 
#include "llvm/Analysis/LazyCallGraph.h"
 
#include "llvm/IR/PassManager.h"
 
#include "llvm/IR/ValueHandle.h"
 
#include "llvm/Support/raw_ostream.h"
 
#include <cassert>
 
#include <utility>
 
 
 
namespace llvm {
 
 
 
class Function;
 
class Value;
 
template <typename T, unsigned int N> class SmallPriorityWorklist;
 
struct CGSCCUpdateResult;
 
 
 
class Module;
 
 
 
// Allow debug logging in this inline function.
 
#define DEBUG_TYPE "cgscc"
 
 
 
/// Extern template declaration for the analysis set for this IR unit.
 
extern template class AllAnalysesOn<LazyCallGraph::SCC>;
 
 
 
extern template class AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>;
 
 
 
/// The CGSCC analysis manager.
 
///
 
/// See the documentation for the AnalysisManager template for detail
 
/// documentation. This type 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.
 
using CGSCCAnalysisManager =
 
    AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>;
 
 
 
// Explicit specialization and instantiation declarations for the pass manager.
 
// See the comments on the definition of the specialization for details on how
 
// it differs from the primary template.
 
template <>
 
PreservedAnalyses
 
PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
 
            CGSCCUpdateResult &>::run(LazyCallGraph::SCC &InitialC,
 
                                      CGSCCAnalysisManager &AM,
 
                                      LazyCallGraph &G, CGSCCUpdateResult &UR);
 
extern template class PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager,
 
                                  LazyCallGraph &, CGSCCUpdateResult &>;
 
 
 
/// The CGSCC pass manager.
 
///
 
/// See the documentation for the PassManager template for details. It runs
 
/// a sequence of SCC passes over each SCC that the manager is run over. This
 
/// type serves as a convenient way to refer to this construct.
 
using CGSCCPassManager =
 
    PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
 
                CGSCCUpdateResult &>;
 
 
 
/// An explicit specialization of the require analysis template pass.
 
template <typename AnalysisT>
 
struct RequireAnalysisPass<AnalysisT, LazyCallGraph::SCC, CGSCCAnalysisManager,
 
                           LazyCallGraph &, CGSCCUpdateResult &>
 
    : PassInfoMixin<RequireAnalysisPass<AnalysisT, LazyCallGraph::SCC,
 
                                        CGSCCAnalysisManager, LazyCallGraph &,
 
                                        CGSCCUpdateResult &>> {
 
  PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
 
                        LazyCallGraph &CG, CGSCCUpdateResult &) {
 
    (void)AM.template getResult<AnalysisT>(C, CG);
 
    return PreservedAnalyses::all();
 
  }
 
  void printPipeline(raw_ostream &OS,
 
                     function_ref<StringRef(StringRef)> MapClassName2PassName) {
 
    auto ClassName = AnalysisT::name();
 
    auto PassName = MapClassName2PassName(ClassName);
 
    OS << "require<" << PassName << ">";
 
  }
 
};
 
 
 
/// A proxy from a \c CGSCCAnalysisManager to a \c Module.
 
using CGSCCAnalysisManagerModuleProxy =
 
    InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;
 
 
 
/// We need a specialized result for the \c CGSCCAnalysisManagerModuleProxy so
 
/// it can have access to the call graph in order to walk all the SCCs when
 
/// invalidating things.
 
template <> class CGSCCAnalysisManagerModuleProxy::Result {
 
public:
 
  explicit Result(CGSCCAnalysisManager &InnerAM, LazyCallGraph &G)
 
      : InnerAM(&InnerAM), G(&G) {}
 
 
 
  /// Accessor for the analysis manager.
 
  CGSCCAnalysisManager &getManager() { return *InnerAM; }
 
 
 
  /// Handler for invalidation of the Module.
 
  ///
 
  /// If the proxy analysis itself is preserved, then we assume that the set of
 
  /// SCCs in the Module hasn't changed. Thus any pointers to SCCs in the
 
  /// CGSCCAnalysisManager are still valid, and we don't need to call \c clear
 
  /// on the CGSCCAnalysisManager.
 
  ///
 
  /// Regardless of whether this analysis is marked as preserved, all of the
 
  /// analyses in the \c CGSCCAnalysisManager are potentially invalidated based
 
  /// on the set of preserved analyses.
 
  bool invalidate(Module &M, const PreservedAnalyses &PA,
 
                  ModuleAnalysisManager::Invalidator &Inv);
 
 
 
private:
 
  CGSCCAnalysisManager *InnerAM;
 
  LazyCallGraph *G;
 
};
 
 
 
/// Provide a specialized run method for the \c CGSCCAnalysisManagerModuleProxy
 
/// so it can pass the lazy call graph to the result.
 
template <>
 
CGSCCAnalysisManagerModuleProxy::Result
 
CGSCCAnalysisManagerModuleProxy::run(Module &M, ModuleAnalysisManager &AM);
 
 
 
// Ensure the \c CGSCCAnalysisManagerModuleProxy is provided as an extern
 
// template.
 
extern template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;
 
 
 
extern template class OuterAnalysisManagerProxy<
 
    ModuleAnalysisManager, LazyCallGraph::SCC, LazyCallGraph &>;
 
 
 
/// A proxy from a \c ModuleAnalysisManager to an \c SCC.
 
using ModuleAnalysisManagerCGSCCProxy =
 
    OuterAnalysisManagerProxy<ModuleAnalysisManager, LazyCallGraph::SCC,
 
                              LazyCallGraph &>;
 
 
 
/// Support structure for SCC passes to communicate updates the call graph back
 
/// to the CGSCC pass manager infrastructure.
 
///
 
/// The CGSCC pass manager runs SCC passes which are allowed to update the call
 
/// graph and SCC structures. This means the structure the pass manager works
 
/// on is mutating underneath it. In order to support that, there needs to be
 
/// careful communication about the precise nature and ramifications of these
 
/// updates to the pass management infrastructure.
 
///
 
/// All SCC passes will have to accept a reference to the management layer's
 
/// update result struct and use it to reflect the results of any CG updates
 
/// performed.
 
///
 
/// Passes which do not change the call graph structure in any way can just
 
/// ignore this argument to their run method.
 
struct CGSCCUpdateResult {
 
  /// Worklist of the RefSCCs queued for processing.
 
  ///
 
  /// When a pass refines the graph and creates new RefSCCs or causes them to
 
  /// have a different shape or set of component SCCs it should add the RefSCCs
 
  /// to this worklist so that we visit them in the refined form.
 
  ///
 
  /// This worklist is in reverse post-order, as we pop off the back in order
 
  /// to observe RefSCCs in post-order. When adding RefSCCs, clients should add
 
  /// them in reverse post-order.
 
  SmallPriorityWorklist<LazyCallGraph::RefSCC *, 1> &RCWorklist;
 
 
 
  /// Worklist of the SCCs queued for processing.
 
  ///
 
  /// When a pass refines the graph and creates new SCCs or causes them to have
 
  /// a different shape or set of component functions it should add the SCCs to
 
  /// this worklist so that we visit them in the refined form.
 
  ///
 
  /// Note that if the SCCs are part of a RefSCC that is added to the \c
 
  /// RCWorklist, they don't need to be added here as visiting the RefSCC will
 
  /// be sufficient to re-visit the SCCs within it.
 
  ///
 
  /// This worklist is in reverse post-order, as we pop off the back in order
 
  /// to observe SCCs in post-order. When adding SCCs, clients should add them
 
  /// in reverse post-order.
 
  SmallPriorityWorklist<LazyCallGraph::SCC *, 1> &CWorklist;
 
 
 
  /// The set of invalidated RefSCCs which should be skipped if they are found
 
  /// in \c RCWorklist.
 
  ///
 
  /// This is used to quickly prune out RefSCCs when they get deleted and
 
  /// happen to already be on the worklist. We use this primarily to avoid
 
  /// scanning the list and removing entries from it.
 
  SmallPtrSetImpl<LazyCallGraph::RefSCC *> &InvalidatedRefSCCs;
 
 
 
  /// The set of invalidated SCCs which should be skipped if they are found
 
  /// in \c CWorklist.
 
  ///
 
  /// This is used to quickly prune out SCCs when they get deleted and happen
 
  /// to already be on the worklist. We use this primarily to avoid scanning
 
  /// the list and removing entries from it.
 
  SmallPtrSetImpl<LazyCallGraph::SCC *> &InvalidatedSCCs;
 
 
 
  /// If non-null, the updated current \c SCC being processed.
 
  ///
 
  /// This is set when a graph refinement takes place and the "current" point
 
  /// in the graph moves "down" or earlier in the post-order walk. This will
 
  /// often cause the "current" SCC to be a newly created SCC object and the
 
  /// old one to be added to the above worklist. When that happens, this
 
  /// pointer is non-null and can be used to continue processing the "top" of
 
  /// the post-order walk.
 
  LazyCallGraph::SCC *UpdatedC;
 
 
 
  /// Preserved analyses across SCCs.
 
  ///
 
  /// We specifically want to allow CGSCC passes to mutate ancestor IR
 
  /// (changing both the CG structure and the function IR itself). However,
 
  /// this means we need to take special care to correctly mark what analyses
 
  /// are preserved *across* SCCs. We have to track this out-of-band here
 
  /// because within the main `PassManager` infrastructure we need to mark
 
  /// everything within an SCC as preserved in order to avoid repeatedly
 
  /// invalidating the same analyses as we unnest pass managers and adaptors.
 
  /// So we track the cross-SCC version of the preserved analyses here from any
 
  /// code that does direct invalidation of SCC analyses, and then use it
 
  /// whenever we move forward in the post-order walk of SCCs before running
 
  /// passes over the new SCC.
 
  PreservedAnalyses CrossSCCPA;
 
 
 
  /// A hacky area where the inliner can retain history about inlining
 
  /// decisions that mutated the call graph's SCC structure in order to avoid
 
  /// infinite inlining. See the comments in the inliner's CG update logic.
 
  ///
 
  /// FIXME: Keeping this here seems like a big layering issue, we should look
 
  /// for a better technique.
 
  SmallDenseSet<std::pair<LazyCallGraph::Node *, LazyCallGraph::SCC *>, 4>
 
      &InlinedInternalEdges;
 
 
 
  /// Weak VHs to keep track of indirect calls for the purposes of detecting
 
  /// devirtualization.
 
  ///
 
  /// This is a map to avoid having duplicate entries. If a Value is
 
  /// deallocated, its corresponding WeakTrackingVH will be nulled out. When
 
  /// checking if a Value is in the map or not, also check if the corresponding
 
  /// WeakTrackingVH is null to avoid issues with a new Value sharing the same
 
  /// address as a deallocated one.
 
  SmallMapVector<Value *, WeakTrackingVH, 16> IndirectVHs;
 
};
 
 
 
/// 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.
 
class ModuleToPostOrderCGSCCPassAdaptor
 
    : public PassInfoMixin<ModuleToPostOrderCGSCCPassAdaptor> {
 
public:
 
  using PassConceptT =
 
      detail::PassConcept<LazyCallGraph::SCC, CGSCCAnalysisManager,
 
                          LazyCallGraph &, CGSCCUpdateResult &>;
 
 
 
  explicit ModuleToPostOrderCGSCCPassAdaptor(std::unique_ptr<PassConceptT> Pass)
 
      : Pass(std::move(Pass)) {}
 
 
 
  ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
 
      : Pass(std::move(Arg.Pass)) {}
 
 
 
  friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
 
                   ModuleToPostOrderCGSCCPassAdaptor &RHS) {
 
    std::swap(LHS.Pass, RHS.Pass);
 
  }
 
 
 
  ModuleToPostOrderCGSCCPassAdaptor &
 
  operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
 
    swap(*this, RHS);
 
    return *this;
 
  }
 
 
 
  /// Runs the CGSCC pass across every SCC in the module.
 
  PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
 
 
 
  void printPipeline(raw_ostream &OS,
 
                     function_ref<StringRef(StringRef)> MapClassName2PassName) {
 
    OS << "cgscc(";
 
    Pass->printPipeline(OS, MapClassName2PassName);
 
    OS << ")";
 
  }
 
 
 
  static bool isRequired() { return true; }
 
 
 
private:
 
  std::unique_ptr<PassConceptT> Pass;
 
};
 
 
 
/// A function to deduce a function pass type and wrap it in the
 
/// templated adaptor.
 
template <typename CGSCCPassT>
 
ModuleToPostOrderCGSCCPassAdaptor
 
createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT &&Pass) {
 
  using PassModelT = detail::PassModel<LazyCallGraph::SCC, CGSCCPassT,
 
                                       PreservedAnalyses, CGSCCAnalysisManager,
 
                                       LazyCallGraph &, CGSCCUpdateResult &>;
 
  // Do not use make_unique, it causes too many template instantiations,
 
  // causing terrible compile times.
 
  return ModuleToPostOrderCGSCCPassAdaptor(
 
      std::unique_ptr<ModuleToPostOrderCGSCCPassAdaptor::PassConceptT>(
 
          new PassModelT(std::forward<CGSCCPassT>(Pass))));
 
}
 
 
 
/// A proxy from a \c FunctionAnalysisManager to an \c SCC.
 
///
 
/// When a module pass runs and triggers invalidation, both the CGSCC and
 
/// Function analysis manager proxies on the module get an invalidation event.
 
/// We don't want to fully duplicate responsibility for most of the
 
/// invalidation logic. Instead, this layer is only responsible for SCC-local
 
/// invalidation events. We work with the module's FunctionAnalysisManager to
 
/// invalidate function analyses.
 
class FunctionAnalysisManagerCGSCCProxy
 
    : public AnalysisInfoMixin<FunctionAnalysisManagerCGSCCProxy> {
 
public:
 
  class Result {
 
  public:
 
    explicit Result() : FAM(nullptr) {}
 
    explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
 
 
 
    void updateFAM(FunctionAnalysisManager &FAM) { this->FAM = &FAM; }
 
    /// Accessor for the analysis manager.
 
    FunctionAnalysisManager &getManager() {
 
      assert(FAM);
 
      return *FAM;
 
    }
 
 
 
    bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
 
                    CGSCCAnalysisManager::Invalidator &Inv);
 
 
 
  private:
 
    FunctionAnalysisManager *FAM;
 
  };
 
 
 
  /// Computes the \c FunctionAnalysisManager and stores it in the result proxy.
 
  Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &);
 
 
 
private:
 
  friend AnalysisInfoMixin<FunctionAnalysisManagerCGSCCProxy>;
 
 
 
  static AnalysisKey Key;
 
};
 
 
 
extern template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;
 
 
 
/// A proxy from a \c CGSCCAnalysisManager to a \c Function.
 
using CGSCCAnalysisManagerFunctionProxy =
 
    OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;
 
 
 
/// Helper to update the call graph after running a function pass.
 
///
 
/// Function passes can only mutate the call graph in specific ways. This
 
/// routine provides a helper that updates the call graph in those ways
 
/// including returning whether any changes were made and populating a CG
 
/// update result struct for the overall CGSCC walk.
 
LazyCallGraph::SCC &updateCGAndAnalysisManagerForFunctionPass(
 
    LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
 
    CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
 
    FunctionAnalysisManager &FAM);
 
 
 
/// Helper to update the call graph after running a CGSCC pass.
 
///
 
/// CGSCC passes can only mutate the call graph in specific ways. This
 
/// routine provides a helper that updates the call graph in those ways
 
/// including returning whether any changes were made and populating a CG
 
/// update result struct for the overall CGSCC walk.
 
LazyCallGraph::SCC &updateCGAndAnalysisManagerForCGSCCPass(
 
    LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
 
    CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
 
    FunctionAnalysisManager &FAM);
 
 
 
/// 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.
 
class CGSCCToFunctionPassAdaptor
 
    : public PassInfoMixin<CGSCCToFunctionPassAdaptor> {
 
public:
 
  using PassConceptT = detail::PassConcept<Function, FunctionAnalysisManager>;
 
 
 
  explicit CGSCCToFunctionPassAdaptor(std::unique_ptr<PassConceptT> Pass,
 
                                      bool EagerlyInvalidate, bool NoRerun)
 
      : Pass(std::move(Pass)), EagerlyInvalidate(EagerlyInvalidate),
 
        NoRerun(NoRerun) {}
 
 
 
  CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
 
      : Pass(std::move(Arg.Pass)), EagerlyInvalidate(Arg.EagerlyInvalidate),
 
        NoRerun(Arg.NoRerun) {}
 
 
 
  friend void swap(CGSCCToFunctionPassAdaptor &LHS,
 
                   CGSCCToFunctionPassAdaptor &RHS) {
 
    std::swap(LHS.Pass, RHS.Pass);
 
  }
 
 
 
  CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
 
    swap(*this, RHS);
 
    return *this;
 
  }
 
 
 
  /// Runs the function pass across every function in the module.
 
  PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
 
                        LazyCallGraph &CG, CGSCCUpdateResult &UR);
 
 
 
  void printPipeline(raw_ostream &OS,
 
                     function_ref<StringRef(StringRef)> MapClassName2PassName) {
 
    OS << "function";
 
    if (EagerlyInvalidate)
 
      OS << "<eager-inv>";
 
    OS << "(";
 
    Pass->printPipeline(OS, MapClassName2PassName);
 
    OS << ")";
 
  }
 
 
 
  static bool isRequired() { return true; }
 
 
 
private:
 
  std::unique_ptr<PassConceptT> Pass;
 
  bool EagerlyInvalidate;
 
  bool NoRerun;
 
};
 
 
 
/// A function to deduce a function pass type and wrap it in the
 
/// templated adaptor.
 
template <typename FunctionPassT>
 
CGSCCToFunctionPassAdaptor
 
createCGSCCToFunctionPassAdaptor(FunctionPassT &&Pass,
 
                                 bool EagerlyInvalidate = false,
 
                                 bool NoRerun = false) {
 
  using PassModelT =
 
      detail::PassModel<Function, FunctionPassT, PreservedAnalyses,
 
                        FunctionAnalysisManager>;
 
  // Do not use make_unique, it causes too many template instantiations,
 
  // causing terrible compile times.
 
  return CGSCCToFunctionPassAdaptor(
 
      std::unique_ptr<CGSCCToFunctionPassAdaptor::PassConceptT>(
 
          new PassModelT(std::forward<FunctionPassT>(Pass))),
 
      EagerlyInvalidate, NoRerun);
 
}
 
 
 
// A marker to determine if function passes should be run on a function within a
 
// CGSCCToFunctionPassAdaptor. This is used to prevent running an expensive
 
// function pass (manager) on a function multiple times if SCC mutations cause a
 
// function to be visited multiple times and the function is not modified by
 
// other SCC passes.
 
class ShouldNotRunFunctionPassesAnalysis
 
    : public AnalysisInfoMixin<ShouldNotRunFunctionPassesAnalysis> {
 
public:
 
  static AnalysisKey Key;
 
  struct Result {};
 
 
 
  Result run(Function &F, FunctionAnalysisManager &FAM) { return Result(); }
 
};
 
 
 
/// A helper that repeats an SCC pass each time an indirect call is refined to
 
/// a direct call by that pass.
 
///
 
/// While the CGSCC pass manager works to re-visit SCCs and RefSCCs as they
 
/// change shape, we may also want to repeat an SCC pass if it simply refines
 
/// an indirect call to a direct call, even if doing so does not alter the
 
/// shape of the graph. Note that this only pertains to direct calls to
 
/// functions where IPO across the SCC may be able to compute more precise
 
/// results. For intrinsics, we assume scalar optimizations already can fully
 
/// reason about them.
 
///
 
/// This repetition has the potential to be very large however, as each one
 
/// might refine a single call site. As a consequence, in practice we use an
 
/// upper bound on the number of repetitions to limit things.
 
class DevirtSCCRepeatedPass : public PassInfoMixin<DevirtSCCRepeatedPass> {
 
public:
 
  using PassConceptT =
 
      detail::PassConcept<LazyCallGraph::SCC, CGSCCAnalysisManager,
 
                          LazyCallGraph &, CGSCCUpdateResult &>;
 
 
 
  explicit DevirtSCCRepeatedPass(std::unique_ptr<PassConceptT> Pass,
 
                                 int MaxIterations)
 
      : Pass(std::move(Pass)), MaxIterations(MaxIterations) {}
 
 
 
  /// Runs the wrapped pass up to \c MaxIterations on the SCC, iterating
 
  /// whenever an indirect call is refined.
 
  PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM,
 
                        LazyCallGraph &CG, CGSCCUpdateResult &UR);
 
 
 
  void printPipeline(raw_ostream &OS,
 
                     function_ref<StringRef(StringRef)> MapClassName2PassName) {
 
    OS << "devirt<" << MaxIterations << ">(";
 
    Pass->printPipeline(OS, MapClassName2PassName);
 
    OS << ")";
 
  }
 
 
 
private:
 
  std::unique_ptr<PassConceptT> Pass;
 
  int MaxIterations;
 
};
 
 
 
/// A function to deduce a function pass type and wrap it in the
 
/// templated adaptor.
 
template <typename CGSCCPassT>
 
DevirtSCCRepeatedPass createDevirtSCCRepeatedPass(CGSCCPassT &&Pass,
 
                                                  int MaxIterations) {
 
  using PassModelT = detail::PassModel<LazyCallGraph::SCC, CGSCCPassT,
 
                                       PreservedAnalyses, CGSCCAnalysisManager,
 
                                       LazyCallGraph &, CGSCCUpdateResult &>;
 
  // Do not use make_unique, it causes too many template instantiations,
 
  // causing terrible compile times.
 
  return DevirtSCCRepeatedPass(
 
      std::unique_ptr<DevirtSCCRepeatedPass::PassConceptT>(
 
          new PassModelT(std::forward<CGSCCPassT>(Pass))),
 
      MaxIterations);
 
}
 
 
 
// Clear out the debug logging macro.
 
#undef DEBUG_TYPE
 
 
 
} // end namespace llvm
 
 
 
#endif // LLVM_ANALYSIS_CGSCCPASSMANAGER_H