Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:12

0001 //===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 /// \file
0009 ///
0010 /// This header provides classes for managing passes over SCCs of the call
0011 /// graph. These passes form an important component of LLVM's interprocedural
0012 /// optimizations. Because they operate on the SCCs of the call graph, and they
0013 /// traverse the graph in post-order, they can effectively do pair-wise
0014 /// interprocedural optimizations for all call edges in the program while
0015 /// incrementally refining it and improving the context of these pair-wise
0016 /// optimizations. At each call site edge, the callee has already been
0017 /// optimized as much as is possible. This in turn allows very accurate
0018 /// analysis of it for IPO.
0019 ///
0020 /// A secondary more general goal is to be able to isolate optimization on
0021 /// unrelated parts of the IR module. This is useful to ensure our
0022 /// optimizations are principled and don't miss oportunities where refinement
0023 /// of one part of the module influences transformations in another part of the
0024 /// module. But this is also useful if we want to parallelize the optimizations
0025 /// across common large module graph shapes which tend to be very wide and have
0026 /// large regions of unrelated cliques.
0027 ///
0028 /// To satisfy these goals, we use the LazyCallGraph which provides two graphs
0029 /// nested inside each other (and built lazily from the bottom-up): the call
0030 /// graph proper, and a reference graph. The reference graph is super set of
0031 /// the call graph and is a conservative approximation of what could through
0032 /// scalar or CGSCC transforms *become* the call graph. Using this allows us to
0033 /// ensure we optimize functions prior to them being introduced into the call
0034 /// graph by devirtualization or other technique, and thus ensures that
0035 /// subsequent pair-wise interprocedural optimizations observe the optimized
0036 /// form of these functions. The (potentially transitive) reference
0037 /// reachability used by the reference graph is a conservative approximation
0038 /// that still allows us to have independent regions of the graph.
0039 ///
0040 /// FIXME: There is one major drawback of the reference graph: in its naive
0041 /// form it is quadratic because it contains a distinct edge for each
0042 /// (potentially indirect) reference, even if are all through some common
0043 /// global table of function pointers. This can be fixed in a number of ways
0044 /// that essentially preserve enough of the normalization. While it isn't
0045 /// expected to completely preclude the usability of this, it will need to be
0046 /// addressed.
0047 ///
0048 ///
0049 /// All of these issues are made substantially more complex in the face of
0050 /// mutations to the call graph while optimization passes are being run. When
0051 /// mutations to the call graph occur we want to achieve two different things:
0052 ///
0053 /// - We need to update the call graph in-flight and invalidate analyses
0054 ///   cached on entities in the graph. Because of the cache-based analysis
0055 ///   design of the pass manager, it is essential to have stable identities for
0056 ///   the elements of the IR that passes traverse, and to invalidate any
0057 ///   analyses cached on these elements as the mutations take place.
0058 ///
0059 /// - We want to preserve the incremental and post-order traversal of the
0060 ///   graph even as it is refined and mutated. This means we want optimization
0061 ///   to observe the most refined form of the call graph and to do so in
0062 ///   post-order.
0063 ///
0064 /// To address this, the CGSCC manager uses both worklists that can be expanded
0065 /// by passes which transform the IR, and provides invalidation tests to skip
0066 /// entries that become dead. This extra data is provided to every SCC pass so
0067 /// that it can carefully update the manager's traversal as the call graph
0068 /// mutates.
0069 ///
0070 /// We also provide support for running function passes within the CGSCC walk,
0071 /// and there we provide automatic update of the call graph including of the
0072 /// pass manager to reflect call graph changes that fall out naturally as part
0073 /// of scalar transformations.
0074 ///
0075 /// The patterns used to ensure the goals of post-order visitation of the fully
0076 /// refined graph:
0077 ///
0078 /// 1) Sink toward the "bottom" as the graph is refined. This means that any
0079 ///    iteration continues in some valid post-order sequence after the mutation
0080 ///    has altered the structure.
0081 ///
0082 /// 2) Enqueue in post-order, including the current entity. If the current
0083 ///    entity's shape changes, it and everything after it in post-order needs
0084 ///    to be visited to observe that shape.
0085 ///
0086 //===----------------------------------------------------------------------===//
0087 
0088 #ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H
0089 #define LLVM_ANALYSIS_CGSCCPASSMANAGER_H
0090 
0091 #include "llvm/ADT/MapVector.h"
0092 #include "llvm/Analysis/LazyCallGraph.h"
0093 #include "llvm/IR/PassManager.h"
0094 #include "llvm/IR/ValueHandle.h"
0095 #include "llvm/Support/raw_ostream.h"
0096 #include <cassert>
0097 #include <utility>
0098 
0099 namespace llvm {
0100 
0101 class Function;
0102 template <typename T, unsigned int N> class SmallPriorityWorklist;
0103 struct CGSCCUpdateResult;
0104 
0105 class Module;
0106 
0107 // Allow debug logging in this inline function.
0108 #define DEBUG_TYPE "cgscc"
0109 
0110 /// Extern template declaration for the analysis set for this IR unit.
0111 extern template class AllAnalysesOn<LazyCallGraph::SCC>;
0112 
0113 extern template class AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>;
0114 
0115 /// The CGSCC analysis manager.
0116 ///
0117 /// See the documentation for the AnalysisManager template for detail
0118 /// documentation. This type serves as a convenient way to refer to this
0119 /// construct in the adaptors and proxies used to integrate this into the larger
0120 /// pass manager infrastructure.
0121 using CGSCCAnalysisManager =
0122     AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>;
0123 
0124 // Explicit specialization and instantiation declarations for the pass manager.
0125 // See the comments on the definition of the specialization for details on how
0126 // it differs from the primary template.
0127 template <>
0128 PreservedAnalyses
0129 PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
0130             CGSCCUpdateResult &>::run(LazyCallGraph::SCC &InitialC,
0131                                       CGSCCAnalysisManager &AM,
0132                                       LazyCallGraph &G, CGSCCUpdateResult &UR);
0133 extern template class PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager,
0134                                   LazyCallGraph &, CGSCCUpdateResult &>;
0135 
0136 /// The CGSCC pass manager.
0137 ///
0138 /// See the documentation for the PassManager template for details. It runs
0139 /// a sequence of SCC passes over each SCC that the manager is run over. This
0140 /// type serves as a convenient way to refer to this construct.
0141 using CGSCCPassManager =
0142     PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
0143                 CGSCCUpdateResult &>;
0144 
0145 /// An explicit specialization of the require analysis template pass.
0146 template <typename AnalysisT>
0147 struct RequireAnalysisPass<AnalysisT, LazyCallGraph::SCC, CGSCCAnalysisManager,
0148                            LazyCallGraph &, CGSCCUpdateResult &>
0149     : PassInfoMixin<RequireAnalysisPass<AnalysisT, LazyCallGraph::SCC,
0150                                         CGSCCAnalysisManager, LazyCallGraph &,
0151                                         CGSCCUpdateResult &>> {
0152   PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
0153                         LazyCallGraph &CG, CGSCCUpdateResult &) {
0154     (void)AM.template getResult<AnalysisT>(C, CG);
0155     return PreservedAnalyses::all();
0156   }
0157   void printPipeline(raw_ostream &OS,
0158                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
0159     auto ClassName = AnalysisT::name();
0160     auto PassName = MapClassName2PassName(ClassName);
0161     OS << "require<" << PassName << '>';
0162   }
0163 };
0164 
0165 /// A proxy from a \c CGSCCAnalysisManager to a \c Module.
0166 using CGSCCAnalysisManagerModuleProxy =
0167     InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;
0168 
0169 /// We need a specialized result for the \c CGSCCAnalysisManagerModuleProxy so
0170 /// it can have access to the call graph in order to walk all the SCCs when
0171 /// invalidating things.
0172 template <> class CGSCCAnalysisManagerModuleProxy::Result {
0173 public:
0174   explicit Result(CGSCCAnalysisManager &InnerAM, LazyCallGraph &G)
0175       : InnerAM(&InnerAM), G(&G) {}
0176 
0177   /// Accessor for the analysis manager.
0178   CGSCCAnalysisManager &getManager() { return *InnerAM; }
0179 
0180   /// Handler for invalidation of the Module.
0181   ///
0182   /// If the proxy analysis itself is preserved, then we assume that the set of
0183   /// SCCs in the Module hasn't changed. Thus any pointers to SCCs in the
0184   /// CGSCCAnalysisManager are still valid, and we don't need to call \c clear
0185   /// on the CGSCCAnalysisManager.
0186   ///
0187   /// Regardless of whether this analysis is marked as preserved, all of the
0188   /// analyses in the \c CGSCCAnalysisManager are potentially invalidated based
0189   /// on the set of preserved analyses.
0190   bool invalidate(Module &M, const PreservedAnalyses &PA,
0191                   ModuleAnalysisManager::Invalidator &Inv);
0192 
0193 private:
0194   CGSCCAnalysisManager *InnerAM;
0195   LazyCallGraph *G;
0196 };
0197 
0198 /// Provide a specialized run method for the \c CGSCCAnalysisManagerModuleProxy
0199 /// so it can pass the lazy call graph to the result.
0200 template <>
0201 CGSCCAnalysisManagerModuleProxy::Result
0202 CGSCCAnalysisManagerModuleProxy::run(Module &M, ModuleAnalysisManager &AM);
0203 
0204 // Ensure the \c CGSCCAnalysisManagerModuleProxy is provided as an extern
0205 // template.
0206 extern template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;
0207 
0208 extern template class OuterAnalysisManagerProxy<
0209     ModuleAnalysisManager, LazyCallGraph::SCC, LazyCallGraph &>;
0210 
0211 /// A proxy from a \c ModuleAnalysisManager to an \c SCC.
0212 using ModuleAnalysisManagerCGSCCProxy =
0213     OuterAnalysisManagerProxy<ModuleAnalysisManager, LazyCallGraph::SCC,
0214                               LazyCallGraph &>;
0215 
0216 /// Support structure for SCC passes to communicate updates the call graph back
0217 /// to the CGSCC pass manager infrastructure.
0218 ///
0219 /// The CGSCC pass manager runs SCC passes which are allowed to update the call
0220 /// graph and SCC structures. This means the structure the pass manager works
0221 /// on is mutating underneath it. In order to support that, there needs to be
0222 /// careful communication about the precise nature and ramifications of these
0223 /// updates to the pass management infrastructure.
0224 ///
0225 /// All SCC passes will have to accept a reference to the management layer's
0226 /// update result struct and use it to reflect the results of any CG updates
0227 /// performed.
0228 ///
0229 /// Passes which do not change the call graph structure in any way can just
0230 /// ignore this argument to their run method.
0231 struct CGSCCUpdateResult {
0232   /// Worklist of the SCCs queued for processing.
0233   ///
0234   /// When a pass refines the graph and creates new SCCs or causes them to have
0235   /// a different shape or set of component functions it should add the SCCs to
0236   /// this worklist so that we visit them in the refined form.
0237   ///
0238   /// Note that if the SCCs are part of a RefSCC that is added to the \c
0239   /// RCWorklist, they don't need to be added here as visiting the RefSCC will
0240   /// be sufficient to re-visit the SCCs within it.
0241   ///
0242   /// This worklist is in reverse post-order, as we pop off the back in order
0243   /// to observe SCCs in post-order. When adding SCCs, clients should add them
0244   /// in reverse post-order.
0245   SmallPriorityWorklist<LazyCallGraph::SCC *, 1> &CWorklist;
0246 
0247   /// The set of invalidated SCCs which should be skipped if they are found
0248   /// in \c CWorklist.
0249   ///
0250   /// This is used to quickly prune out SCCs when they get deleted and happen
0251   /// to already be on the worklist. We use this primarily to avoid scanning
0252   /// the list and removing entries from it.
0253   SmallPtrSetImpl<LazyCallGraph::SCC *> &InvalidatedSCCs;
0254 
0255   /// If non-null, the updated current \c SCC being processed.
0256   ///
0257   /// This is set when a graph refinement takes place and the "current" point
0258   /// in the graph moves "down" or earlier in the post-order walk. This will
0259   /// often cause the "current" SCC to be a newly created SCC object and the
0260   /// old one to be added to the above worklist. When that happens, this
0261   /// pointer is non-null and can be used to continue processing the "top" of
0262   /// the post-order walk.
0263   LazyCallGraph::SCC *UpdatedC;
0264 
0265   /// Preserved analyses across SCCs.
0266   ///
0267   /// We specifically want to allow CGSCC passes to mutate ancestor IR
0268   /// (changing both the CG structure and the function IR itself). However,
0269   /// this means we need to take special care to correctly mark what analyses
0270   /// are preserved *across* SCCs. We have to track this out-of-band here
0271   /// because within the main `PassManager` infrastructure we need to mark
0272   /// everything within an SCC as preserved in order to avoid repeatedly
0273   /// invalidating the same analyses as we unnest pass managers and adaptors.
0274   /// So we track the cross-SCC version of the preserved analyses here from any
0275   /// code that does direct invalidation of SCC analyses, and then use it
0276   /// whenever we move forward in the post-order walk of SCCs before running
0277   /// passes over the new SCC.
0278   PreservedAnalyses CrossSCCPA;
0279 
0280   /// A hacky area where the inliner can retain history about inlining
0281   /// decisions that mutated the call graph's SCC structure in order to avoid
0282   /// infinite inlining. See the comments in the inliner's CG update logic.
0283   ///
0284   /// FIXME: Keeping this here seems like a big layering issue, we should look
0285   /// for a better technique.
0286   SmallDenseSet<std::pair<LazyCallGraph::Node *, LazyCallGraph::SCC *>, 4>
0287       &InlinedInternalEdges;
0288 
0289   /// Functions that a pass has considered to be dead to be removed at the end
0290   /// of the call graph walk in batch.
0291   SmallVector<Function *, 4> &DeadFunctions;
0292 
0293   /// Weak VHs to keep track of indirect calls for the purposes of detecting
0294   /// devirtualization.
0295   ///
0296   /// This is a map to avoid having duplicate entries. If a Value is
0297   /// deallocated, its corresponding WeakTrackingVH will be nulled out. When
0298   /// checking if a Value is in the map or not, also check if the corresponding
0299   /// WeakTrackingVH is null to avoid issues with a new Value sharing the same
0300   /// address as a deallocated one.
0301   SmallMapVector<Value *, WeakTrackingVH, 16> IndirectVHs;
0302 };
0303 
0304 /// The core module pass which does a post-order walk of the SCCs and
0305 /// runs a CGSCC pass over each one.
0306 ///
0307 /// Designed to allow composition of a CGSCCPass(Manager) and
0308 /// a ModulePassManager. Note that this pass must be run with a module analysis
0309 /// manager as it uses the LazyCallGraph analysis. It will also run the
0310 /// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC
0311 /// pass over the module to enable a \c FunctionAnalysisManager to be used
0312 /// within this run safely.
0313 class ModuleToPostOrderCGSCCPassAdaptor
0314     : public PassInfoMixin<ModuleToPostOrderCGSCCPassAdaptor> {
0315 public:
0316   using PassConceptT =
0317       detail::PassConcept<LazyCallGraph::SCC, CGSCCAnalysisManager,
0318                           LazyCallGraph &, CGSCCUpdateResult &>;
0319 
0320   explicit ModuleToPostOrderCGSCCPassAdaptor(std::unique_ptr<PassConceptT> Pass)
0321       : Pass(std::move(Pass)) {}
0322 
0323   ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
0324       : Pass(std::move(Arg.Pass)) {}
0325 
0326   friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
0327                    ModuleToPostOrderCGSCCPassAdaptor &RHS) {
0328     std::swap(LHS.Pass, RHS.Pass);
0329   }
0330 
0331   ModuleToPostOrderCGSCCPassAdaptor &
0332   operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
0333     swap(*this, RHS);
0334     return *this;
0335   }
0336 
0337   /// Runs the CGSCC pass across every SCC in the module.
0338   PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
0339 
0340   void printPipeline(raw_ostream &OS,
0341                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
0342     OS << "cgscc(";
0343     Pass->printPipeline(OS, MapClassName2PassName);
0344     OS << ')';
0345   }
0346 
0347   static bool isRequired() { return true; }
0348 
0349 private:
0350   std::unique_ptr<PassConceptT> Pass;
0351 };
0352 
0353 /// A function to deduce a function pass type and wrap it in the
0354 /// templated adaptor.
0355 template <typename CGSCCPassT>
0356 ModuleToPostOrderCGSCCPassAdaptor
0357 createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT &&Pass) {
0358   using PassModelT =
0359       detail::PassModel<LazyCallGraph::SCC, CGSCCPassT, CGSCCAnalysisManager,
0360                         LazyCallGraph &, CGSCCUpdateResult &>;
0361   // Do not use make_unique, it causes too many template instantiations,
0362   // causing terrible compile times.
0363   return ModuleToPostOrderCGSCCPassAdaptor(
0364       std::unique_ptr<ModuleToPostOrderCGSCCPassAdaptor::PassConceptT>(
0365           new PassModelT(std::forward<CGSCCPassT>(Pass))));
0366 }
0367 
0368 /// A proxy from a \c FunctionAnalysisManager to an \c SCC.
0369 ///
0370 /// When a module pass runs and triggers invalidation, both the CGSCC and
0371 /// Function analysis manager proxies on the module get an invalidation event.
0372 /// We don't want to fully duplicate responsibility for most of the
0373 /// invalidation logic. Instead, this layer is only responsible for SCC-local
0374 /// invalidation events. We work with the module's FunctionAnalysisManager to
0375 /// invalidate function analyses.
0376 class FunctionAnalysisManagerCGSCCProxy
0377     : public AnalysisInfoMixin<FunctionAnalysisManagerCGSCCProxy> {
0378 public:
0379   class Result {
0380   public:
0381     explicit Result() : FAM(nullptr) {}
0382     explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
0383 
0384     void updateFAM(FunctionAnalysisManager &FAM) { this->FAM = &FAM; }
0385     /// Accessor for the analysis manager.
0386     FunctionAnalysisManager &getManager() {
0387       assert(FAM);
0388       return *FAM;
0389     }
0390 
0391     bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
0392                     CGSCCAnalysisManager::Invalidator &Inv);
0393 
0394   private:
0395     FunctionAnalysisManager *FAM;
0396   };
0397 
0398   /// Computes the \c FunctionAnalysisManager and stores it in the result proxy.
0399   Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &);
0400 
0401 private:
0402   friend AnalysisInfoMixin<FunctionAnalysisManagerCGSCCProxy>;
0403 
0404   static AnalysisKey Key;
0405 };
0406 
0407 extern template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;
0408 
0409 /// A proxy from a \c CGSCCAnalysisManager to a \c Function.
0410 using CGSCCAnalysisManagerFunctionProxy =
0411     OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;
0412 
0413 /// Helper to update the call graph after running a function pass.
0414 ///
0415 /// Function passes can only mutate the call graph in specific ways. This
0416 /// routine provides a helper that updates the call graph in those ways
0417 /// including returning whether any changes were made and populating a CG
0418 /// update result struct for the overall CGSCC walk.
0419 LazyCallGraph::SCC &updateCGAndAnalysisManagerForFunctionPass(
0420     LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
0421     CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
0422     FunctionAnalysisManager &FAM);
0423 
0424 /// Helper to update the call graph after running a CGSCC pass.
0425 ///
0426 /// CGSCC passes can only mutate the call graph in specific ways. This
0427 /// routine provides a helper that updates the call graph in those ways
0428 /// including returning whether any changes were made and populating a CG
0429 /// update result struct for the overall CGSCC walk.
0430 LazyCallGraph::SCC &updateCGAndAnalysisManagerForCGSCCPass(
0431     LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
0432     CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
0433     FunctionAnalysisManager &FAM);
0434 
0435 /// Adaptor that maps from a SCC to its functions.
0436 ///
0437 /// Designed to allow composition of a FunctionPass(Manager) and
0438 /// a CGSCCPassManager. Note that if this pass is constructed with a pointer
0439 /// to a \c CGSCCAnalysisManager it will run the
0440 /// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function
0441 /// pass over the SCC to enable a \c FunctionAnalysisManager to be used
0442 /// within this run safely.
0443 class CGSCCToFunctionPassAdaptor
0444     : public PassInfoMixin<CGSCCToFunctionPassAdaptor> {
0445 public:
0446   using PassConceptT = detail::PassConcept<Function, FunctionAnalysisManager>;
0447 
0448   explicit CGSCCToFunctionPassAdaptor(std::unique_ptr<PassConceptT> Pass,
0449                                       bool EagerlyInvalidate, bool NoRerun)
0450       : Pass(std::move(Pass)), EagerlyInvalidate(EagerlyInvalidate),
0451         NoRerun(NoRerun) {}
0452 
0453   CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
0454       : Pass(std::move(Arg.Pass)), EagerlyInvalidate(Arg.EagerlyInvalidate),
0455         NoRerun(Arg.NoRerun) {}
0456 
0457   friend void swap(CGSCCToFunctionPassAdaptor &LHS,
0458                    CGSCCToFunctionPassAdaptor &RHS) {
0459     std::swap(LHS.Pass, RHS.Pass);
0460   }
0461 
0462   CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
0463     swap(*this, RHS);
0464     return *this;
0465   }
0466 
0467   /// Runs the function pass across every function in the module.
0468   PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
0469                         LazyCallGraph &CG, CGSCCUpdateResult &UR);
0470 
0471   void printPipeline(raw_ostream &OS,
0472                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
0473     OS << "function";
0474     if (EagerlyInvalidate || NoRerun) {
0475       OS << "<";
0476       if (EagerlyInvalidate)
0477         OS << "eager-inv";
0478       if (EagerlyInvalidate && NoRerun)
0479         OS << ";";
0480       if (NoRerun)
0481         OS << "no-rerun";
0482       OS << ">";
0483     }
0484     OS << '(';
0485     Pass->printPipeline(OS, MapClassName2PassName);
0486     OS << ')';
0487   }
0488 
0489   static bool isRequired() { return true; }
0490 
0491 private:
0492   std::unique_ptr<PassConceptT> Pass;
0493   bool EagerlyInvalidate;
0494   bool NoRerun;
0495 };
0496 
0497 /// A function to deduce a function pass type and wrap it in the
0498 /// templated adaptor.
0499 template <typename FunctionPassT>
0500 CGSCCToFunctionPassAdaptor
0501 createCGSCCToFunctionPassAdaptor(FunctionPassT &&Pass,
0502                                  bool EagerlyInvalidate = false,
0503                                  bool NoRerun = false) {
0504   using PassModelT =
0505       detail::PassModel<Function, FunctionPassT, FunctionAnalysisManager>;
0506   // Do not use make_unique, it causes too many template instantiations,
0507   // causing terrible compile times.
0508   return CGSCCToFunctionPassAdaptor(
0509       std::unique_ptr<CGSCCToFunctionPassAdaptor::PassConceptT>(
0510           new PassModelT(std::forward<FunctionPassT>(Pass))),
0511       EagerlyInvalidate, NoRerun);
0512 }
0513 
0514 // A marker to determine if function passes should be run on a function within a
0515 // CGSCCToFunctionPassAdaptor. This is used to prevent running an expensive
0516 // function pass (manager) on a function multiple times if SCC mutations cause a
0517 // function to be visited multiple times and the function is not modified by
0518 // other SCC passes.
0519 class ShouldNotRunFunctionPassesAnalysis
0520     : public AnalysisInfoMixin<ShouldNotRunFunctionPassesAnalysis> {
0521 public:
0522   static AnalysisKey Key;
0523   struct Result {};
0524 
0525   Result run(Function &F, FunctionAnalysisManager &FAM) { return Result(); }
0526 };
0527 
0528 /// A helper that repeats an SCC pass each time an indirect call is refined to
0529 /// a direct call by that pass.
0530 ///
0531 /// While the CGSCC pass manager works to re-visit SCCs and RefSCCs as they
0532 /// change shape, we may also want to repeat an SCC pass if it simply refines
0533 /// an indirect call to a direct call, even if doing so does not alter the
0534 /// shape of the graph. Note that this only pertains to direct calls to
0535 /// functions where IPO across the SCC may be able to compute more precise
0536 /// results. For intrinsics, we assume scalar optimizations already can fully
0537 /// reason about them.
0538 ///
0539 /// This repetition has the potential to be very large however, as each one
0540 /// might refine a single call site. As a consequence, in practice we use an
0541 /// upper bound on the number of repetitions to limit things.
0542 class DevirtSCCRepeatedPass : public PassInfoMixin<DevirtSCCRepeatedPass> {
0543 public:
0544   using PassConceptT =
0545       detail::PassConcept<LazyCallGraph::SCC, CGSCCAnalysisManager,
0546                           LazyCallGraph &, CGSCCUpdateResult &>;
0547 
0548   explicit DevirtSCCRepeatedPass(std::unique_ptr<PassConceptT> Pass,
0549                                  int MaxIterations)
0550       : Pass(std::move(Pass)), MaxIterations(MaxIterations) {}
0551 
0552   /// Runs the wrapped pass up to \c MaxIterations on the SCC, iterating
0553   /// whenever an indirect call is refined.
0554   PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM,
0555                         LazyCallGraph &CG, CGSCCUpdateResult &UR);
0556 
0557   void printPipeline(raw_ostream &OS,
0558                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
0559     OS << "devirt<" << MaxIterations << ">(";
0560     Pass->printPipeline(OS, MapClassName2PassName);
0561     OS << ')';
0562   }
0563 
0564 private:
0565   std::unique_ptr<PassConceptT> Pass;
0566   int MaxIterations;
0567 };
0568 
0569 /// A function to deduce a function pass type and wrap it in the
0570 /// templated adaptor.
0571 template <typename CGSCCPassT>
0572 DevirtSCCRepeatedPass createDevirtSCCRepeatedPass(CGSCCPassT &&Pass,
0573                                                   int MaxIterations) {
0574   using PassModelT =
0575       detail::PassModel<LazyCallGraph::SCC, CGSCCPassT, CGSCCAnalysisManager,
0576                         LazyCallGraph &, CGSCCUpdateResult &>;
0577   // Do not use make_unique, it causes too many template instantiations,
0578   // causing terrible compile times.
0579   return DevirtSCCRepeatedPass(
0580       std::unique_ptr<DevirtSCCRepeatedPass::PassConceptT>(
0581           new PassModelT(std::forward<CGSCCPassT>(Pass))),
0582       MaxIterations);
0583 }
0584 
0585 // Clear out the debug logging macro.
0586 #undef DEBUG_TYPE
0587 
0588 } // end namespace llvm
0589 
0590 #endif // LLVM_ANALYSIS_CGSCCPASSMANAGER_H