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

source code of llvm/include/llvm/Transforms/Scalar/LoopPassManager.h