CGSCCPassManager.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. /// \file
  14. ///
  15. /// This header provides classes for managing passes over SCCs of the call
  16. /// graph. These passes form an important component of LLVM's interprocedural
  17. /// optimizations. Because they operate on the SCCs of the call graph, and they
  18. /// traverse the graph in post-order, they can effectively do pair-wise
  19. /// interprocedural optimizations for all call edges in the program while
  20. /// incrementally refining it and improving the context of these pair-wise
  21. /// optimizations. At each call site edge, the callee has already been
  22. /// optimized as much as is possible. This in turn allows very accurate
  23. /// analysis of it for IPO.
  24. ///
  25. /// A secondary more general goal is to be able to isolate optimization on
  26. /// unrelated parts of the IR module. This is useful to ensure our
  27. /// optimizations are principled and don't miss oportunities where refinement
  28. /// of one part of the module influence transformations in another part of the
  29. /// module. But this is also useful if we want to parallelize the optimizations
  30. /// across common large module graph shapes which tend to be very wide and have
  31. /// large regions of unrelated cliques.
  32. ///
  33. /// To satisfy these goals, we use the LazyCallGraph which provides two graphs
  34. /// nested inside each other (and built lazily from the bottom-up): the call
  35. /// graph proper, and a reference graph. The reference graph is super set of
  36. /// the call graph and is a conservative approximation of what could through
  37. /// scalar or CGSCC transforms *become* the call graph. Using this allows us to
  38. /// ensure we optimize functions prior to them being introduced into the call
  39. /// graph by devirtualization or other technique, and thus ensures that
  40. /// subsequent pair-wise interprocedural optimizations observe the optimized
  41. /// form of these functions. The (potentially transitive) reference
  42. /// reachability used by the reference graph is a conservative approximation
  43. /// that still allows us to have independent regions of the graph.
  44. ///
  45. /// FIXME: There is one major drawback of the reference graph: in its naive
  46. /// form it is quadratic because it contains a distinct edge for each
  47. /// (potentially indirect) reference, even if are all through some common
  48. /// global table of function pointers. This can be fixed in a number of ways
  49. /// that essentially preserve enough of the normalization. While it isn't
  50. /// expected to completely preclude the usability of this, it will need to be
  51. /// addressed.
  52. ///
  53. ///
  54. /// All of these issues are made substantially more complex in the face of
  55. /// mutations to the call graph while optimization passes are being run. When
  56. /// mutations to the call graph occur we want to achieve two different things:
  57. ///
  58. /// - We need to update the call graph in-flight and invalidate analyses
  59. /// cached on entities in the graph. Because of the cache-based analysis
  60. /// design of the pass manager, it is essential to have stable identities for
  61. /// the elements of the IR that passes traverse, and to invalidate any
  62. /// analyses cached on these elements as the mutations take place.
  63. ///
  64. /// - We want to preserve the incremental and post-order traversal of the
  65. /// graph even as it is refined and mutated. This means we want optimization
  66. /// to observe the most refined form of the call graph and to do so in
  67. /// post-order.
  68. ///
  69. /// To address this, the CGSCC manager uses both worklists that can be expanded
  70. /// by passes which transform the IR, and provides invalidation tests to skip
  71. /// entries that become dead. This extra data is provided to every SCC pass so
  72. /// that it can carefully update the manager's traversal as the call graph
  73. /// mutates.
  74. ///
  75. /// We also provide support for running function passes within the CGSCC walk,
  76. /// and there we provide automatic update of the call graph including of the
  77. /// pass manager to reflect call graph changes that fall out naturally as part
  78. /// of scalar transformations.
  79. ///
  80. /// The patterns used to ensure the goals of post-order visitation of the fully
  81. /// refined graph:
  82. ///
  83. /// 1) Sink toward the "bottom" as the graph is refined. This means that any
  84. /// iteration continues in some valid post-order sequence after the mutation
  85. /// has altered the structure.
  86. ///
  87. /// 2) Enqueue in post-order, including the current entity. If the current
  88. /// entity's shape changes, it and everything after it in post-order needs
  89. /// to be visited to observe that shape.
  90. ///
  91. //===----------------------------------------------------------------------===//
  92. #ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H
  93. #define LLVM_ANALYSIS_CGSCCPASSMANAGER_H
  94. #include "llvm/ADT/DenseMap.h"
  95. #include "llvm/ADT/DenseSet.h"
  96. #include "llvm/ADT/MapVector.h"
  97. #include "llvm/ADT/PriorityWorklist.h"
  98. #include "llvm/ADT/STLExtras.h"
  99. #include "llvm/ADT/SmallPtrSet.h"
  100. #include "llvm/ADT/SmallVector.h"
  101. #include "llvm/Analysis/LazyCallGraph.h"
  102. #include "llvm/IR/Function.h"
  103. #include "llvm/IR/InstIterator.h"
  104. #include "llvm/IR/PassManager.h"
  105. #include "llvm/IR/ValueHandle.h"
  106. #include "llvm/Support/Debug.h"
  107. #include "llvm/Support/raw_ostream.h"
  108. #include <algorithm>
  109. #include <cassert>
  110. #include <utility>
  111. namespace llvm {
  112. struct CGSCCUpdateResult;
  113. class Module;
  114. // Allow debug logging in this inline function.
  115. #define DEBUG_TYPE "cgscc"
  116. /// Extern template declaration for the analysis set for this IR unit.
  117. extern template class AllAnalysesOn<LazyCallGraph::SCC>;
  118. extern template class AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>;
  119. /// The CGSCC analysis manager.
  120. ///
  121. /// See the documentation for the AnalysisManager template for detail
  122. /// documentation. This type serves as a convenient way to refer to this
  123. /// construct in the adaptors and proxies used to integrate this into the larger
  124. /// pass manager infrastructure.
  125. using CGSCCAnalysisManager =
  126. AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>;
  127. // Explicit specialization and instantiation declarations for the pass manager.
  128. // See the comments on the definition of the specialization for details on how
  129. // it differs from the primary template.
  130. template <>
  131. PreservedAnalyses
  132. PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
  133. CGSCCUpdateResult &>::run(LazyCallGraph::SCC &InitialC,
  134. CGSCCAnalysisManager &AM,
  135. LazyCallGraph &G, CGSCCUpdateResult &UR);
  136. extern template class PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager,
  137. LazyCallGraph &, CGSCCUpdateResult &>;
  138. /// The CGSCC pass manager.
  139. ///
  140. /// See the documentation for the PassManager template for details. It runs
  141. /// a sequence of SCC passes over each SCC that the manager is run over. This
  142. /// type serves as a convenient way to refer to this construct.
  143. using CGSCCPassManager =
  144. PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
  145. CGSCCUpdateResult &>;
  146. /// An explicit specialization of the require analysis template pass.
  147. template <typename AnalysisT>
  148. struct RequireAnalysisPass<AnalysisT, LazyCallGraph::SCC, CGSCCAnalysisManager,
  149. LazyCallGraph &, CGSCCUpdateResult &>
  150. : PassInfoMixin<RequireAnalysisPass<AnalysisT, LazyCallGraph::SCC,
  151. CGSCCAnalysisManager, LazyCallGraph &,
  152. CGSCCUpdateResult &>> {
  153. PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  154. LazyCallGraph &CG, CGSCCUpdateResult &) {
  155. (void)AM.template getResult<AnalysisT>(C, CG);
  156. return PreservedAnalyses::all();
  157. }
  158. };
  159. /// A proxy from a \c CGSCCAnalysisManager to a \c Module.
  160. using CGSCCAnalysisManagerModuleProxy =
  161. InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;
  162. /// We need a specialized result for the \c CGSCCAnalysisManagerModuleProxy so
  163. /// it can have access to the call graph in order to walk all the SCCs when
  164. /// invalidating things.
  165. template <> class CGSCCAnalysisManagerModuleProxy::Result {
  166. public:
  167. explicit Result(CGSCCAnalysisManager &InnerAM, LazyCallGraph &G)
  168. : InnerAM(&InnerAM), G(&G) {}
  169. /// Accessor for the analysis manager.
  170. CGSCCAnalysisManager &getManager() { return *InnerAM; }
  171. /// Handler for invalidation of the Module.
  172. ///
  173. /// If the proxy analysis itself is preserved, then we assume that the set of
  174. /// SCCs in the Module hasn't changed. Thus any pointers to SCCs in the
  175. /// CGSCCAnalysisManager are still valid, and we don't need to call \c clear
  176. /// on the CGSCCAnalysisManager.
  177. ///
  178. /// Regardless of whether this analysis is marked as preserved, all of the
  179. /// analyses in the \c CGSCCAnalysisManager are potentially invalidated based
  180. /// on the set of preserved analyses.
  181. bool invalidate(Module &M, const PreservedAnalyses &PA,
  182. ModuleAnalysisManager::Invalidator &Inv);
  183. private:
  184. CGSCCAnalysisManager *InnerAM;
  185. LazyCallGraph *G;
  186. };
  187. /// Provide a specialized run method for the \c CGSCCAnalysisManagerModuleProxy
  188. /// so it can pass the lazy call graph to the result.
  189. template <>
  190. CGSCCAnalysisManagerModuleProxy::Result
  191. CGSCCAnalysisManagerModuleProxy::run(Module &M, ModuleAnalysisManager &AM);
  192. // Ensure the \c CGSCCAnalysisManagerModuleProxy is provided as an extern
  193. // template.
  194. extern template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;
  195. extern template class OuterAnalysisManagerProxy<
  196. ModuleAnalysisManager, LazyCallGraph::SCC, LazyCallGraph &>;
  197. /// A proxy from a \c ModuleAnalysisManager to an \c SCC.
  198. using ModuleAnalysisManagerCGSCCProxy =
  199. OuterAnalysisManagerProxy<ModuleAnalysisManager, LazyCallGraph::SCC,
  200. LazyCallGraph &>;
  201. /// Support structure for SCC passes to communicate updates the call graph back
  202. /// to the CGSCC pass manager infrsatructure.
  203. ///
  204. /// The CGSCC pass manager runs SCC passes which are allowed to update the call
  205. /// graph and SCC structures. This means the structure the pass manager works
  206. /// on is mutating underneath it. In order to support that, there needs to be
  207. /// careful communication about the precise nature and ramifications of these
  208. /// updates to the pass management infrastructure.
  209. ///
  210. /// All SCC passes will have to accept a reference to the management layer's
  211. /// update result struct and use it to reflect the results of any CG updates
  212. /// performed.
  213. ///
  214. /// Passes which do not change the call graph structure in any way can just
  215. /// ignore this argument to their run method.
  216. struct CGSCCUpdateResult {
  217. /// Worklist of the RefSCCs queued for processing.
  218. ///
  219. /// When a pass refines the graph and creates new RefSCCs or causes them to
  220. /// have a different shape or set of component SCCs it should add the RefSCCs
  221. /// to this worklist so that we visit them in the refined form.
  222. ///
  223. /// This worklist is in reverse post-order, as we pop off the back in order
  224. /// to observe RefSCCs in post-order. When adding RefSCCs, clients should add
  225. /// them in reverse post-order.
  226. SmallPriorityWorklist<LazyCallGraph::RefSCC *, 1> &RCWorklist;
  227. /// Worklist of the SCCs queued for processing.
  228. ///
  229. /// When a pass refines the graph and creates new SCCs or causes them to have
  230. /// a different shape or set of component functions it should add the SCCs to
  231. /// this worklist so that we visit them in the refined form.
  232. ///
  233. /// Note that if the SCCs are part of a RefSCC that is added to the \c
  234. /// RCWorklist, they don't need to be added here as visiting the RefSCC will
  235. /// be sufficient to re-visit the SCCs within it.
  236. ///
  237. /// This worklist is in reverse post-order, as we pop off the back in order
  238. /// to observe SCCs in post-order. When adding SCCs, clients should add them
  239. /// in reverse post-order.
  240. SmallPriorityWorklist<LazyCallGraph::SCC *, 1> &CWorklist;
  241. /// The set of invalidated RefSCCs which should be skipped if they are found
  242. /// in \c RCWorklist.
  243. ///
  244. /// This is used to quickly prune out RefSCCs when they get deleted and
  245. /// happen to already be on the worklist. We use this primarily to avoid
  246. /// scanning the list and removing entries from it.
  247. SmallPtrSetImpl<LazyCallGraph::RefSCC *> &InvalidatedRefSCCs;
  248. /// The set of invalidated SCCs which should be skipped if they are found
  249. /// in \c CWorklist.
  250. ///
  251. /// This is used to quickly prune out SCCs when they get deleted and happen
  252. /// to already be on the worklist. We use this primarily to avoid scanning
  253. /// the list and removing entries from it.
  254. SmallPtrSetImpl<LazyCallGraph::SCC *> &InvalidatedSCCs;
  255. /// If non-null, the updated current \c RefSCC being processed.
  256. ///
  257. /// This is set when a graph refinement takes place an the "current" point in
  258. /// the graph moves "down" or earlier in the post-order walk. This will often
  259. /// cause the "current" RefSCC to be a newly created RefSCC object and the
  260. /// old one to be added to the above worklist. When that happens, this
  261. /// pointer is non-null and can be used to continue processing the "top" of
  262. /// the post-order walk.
  263. LazyCallGraph::RefSCC *UpdatedRC;
  264. /// If non-null, the updated current \c SCC being processed.
  265. ///
  266. /// This is set when a graph refinement takes place an the "current" point in
  267. /// the graph moves "down" or earlier in the post-order walk. This will often
  268. /// cause the "current" SCC to be a newly created SCC object and the old one
  269. /// to be added to the above worklist. When that happens, this pointer is
  270. /// non-null and can be used to continue processing the "top" of the
  271. /// post-order walk.
  272. LazyCallGraph::SCC *UpdatedC;
  273. /// Preserved analyses across SCCs.
  274. ///
  275. /// We specifically want to allow CGSCC passes to mutate ancestor IR
  276. /// (changing both the CG structure and the function IR itself). However,
  277. /// this means we need to take special care to correctly mark what analyses
  278. /// are preserved *across* SCCs. We have to track this out-of-band here
  279. /// because within the main `PassManeger` infrastructure we need to mark
  280. /// everything within an SCC as preserved in order to avoid repeatedly
  281. /// invalidating the same analyses as we unnest pass managers and adaptors.
  282. /// So we track the cross-SCC version of the preserved analyses here from any
  283. /// code that does direct invalidation of SCC analyses, and then use it
  284. /// whenever we move forward in the post-order walk of SCCs before running
  285. /// passes over the new SCC.
  286. PreservedAnalyses CrossSCCPA;
  287. /// A hacky area where the inliner can retain history about inlining
  288. /// decisions that mutated the call graph's SCC structure in order to avoid
  289. /// infinite inlining. See the comments in the inliner's CG update logic.
  290. ///
  291. /// FIXME: Keeping this here seems like a big layering issue, we should look
  292. /// for a better technique.
  293. SmallDenseSet<std::pair<LazyCallGraph::Node *, LazyCallGraph::SCC *>, 4>
  294. &InlinedInternalEdges;
  295. /// Weak VHs to keep track of indirect calls for the purposes of detecting
  296. /// devirtualization.
  297. ///
  298. /// This is a map to avoid having duplicate entries. If a Value is
  299. /// deallocated, its corresponding WeakTrackingVH will be nulled out. When
  300. /// checking if a Value is in the map or not, also check if the corresponding
  301. /// WeakTrackingVH is null to avoid issues with a new Value sharing the same
  302. /// address as a deallocated one.
  303. SmallMapVector<Value *, WeakTrackingVH, 16> IndirectVHs;
  304. };
  305. /// The core module pass which does a post-order walk of the SCCs and
  306. /// runs a CGSCC pass over each one.
  307. ///
  308. /// Designed to allow composition of a CGSCCPass(Manager) and
  309. /// a ModulePassManager. Note that this pass must be run with a module analysis
  310. /// manager as it uses the LazyCallGraph analysis. It will also run the
  311. /// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC
  312. /// pass over the module to enable a \c FunctionAnalysisManager to be used
  313. /// within this run safely.
  314. class ModuleToPostOrderCGSCCPassAdaptor
  315. : public PassInfoMixin<ModuleToPostOrderCGSCCPassAdaptor> {
  316. public:
  317. using PassConceptT =
  318. detail::PassConcept<LazyCallGraph::SCC, CGSCCAnalysisManager,
  319. LazyCallGraph &, CGSCCUpdateResult &>;
  320. explicit ModuleToPostOrderCGSCCPassAdaptor(std::unique_ptr<PassConceptT> Pass)
  321. : Pass(std::move(Pass)) {}
  322. ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
  323. : Pass(std::move(Arg.Pass)) {}
  324. friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
  325. ModuleToPostOrderCGSCCPassAdaptor &RHS) {
  326. std::swap(LHS.Pass, RHS.Pass);
  327. }
  328. ModuleToPostOrderCGSCCPassAdaptor &
  329. operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
  330. swap(*this, RHS);
  331. return *this;
  332. }
  333. /// Runs the CGSCC pass across every SCC in the module.
  334. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
  335. static bool isRequired() { return true; }
  336. private:
  337. std::unique_ptr<PassConceptT> Pass;
  338. };
  339. /// A function to deduce a function pass type and wrap it in the
  340. /// templated adaptor.
  341. template <typename CGSCCPassT>
  342. ModuleToPostOrderCGSCCPassAdaptor
  343. createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
  344. using PassModelT = detail::PassModel<LazyCallGraph::SCC, CGSCCPassT,
  345. PreservedAnalyses, CGSCCAnalysisManager,
  346. LazyCallGraph &, CGSCCUpdateResult &>;
  347. return ModuleToPostOrderCGSCCPassAdaptor(
  348. std::make_unique<PassModelT>(std::move(Pass)));
  349. }
  350. /// A proxy from a \c FunctionAnalysisManager to an \c SCC.
  351. ///
  352. /// When a module pass runs and triggers invalidation, both the CGSCC and
  353. /// Function analysis manager proxies on the module get an invalidation event.
  354. /// We don't want to fully duplicate responsibility for most of the
  355. /// invalidation logic. Instead, this layer is only responsible for SCC-local
  356. /// invalidation events. We work with the module's FunctionAnalysisManager to
  357. /// invalidate function analyses.
  358. class FunctionAnalysisManagerCGSCCProxy
  359. : public AnalysisInfoMixin<FunctionAnalysisManagerCGSCCProxy> {
  360. public:
  361. class Result {
  362. public:
  363. explicit Result() : FAM(nullptr) {}
  364. explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
  365. void updateFAM(FunctionAnalysisManager &FAM) { this->FAM = &FAM; }
  366. /// Accessor for the analysis manager.
  367. FunctionAnalysisManager &getManager() {
  368. assert(FAM);
  369. return *FAM;
  370. }
  371. bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
  372. CGSCCAnalysisManager::Invalidator &Inv);
  373. private:
  374. FunctionAnalysisManager *FAM;
  375. };
  376. /// Computes the \c FunctionAnalysisManager and stores it in the result proxy.
  377. Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &);
  378. private:
  379. friend AnalysisInfoMixin<FunctionAnalysisManagerCGSCCProxy>;
  380. static AnalysisKey Key;
  381. };
  382. extern template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;
  383. /// A proxy from a \c CGSCCAnalysisManager to a \c Function.
  384. using CGSCCAnalysisManagerFunctionProxy =
  385. OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;
  386. /// Helper to update the call graph after running a function pass.
  387. ///
  388. /// Function passes can only mutate the call graph in specific ways. This
  389. /// routine provides a helper that updates the call graph in those ways
  390. /// including returning whether any changes were made and populating a CG
  391. /// update result struct for the overall CGSCC walk.
  392. LazyCallGraph::SCC &updateCGAndAnalysisManagerForFunctionPass(
  393. LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
  394. CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
  395. FunctionAnalysisManager &FAM);
  396. /// Helper to update the call graph after running a CGSCC pass.
  397. ///
  398. /// CGSCC passes can only mutate the call graph in specific ways. This
  399. /// routine provides a helper that updates the call graph in those ways
  400. /// including returning whether any changes were made and populating a CG
  401. /// update result struct for the overall CGSCC walk.
  402. LazyCallGraph::SCC &updateCGAndAnalysisManagerForCGSCCPass(
  403. LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
  404. CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
  405. FunctionAnalysisManager &FAM);
  406. /// Adaptor that maps from a SCC to its functions.
  407. ///
  408. /// Designed to allow composition of a FunctionPass(Manager) and
  409. /// a CGSCCPassManager. Note that if this pass is constructed with a pointer
  410. /// to a \c CGSCCAnalysisManager it will run the
  411. /// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function
  412. /// pass over the SCC to enable a \c FunctionAnalysisManager to be used
  413. /// within this run safely.
  414. class CGSCCToFunctionPassAdaptor
  415. : public PassInfoMixin<CGSCCToFunctionPassAdaptor> {
  416. public:
  417. using PassConceptT = detail::PassConcept<Function, FunctionAnalysisManager>;
  418. explicit CGSCCToFunctionPassAdaptor(std::unique_ptr<PassConceptT> Pass)
  419. : Pass(std::move(Pass)) {}
  420. CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
  421. : Pass(std::move(Arg.Pass)) {}
  422. friend void swap(CGSCCToFunctionPassAdaptor &LHS,
  423. CGSCCToFunctionPassAdaptor &RHS) {
  424. std::swap(LHS.Pass, RHS.Pass);
  425. }
  426. CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
  427. swap(*this, RHS);
  428. return *this;
  429. }
  430. /// Runs the function pass across every function in the module.
  431. PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
  432. LazyCallGraph &CG, CGSCCUpdateResult &UR);
  433. static bool isRequired() { return true; }
  434. private:
  435. std::unique_ptr<PassConceptT> Pass;
  436. };
  437. /// A function to deduce a function pass type and wrap it in the
  438. /// templated adaptor.
  439. template <typename FunctionPassT>
  440. CGSCCToFunctionPassAdaptor
  441. createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
  442. using PassModelT =
  443. detail::PassModel<Function, FunctionPassT, PreservedAnalyses,
  444. FunctionAnalysisManager>;
  445. return CGSCCToFunctionPassAdaptor(
  446. std::make_unique<PassModelT>(std::move(Pass)));
  447. }
  448. /// A helper that repeats an SCC pass each time an indirect call is refined to
  449. /// a direct call by that pass.
  450. ///
  451. /// While the CGSCC pass manager works to re-visit SCCs and RefSCCs as they
  452. /// change shape, we may also want to repeat an SCC pass if it simply refines
  453. /// an indirect call to a direct call, even if doing so does not alter the
  454. /// shape of the graph. Note that this only pertains to direct calls to
  455. /// functions where IPO across the SCC may be able to compute more precise
  456. /// results. For intrinsics, we assume scalar optimizations already can fully
  457. /// reason about them.
  458. ///
  459. /// This repetition has the potential to be very large however, as each one
  460. /// might refine a single call site. As a consequence, in practice we use an
  461. /// upper bound on the number of repetitions to limit things.
  462. class DevirtSCCRepeatedPass : public PassInfoMixin<DevirtSCCRepeatedPass> {
  463. public:
  464. using PassConceptT =
  465. detail::PassConcept<LazyCallGraph::SCC, CGSCCAnalysisManager,
  466. LazyCallGraph &, CGSCCUpdateResult &>;
  467. explicit DevirtSCCRepeatedPass(std::unique_ptr<PassConceptT> Pass,
  468. int MaxIterations)
  469. : Pass(std::move(Pass)), MaxIterations(MaxIterations) {}
  470. /// Runs the wrapped pass up to \c MaxIterations on the SCC, iterating
  471. /// whenever an indirect call is refined.
  472. PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM,
  473. LazyCallGraph &CG, CGSCCUpdateResult &UR);
  474. private:
  475. std::unique_ptr<PassConceptT> Pass;
  476. int MaxIterations;
  477. };
  478. /// A function to deduce a function pass type and wrap it in the
  479. /// templated adaptor.
  480. template <typename CGSCCPassT>
  481. DevirtSCCRepeatedPass createDevirtSCCRepeatedPass(CGSCCPassT Pass,
  482. int MaxIterations) {
  483. using PassModelT = detail::PassModel<LazyCallGraph::SCC, CGSCCPassT,
  484. PreservedAnalyses, CGSCCAnalysisManager,
  485. LazyCallGraph &, CGSCCUpdateResult &>;
  486. return DevirtSCCRepeatedPass(std::make_unique<PassModelT>(std::move(Pass)),
  487. MaxIterations);
  488. }
  489. // Clear out the debug logging macro.
  490. #undef DEBUG_TYPE
  491. } // end namespace llvm
  492. #endif // LLVM_ANALYSIS_CGSCCPASSMANAGER_H
  493. #ifdef __GNUC__
  494. #pragma GCC diagnostic pop
  495. #endif