LoopPassManager.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- LoopPassManager.h - Loop 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 a pipeline of passes over loops
  16. /// in LLVM IR.
  17. ///
  18. /// The primary loop pass pipeline is managed in a very particular way to
  19. /// provide a set of core guarantees:
  20. /// 1) Loops are, where possible, in simplified form.
  21. /// 2) Loops are *always* in LCSSA form.
  22. /// 3) A collection of Loop-specific analysis results are available:
  23. /// - LoopInfo
  24. /// - DominatorTree
  25. /// - ScalarEvolution
  26. /// - AAManager
  27. /// 4) All loop passes preserve #1 (where possible), #2, and #3.
  28. /// 5) Loop passes run over each loop in the loop nest from the innermost to
  29. /// the outermost. Specifically, all inner loops are processed before
  30. /// passes run over outer loops. When running the pipeline across an inner
  31. /// loop creates new inner loops, those are added and processed in this
  32. /// order as well.
  33. ///
  34. /// This process is designed to facilitate transformations which simplify,
  35. /// reduce, and remove loops. For passes which are more oriented towards
  36. /// optimizing loops, especially optimizing loop *nests* instead of single
  37. /// loops in isolation, this framework is less interesting.
  38. ///
  39. //===----------------------------------------------------------------------===//
  40. #ifndef LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H
  41. #define LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H
  42. #include "llvm/ADT/PriorityWorklist.h"
  43. #include "llvm/Analysis/LoopAnalysisManager.h"
  44. #include "llvm/Analysis/LoopInfo.h"
  45. #include "llvm/Analysis/LoopNestAnalysis.h"
  46. #include "llvm/IR/Dominators.h"
  47. #include "llvm/IR/PassInstrumentation.h"
  48. #include "llvm/IR/PassManager.h"
  49. #include "llvm/Transforms/Utils/LCSSA.h"
  50. #include "llvm/Transforms/Utils/LoopSimplify.h"
  51. #include "llvm/Transforms/Utils/LoopUtils.h"
  52. #include <memory>
  53. namespace llvm {
  54. // Forward declarations of an update tracking API used in the pass manager.
  55. class LPMUpdater;
  56. namespace {
  57. template <typename PassT>
  58. using HasRunOnLoopT = decltype(std::declval<PassT>().run(
  59. std::declval<Loop &>(), std::declval<LoopAnalysisManager &>(),
  60. std::declval<LoopStandardAnalysisResults &>(),
  61. std::declval<LPMUpdater &>()));
  62. } // namespace
  63. // Explicit specialization and instantiation declarations for the pass manager.
  64. // See the comments on the definition of the specialization for details on how
  65. // it differs from the primary template.
  66. template <>
  67. class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
  68. LPMUpdater &>
  69. : public PassInfoMixin<
  70. PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
  71. LPMUpdater &>> {
  72. public:
  73. /// Construct a pass manager.
  74. ///
  75. /// If \p DebugLogging is true, we'll log our progress to llvm::dbgs().
  76. explicit PassManager(bool DebugLogging = false)
  77. : DebugLogging(DebugLogging) {}
  78. // FIXME: These are equivalent to the default move constructor/move
  79. // assignment. However, using = default triggers linker errors due to the
  80. // explicit instantiations below. Find a way to use the default and remove the
  81. // duplicated code here.
  82. PassManager(PassManager &&Arg)
  83. : IsLoopNestPass(std::move(Arg.IsLoopNestPass)),
  84. LoopPasses(std::move(Arg.LoopPasses)),
  85. LoopNestPasses(std::move(Arg.LoopNestPasses)),
  86. DebugLogging(std::move(Arg.DebugLogging)) {}
  87. PassManager &operator=(PassManager &&RHS) {
  88. IsLoopNestPass = std::move(RHS.IsLoopNestPass);
  89. LoopPasses = std::move(RHS.LoopPasses);
  90. LoopNestPasses = std::move(RHS.LoopNestPasses);
  91. DebugLogging = std::move(RHS.DebugLogging);
  92. return *this;
  93. }
  94. PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
  95. LoopStandardAnalysisResults &AR, LPMUpdater &U);
  96. /// Add either a loop pass or a loop-nest pass to the pass manager. Append \p
  97. /// Pass to the list of loop passes if it has a dedicated \fn run() method for
  98. /// loops and to the list of loop-nest passes if the \fn run() method is for
  99. /// loop-nests instead. Also append whether \p Pass is loop-nest pass or not
  100. /// to the end of \var IsLoopNestPass so we can easily identify the types of
  101. /// passes in the pass manager later.
  102. template <typename PassT>
  103. std::enable_if_t<is_detected<HasRunOnLoopT, PassT>::value>
  104. addPass(PassT Pass) {
  105. using LoopPassModelT =
  106. detail::PassModel<Loop, PassT, PreservedAnalyses, LoopAnalysisManager,
  107. LoopStandardAnalysisResults &, LPMUpdater &>;
  108. IsLoopNestPass.push_back(false);
  109. LoopPasses.emplace_back(new LoopPassModelT(std::move(Pass)));
  110. }
  111. template <typename PassT>
  112. std::enable_if_t<!is_detected<HasRunOnLoopT, PassT>::value>
  113. addPass(PassT Pass) {
  114. using LoopNestPassModelT =
  115. detail::PassModel<LoopNest, PassT, PreservedAnalyses,
  116. LoopAnalysisManager, LoopStandardAnalysisResults &,
  117. LPMUpdater &>;
  118. IsLoopNestPass.push_back(true);
  119. LoopNestPasses.emplace_back(new LoopNestPassModelT(std::move(Pass)));
  120. }
  121. // Specializations of `addPass` for `RepeatedPass`. These are necessary since
  122. // `RepeatedPass` has a templated `run` method that will result in incorrect
  123. // detection of `HasRunOnLoopT`.
  124. template <typename PassT>
  125. std::enable_if_t<is_detected<HasRunOnLoopT, PassT>::value>
  126. addPass(RepeatedPass<PassT> Pass) {
  127. using RepeatedLoopPassModelT =
  128. detail::PassModel<Loop, RepeatedPass<PassT>, PreservedAnalyses,
  129. LoopAnalysisManager, LoopStandardAnalysisResults &,
  130. LPMUpdater &>;
  131. IsLoopNestPass.push_back(false);
  132. LoopPasses.emplace_back(new RepeatedLoopPassModelT(std::move(Pass)));
  133. }
  134. template <typename PassT>
  135. std::enable_if_t<!is_detected<HasRunOnLoopT, PassT>::value>
  136. addPass(RepeatedPass<PassT> Pass) {
  137. using RepeatedLoopNestPassModelT =
  138. detail::PassModel<LoopNest, RepeatedPass<PassT>, PreservedAnalyses,
  139. LoopAnalysisManager, LoopStandardAnalysisResults &,
  140. LPMUpdater &>;
  141. IsLoopNestPass.push_back(true);
  142. LoopNestPasses.emplace_back(
  143. new RepeatedLoopNestPassModelT(std::move(Pass)));
  144. }
  145. bool isEmpty() const { return LoopPasses.empty() && LoopNestPasses.empty(); }
  146. static bool isRequired() { return true; }
  147. size_t getNumLoopPasses() const { return LoopPasses.size(); }
  148. size_t getNumLoopNestPasses() const { return LoopNestPasses.size(); }
  149. protected:
  150. using LoopPassConceptT =
  151. detail::PassConcept<Loop, LoopAnalysisManager,
  152. LoopStandardAnalysisResults &, LPMUpdater &>;
  153. using LoopNestPassConceptT =
  154. detail::PassConcept<LoopNest, LoopAnalysisManager,
  155. LoopStandardAnalysisResults &, LPMUpdater &>;
  156. // BitVector that identifies whether the passes are loop passes or loop-nest
  157. // passes (true for loop-nest passes).
  158. BitVector IsLoopNestPass;
  159. std::vector<std::unique_ptr<LoopPassConceptT>> LoopPasses;
  160. std::vector<std::unique_ptr<LoopNestPassConceptT>> LoopNestPasses;
  161. /// Flag indicating whether we should do debug logging.
  162. bool DebugLogging;
  163. /// Run either a loop pass or a loop-nest pass. Returns `None` if
  164. /// PassInstrumentation's BeforePass returns false. Otherwise, returns the
  165. /// preserved analyses of the pass.
  166. template <typename IRUnitT, typename PassT>
  167. Optional<PreservedAnalyses>
  168. runSinglePass(IRUnitT &IR, PassT &Pass, LoopAnalysisManager &AM,
  169. LoopStandardAnalysisResults &AR, LPMUpdater &U,
  170. PassInstrumentation &PI);
  171. PreservedAnalyses runWithLoopNestPasses(Loop &L, LoopAnalysisManager &AM,
  172. LoopStandardAnalysisResults &AR,
  173. LPMUpdater &U);
  174. PreservedAnalyses runWithoutLoopNestPasses(Loop &L, LoopAnalysisManager &AM,
  175. LoopStandardAnalysisResults &AR,
  176. LPMUpdater &U);
  177. };
  178. /// The Loop pass manager.
  179. ///
  180. /// See the documentation for the PassManager template for details. It runs
  181. /// a sequence of Loop passes over each Loop that the manager is run over. This
  182. /// typedef serves as a convenient way to refer to this construct.
  183. typedef PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
  184. LPMUpdater &>
  185. LoopPassManager;
  186. /// A partial specialization of the require analysis template pass to forward
  187. /// the extra parameters from a transformation's run method to the
  188. /// AnalysisManager's getResult.
  189. template <typename AnalysisT>
  190. struct RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager,
  191. LoopStandardAnalysisResults &, LPMUpdater &>
  192. : PassInfoMixin<
  193. RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager,
  194. LoopStandardAnalysisResults &, LPMUpdater &>> {
  195. PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
  196. LoopStandardAnalysisResults &AR, LPMUpdater &) {
  197. (void)AM.template getResult<AnalysisT>(L, AR);
  198. return PreservedAnalyses::all();
  199. }
  200. };
  201. /// An alias template to easily name a require analysis loop pass.
  202. template <typename AnalysisT>
  203. using RequireAnalysisLoopPass =
  204. RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager,
  205. LoopStandardAnalysisResults &, LPMUpdater &>;
  206. class FunctionToLoopPassAdaptor;
  207. /// This class provides an interface for updating the loop pass manager based
  208. /// on mutations to the loop nest.
  209. ///
  210. /// A reference to an instance of this class is passed as an argument to each
  211. /// Loop pass, and Loop passes should use it to update LPM infrastructure if
  212. /// they modify the loop nest structure.
  213. ///
  214. /// \c LPMUpdater comes with two modes: the loop mode and the loop-nest mode. In
  215. /// loop mode, all the loops in the function will be pushed into the worklist
  216. /// and when new loops are added to the pipeline, their subloops are also
  217. /// inserted recursively. On the other hand, in loop-nest mode, only top-level
  218. /// loops are contained in the worklist and the addition of new (top-level)
  219. /// loops will not trigger the addition of their subloops.
  220. class LPMUpdater {
  221. public:
  222. /// This can be queried by loop passes which run other loop passes (like pass
  223. /// managers) to know whether the loop needs to be skipped due to updates to
  224. /// the loop nest.
  225. ///
  226. /// If this returns true, the loop object may have been deleted, so passes
  227. /// should take care not to touch the object.
  228. bool skipCurrentLoop() const { return SkipCurrentLoop; }
  229. /// Loop passes should use this method to indicate they have deleted a loop
  230. /// from the nest.
  231. ///
  232. /// Note that this loop must either be the current loop or a subloop of the
  233. /// current loop. This routine must be called prior to removing the loop from
  234. /// the loop nest.
  235. ///
  236. /// If this is called for the current loop, in addition to clearing any
  237. /// state, this routine will mark that the current loop should be skipped by
  238. /// the rest of the pass management infrastructure.
  239. void markLoopAsDeleted(Loop &L, llvm::StringRef Name) {
  240. assert((!LoopNestMode || L.isOutermost()) &&
  241. "L should be a top-level loop in loop-nest mode.");
  242. LAM.clear(L, Name);
  243. assert((&L == CurrentL || CurrentL->contains(&L)) &&
  244. "Cannot delete a loop outside of the "
  245. "subloop tree currently being processed.");
  246. if (&L == CurrentL)
  247. SkipCurrentLoop = true;
  248. }
  249. /// Loop passes should use this method to indicate they have added new child
  250. /// loops of the current loop.
  251. ///
  252. /// \p NewChildLoops must contain only the immediate children. Any nested
  253. /// loops within them will be visited in postorder as usual for the loop pass
  254. /// manager.
  255. void addChildLoops(ArrayRef<Loop *> NewChildLoops) {
  256. assert(!LoopNestMode &&
  257. "Child loops should not be pushed in loop-nest mode.");
  258. // Insert ourselves back into the worklist first, as this loop should be
  259. // revisited after all the children have been processed.
  260. Worklist.insert(CurrentL);
  261. #ifndef NDEBUG
  262. for (Loop *NewL : NewChildLoops)
  263. assert(NewL->getParentLoop() == CurrentL && "All of the new loops must "
  264. "be immediate children of "
  265. "the current loop!");
  266. #endif
  267. appendLoopsToWorklist(NewChildLoops, Worklist);
  268. // Also skip further processing of the current loop--it will be revisited
  269. // after all of its newly added children are accounted for.
  270. SkipCurrentLoop = true;
  271. }
  272. /// Loop passes should use this method to indicate they have added new
  273. /// sibling loops to the current loop.
  274. ///
  275. /// \p NewSibLoops must only contain the immediate sibling loops. Any nested
  276. /// loops within them will be visited in postorder as usual for the loop pass
  277. /// manager.
  278. void addSiblingLoops(ArrayRef<Loop *> NewSibLoops) {
  279. #ifndef NDEBUG
  280. for (Loop *NewL : NewSibLoops)
  281. assert(NewL->getParentLoop() == ParentL &&
  282. "All of the new loops must be siblings of the current loop!");
  283. #endif
  284. if (LoopNestMode)
  285. Worklist.insert(NewSibLoops);
  286. else
  287. appendLoopsToWorklist(NewSibLoops, Worklist);
  288. // No need to skip the current loop or revisit it, as sibling loops
  289. // shouldn't impact anything.
  290. }
  291. /// Restart the current loop.
  292. ///
  293. /// Loop passes should call this method to indicate the current loop has been
  294. /// sufficiently changed that it should be re-visited from the begining of
  295. /// the loop pass pipeline rather than continuing.
  296. void revisitCurrentLoop() {
  297. // Tell the currently in-flight pipeline to stop running.
  298. SkipCurrentLoop = true;
  299. // And insert ourselves back into the worklist.
  300. Worklist.insert(CurrentL);
  301. }
  302. private:
  303. friend class llvm::FunctionToLoopPassAdaptor;
  304. /// The \c FunctionToLoopPassAdaptor's worklist of loops to process.
  305. SmallPriorityWorklist<Loop *, 4> &Worklist;
  306. /// The analysis manager for use in the current loop nest.
  307. LoopAnalysisManager &LAM;
  308. Loop *CurrentL;
  309. bool SkipCurrentLoop;
  310. const bool LoopNestMode;
  311. #ifndef NDEBUG
  312. // In debug builds we also track the parent loop to implement asserts even in
  313. // the face of loop deletion.
  314. Loop *ParentL;
  315. #endif
  316. LPMUpdater(SmallPriorityWorklist<Loop *, 4> &Worklist,
  317. LoopAnalysisManager &LAM, bool LoopNestMode = false)
  318. : Worklist(Worklist), LAM(LAM), LoopNestMode(LoopNestMode) {}
  319. };
  320. template <typename IRUnitT, typename PassT>
  321. Optional<PreservedAnalyses> LoopPassManager::runSinglePass(
  322. IRUnitT &IR, PassT &Pass, LoopAnalysisManager &AM,
  323. LoopStandardAnalysisResults &AR, LPMUpdater &U, PassInstrumentation &PI) {
  324. // Check the PassInstrumentation's BeforePass callbacks before running the
  325. // pass, skip its execution completely if asked to (callback returns false).
  326. if (!PI.runBeforePass<IRUnitT>(*Pass, IR))
  327. return None;
  328. PreservedAnalyses PA;
  329. {
  330. TimeTraceScope TimeScope(Pass->name(), IR.getName());
  331. PA = Pass->run(IR, AM, AR, U);
  332. }
  333. // do not pass deleted Loop into the instrumentation
  334. if (U.skipCurrentLoop())
  335. PI.runAfterPassInvalidated<IRUnitT>(*Pass, PA);
  336. else
  337. PI.runAfterPass<IRUnitT>(*Pass, IR, PA);
  338. return PA;
  339. }
  340. /// Adaptor that maps from a function to its loops.
  341. ///
  342. /// Designed to allow composition of a LoopPass(Manager) and a
  343. /// FunctionPassManager. Note that if this pass is constructed with a \c
  344. /// FunctionAnalysisManager it will run the \c LoopAnalysisManagerFunctionProxy
  345. /// analysis prior to running the loop passes over the function to enable a \c
  346. /// LoopAnalysisManager to be used within this run safely.
  347. ///
  348. /// The adaptor comes with two modes: the loop mode and the loop-nest mode, and
  349. /// the worklist updater lived inside will be in the same mode as the adaptor
  350. /// (refer to the documentation of \c LPMUpdater for more detailed explanation).
  351. /// Specifically, in loop mode, all loops in the funciton will be pushed into
  352. /// the worklist and processed by \p Pass, while only top-level loops are
  353. /// processed in loop-nest mode. Please refer to the various specializations of
  354. /// \fn createLoopFunctionToLoopPassAdaptor to see when loop mode and loop-nest
  355. /// mode are used.
  356. class FunctionToLoopPassAdaptor
  357. : public PassInfoMixin<FunctionToLoopPassAdaptor> {
  358. public:
  359. using PassConceptT =
  360. detail::PassConcept<Loop, LoopAnalysisManager,
  361. LoopStandardAnalysisResults &, LPMUpdater &>;
  362. explicit FunctionToLoopPassAdaptor(std::unique_ptr<PassConceptT> Pass,
  363. bool UseMemorySSA = false,
  364. bool UseBlockFrequencyInfo = false,
  365. bool DebugLogging = false,
  366. bool LoopNestMode = false)
  367. : Pass(std::move(Pass)), LoopCanonicalizationFPM(DebugLogging),
  368. UseMemorySSA(UseMemorySSA),
  369. UseBlockFrequencyInfo(UseBlockFrequencyInfo),
  370. LoopNestMode(LoopNestMode) {
  371. LoopCanonicalizationFPM.addPass(LoopSimplifyPass());
  372. LoopCanonicalizationFPM.addPass(LCSSAPass());
  373. }
  374. /// Runs the loop passes across every loop in the function.
  375. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
  376. static bool isRequired() { return true; }
  377. bool isLoopNestMode() const { return LoopNestMode; }
  378. private:
  379. std::unique_ptr<PassConceptT> Pass;
  380. FunctionPassManager LoopCanonicalizationFPM;
  381. bool UseMemorySSA = false;
  382. bool UseBlockFrequencyInfo = false;
  383. const bool LoopNestMode;
  384. };
  385. /// A function to deduce a loop pass type and wrap it in the templated
  386. /// adaptor.
  387. ///
  388. /// If \p Pass is a loop pass, the returned adaptor will be in loop mode.
  389. template <typename LoopPassT>
  390. inline std::enable_if_t<is_detected<HasRunOnLoopT, LoopPassT>::value,
  391. FunctionToLoopPassAdaptor>
  392. createFunctionToLoopPassAdaptor(LoopPassT Pass, bool UseMemorySSA = false,
  393. bool UseBlockFrequencyInfo = false,
  394. bool DebugLogging = false) {
  395. using PassModelT =
  396. detail::PassModel<Loop, LoopPassT, PreservedAnalyses, LoopAnalysisManager,
  397. LoopStandardAnalysisResults &, LPMUpdater &>;
  398. return FunctionToLoopPassAdaptor(
  399. std::make_unique<PassModelT>(std::move(Pass)), UseMemorySSA,
  400. UseBlockFrequencyInfo, DebugLogging, false);
  401. }
  402. /// If \p Pass is a loop-nest pass, \p Pass will first be wrapped into a
  403. /// \c LoopPassManager and the returned adaptor will be in loop-nest mode.
  404. template <typename LoopNestPassT>
  405. inline std::enable_if_t<!is_detected<HasRunOnLoopT, LoopNestPassT>::value,
  406. FunctionToLoopPassAdaptor>
  407. createFunctionToLoopPassAdaptor(LoopNestPassT Pass, bool UseMemorySSA = false,
  408. bool UseBlockFrequencyInfo = false,
  409. bool DebugLogging = false) {
  410. LoopPassManager LPM(DebugLogging);
  411. LPM.addPass(std::move(Pass));
  412. using PassModelT =
  413. detail::PassModel<Loop, LoopPassManager, PreservedAnalyses,
  414. LoopAnalysisManager, LoopStandardAnalysisResults &,
  415. LPMUpdater &>;
  416. return FunctionToLoopPassAdaptor(std::make_unique<PassModelT>(std::move(LPM)),
  417. UseMemorySSA, UseBlockFrequencyInfo,
  418. DebugLogging, true);
  419. }
  420. /// If \p Pass is an instance of \c LoopPassManager, the returned adaptor will
  421. /// be in loop-nest mode if the pass manager contains only loop-nest passes.
  422. template <>
  423. inline FunctionToLoopPassAdaptor
  424. createFunctionToLoopPassAdaptor<LoopPassManager>(LoopPassManager LPM,
  425. bool UseMemorySSA,
  426. bool UseBlockFrequencyInfo,
  427. bool DebugLogging) {
  428. // Check if LPM contains any loop pass and if it does not, returns an adaptor
  429. // in loop-nest mode.
  430. using PassModelT =
  431. detail::PassModel<Loop, LoopPassManager, PreservedAnalyses,
  432. LoopAnalysisManager, LoopStandardAnalysisResults &,
  433. LPMUpdater &>;
  434. bool LoopNestMode = (LPM.getNumLoopPasses() == 0);
  435. return FunctionToLoopPassAdaptor(std::make_unique<PassModelT>(std::move(LPM)),
  436. UseMemorySSA, UseBlockFrequencyInfo,
  437. DebugLogging, LoopNestMode);
  438. }
  439. /// Pass for printing a loop's contents as textual IR.
  440. class PrintLoopPass : public PassInfoMixin<PrintLoopPass> {
  441. raw_ostream &OS;
  442. std::string Banner;
  443. public:
  444. PrintLoopPass();
  445. PrintLoopPass(raw_ostream &OS, const std::string &Banner = "");
  446. PreservedAnalyses run(Loop &L, LoopAnalysisManager &,
  447. LoopStandardAnalysisResults &, LPMUpdater &);
  448. };
  449. }
  450. #endif // LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H
  451. #ifdef __GNUC__
  452. #pragma GCC diagnostic pop
  453. #endif