Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:42

0001 //===- LoopPassManager.h - Loop 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 a pipeline of passes over loops
0011 /// in LLVM IR.
0012 ///
0013 /// The primary loop pass pipeline is managed in a very particular way to
0014 /// provide a set of core guarantees:
0015 /// 1) Loops are, where possible, in simplified form.
0016 /// 2) Loops are *always* in LCSSA form.
0017 /// 3) A collection of Loop-specific analysis results are available:
0018 ///    - LoopInfo
0019 ///    - DominatorTree
0020 ///    - ScalarEvolution
0021 ///    - AAManager
0022 /// 4) All loop passes preserve #1 (where possible), #2, and #3.
0023 /// 5) Loop passes run over each loop in the loop nest from the innermost to
0024 ///    the outermost. Specifically, all inner loops are processed before
0025 ///    passes run over outer loops. When running the pipeline across an inner
0026 ///    loop creates new inner loops, those are added and processed in this
0027 ///    order as well.
0028 ///
0029 /// This process is designed to facilitate transformations which simplify,
0030 /// reduce, and remove loops. For passes which are more oriented towards
0031 /// optimizing loops, especially optimizing loop *nests* instead of single
0032 /// loops in isolation, this framework is less interesting.
0033 ///
0034 //===----------------------------------------------------------------------===//
0035 
0036 #ifndef LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H
0037 #define LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H
0038 
0039 #include "llvm/ADT/PriorityWorklist.h"
0040 #include "llvm/Analysis/LoopAnalysisManager.h"
0041 #include "llvm/Analysis/LoopInfo.h"
0042 #include "llvm/Analysis/LoopNestAnalysis.h"
0043 #include "llvm/IR/PassManager.h"
0044 #include "llvm/IR/PassInstrumentation.h"
0045 #include "llvm/Transforms/Utils/LCSSA.h"
0046 #include "llvm/Transforms/Utils/LoopSimplify.h"
0047 #include "llvm/Transforms/Utils/LoopUtils.h"
0048 #include <memory>
0049 
0050 namespace llvm {
0051 
0052 // Forward declarations of an update tracking API used in the pass manager.
0053 class LPMUpdater;
0054 class PassInstrumentation;
0055 
0056 namespace {
0057 
0058 template <typename PassT>
0059 using HasRunOnLoopT = decltype(std::declval<PassT>().run(
0060     std::declval<Loop &>(), std::declval<LoopAnalysisManager &>(),
0061     std::declval<LoopStandardAnalysisResults &>(),
0062     std::declval<LPMUpdater &>()));
0063 
0064 } // namespace
0065 
0066 // Explicit specialization and instantiation declarations for the pass manager.
0067 // See the comments on the definition of the specialization for details on how
0068 // it differs from the primary template.
0069 template <>
0070 class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
0071                   LPMUpdater &>
0072     : public PassInfoMixin<
0073           PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
0074                       LPMUpdater &>> {
0075 public:
0076   explicit PassManager() = default;
0077 
0078   // FIXME: These are equivalent to the default move constructor/move
0079   // assignment. However, using = default triggers linker errors due to the
0080   // explicit instantiations below. Find a way to use the default and remove the
0081   // duplicated code here.
0082   PassManager(PassManager &&Arg)
0083       : IsLoopNestPass(std::move(Arg.IsLoopNestPass)),
0084         LoopPasses(std::move(Arg.LoopPasses)),
0085         LoopNestPasses(std::move(Arg.LoopNestPasses)) {}
0086 
0087   PassManager &operator=(PassManager &&RHS) {
0088     IsLoopNestPass = std::move(RHS.IsLoopNestPass);
0089     LoopPasses = std::move(RHS.LoopPasses);
0090     LoopNestPasses = std::move(RHS.LoopNestPasses);
0091     return *this;
0092   }
0093 
0094   PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
0095                         LoopStandardAnalysisResults &AR, LPMUpdater &U);
0096 
0097   void printPipeline(raw_ostream &OS,
0098                      function_ref<StringRef(StringRef)> MapClassName2PassName);
0099   /// Add either a loop pass or a loop-nest pass to the pass manager. Append \p
0100   /// Pass to the list of loop passes if it has a dedicated \fn run() method for
0101   /// loops and to the list of loop-nest passes if the \fn run() method is for
0102   /// loop-nests instead. Also append whether \p Pass is loop-nest pass or not
0103   /// to the end of \var IsLoopNestPass so we can easily identify the types of
0104   /// passes in the pass manager later.
0105   template <typename PassT>
0106   LLVM_ATTRIBUTE_MINSIZE
0107       std::enable_if_t<is_detected<HasRunOnLoopT, PassT>::value>
0108       addPass(PassT &&Pass) {
0109     using LoopPassModelT =
0110         detail::PassModel<Loop, PassT, LoopAnalysisManager,
0111                           LoopStandardAnalysisResults &, LPMUpdater &>;
0112     IsLoopNestPass.push_back(false);
0113     // Do not use make_unique or emplace_back, they cause too many template
0114     // instantiations, causing terrible compile times.
0115     LoopPasses.push_back(std::unique_ptr<LoopPassConceptT>(
0116         new LoopPassModelT(std::forward<PassT>(Pass))));
0117   }
0118 
0119   template <typename PassT>
0120   LLVM_ATTRIBUTE_MINSIZE
0121       std::enable_if_t<!is_detected<HasRunOnLoopT, PassT>::value>
0122       addPass(PassT &&Pass) {
0123     using LoopNestPassModelT =
0124         detail::PassModel<LoopNest, PassT, LoopAnalysisManager,
0125                           LoopStandardAnalysisResults &, LPMUpdater &>;
0126     IsLoopNestPass.push_back(true);
0127     // Do not use make_unique or emplace_back, they cause too many template
0128     // instantiations, causing terrible compile times.
0129     LoopNestPasses.push_back(std::unique_ptr<LoopNestPassConceptT>(
0130         new LoopNestPassModelT(std::forward<PassT>(Pass))));
0131   }
0132 
0133   bool isEmpty() const { return LoopPasses.empty() && LoopNestPasses.empty(); }
0134 
0135   static bool isRequired() { return true; }
0136 
0137   size_t getNumLoopPasses() const { return LoopPasses.size(); }
0138   size_t getNumLoopNestPasses() const { return LoopNestPasses.size(); }
0139 
0140 protected:
0141   using LoopPassConceptT =
0142       detail::PassConcept<Loop, LoopAnalysisManager,
0143                           LoopStandardAnalysisResults &, LPMUpdater &>;
0144   using LoopNestPassConceptT =
0145       detail::PassConcept<LoopNest, LoopAnalysisManager,
0146                           LoopStandardAnalysisResults &, LPMUpdater &>;
0147 
0148   // BitVector that identifies whether the passes are loop passes or loop-nest
0149   // passes (true for loop-nest passes).
0150   BitVector IsLoopNestPass;
0151   std::vector<std::unique_ptr<LoopPassConceptT>> LoopPasses;
0152   std::vector<std::unique_ptr<LoopNestPassConceptT>> LoopNestPasses;
0153 
0154   /// Run either a loop pass or a loop-nest pass. Returns `std::nullopt` if
0155   /// PassInstrumentation's BeforePass returns false. Otherwise, returns the
0156   /// preserved analyses of the pass.
0157   template <typename IRUnitT, typename PassT>
0158   std::optional<PreservedAnalyses>
0159   runSinglePass(IRUnitT &IR, PassT &Pass, LoopAnalysisManager &AM,
0160                 LoopStandardAnalysisResults &AR, LPMUpdater &U,
0161                 PassInstrumentation &PI);
0162 
0163   PreservedAnalyses runWithLoopNestPasses(Loop &L, LoopAnalysisManager &AM,
0164                                           LoopStandardAnalysisResults &AR,
0165                                           LPMUpdater &U);
0166   PreservedAnalyses runWithoutLoopNestPasses(Loop &L, LoopAnalysisManager &AM,
0167                                              LoopStandardAnalysisResults &AR,
0168                                              LPMUpdater &U);
0169 
0170 private:
0171   static const Loop &getLoopFromIR(Loop &L) { return L; }
0172   static const Loop &getLoopFromIR(LoopNest &LN) {
0173     return LN.getOutermostLoop();
0174   }
0175 };
0176 
0177 /// The Loop pass manager.
0178 ///
0179 /// See the documentation for the PassManager template for details. It runs
0180 /// a sequence of Loop passes over each Loop that the manager is run over. This
0181 /// typedef serves as a convenient way to refer to this construct.
0182 typedef PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
0183                     LPMUpdater &>
0184     LoopPassManager;
0185 
0186 /// A partial specialization of the require analysis template pass to forward
0187 /// the extra parameters from a transformation's run method to the
0188 /// AnalysisManager's getResult.
0189 template <typename AnalysisT>
0190 struct RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager,
0191                            LoopStandardAnalysisResults &, LPMUpdater &>
0192     : PassInfoMixin<
0193           RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager,
0194                               LoopStandardAnalysisResults &, LPMUpdater &>> {
0195   PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
0196                         LoopStandardAnalysisResults &AR, LPMUpdater &) {
0197     (void)AM.template getResult<AnalysisT>(L, AR);
0198     return PreservedAnalyses::all();
0199   }
0200   void printPipeline(raw_ostream &OS,
0201                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
0202     auto ClassName = AnalysisT::name();
0203     auto PassName = MapClassName2PassName(ClassName);
0204     OS << "require<" << PassName << '>';
0205   }
0206 };
0207 
0208 /// An alias template to easily name a require analysis loop pass.
0209 template <typename AnalysisT>
0210 using RequireAnalysisLoopPass =
0211     RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager,
0212                         LoopStandardAnalysisResults &, LPMUpdater &>;
0213 
0214 class FunctionToLoopPassAdaptor;
0215 
0216 /// This class provides an interface for updating the loop pass manager based
0217 /// on mutations to the loop nest.
0218 ///
0219 /// A reference to an instance of this class is passed as an argument to each
0220 /// Loop pass, and Loop passes should use it to update LPM infrastructure if
0221 /// they modify the loop nest structure.
0222 ///
0223 /// \c LPMUpdater comes with two modes: the loop mode and the loop-nest mode. In
0224 /// loop mode, all the loops in the function will be pushed into the worklist
0225 /// and when new loops are added to the pipeline, their subloops are also
0226 /// inserted recursively. On the other hand, in loop-nest mode, only top-level
0227 /// loops are contained in the worklist and the addition of new (top-level)
0228 /// loops will not trigger the addition of their subloops.
0229 class LPMUpdater {
0230 public:
0231   /// This can be queried by loop passes which run other loop passes (like pass
0232   /// managers) to know whether the loop needs to be skipped due to updates to
0233   /// the loop nest.
0234   ///
0235   /// If this returns true, the loop object may have been deleted, so passes
0236   /// should take care not to touch the object.
0237   bool skipCurrentLoop() const { return SkipCurrentLoop; }
0238 
0239   /// Loop passes should use this method to indicate they have deleted a loop
0240   /// from the nest.
0241   ///
0242   /// Note that this loop must either be the current loop or a subloop of the
0243   /// current loop. This routine must be called prior to removing the loop from
0244   /// the loop nest.
0245   ///
0246   /// If this is called for the current loop, in addition to clearing any
0247   /// state, this routine will mark that the current loop should be skipped by
0248   /// the rest of the pass management infrastructure.
0249   void markLoopAsDeleted(Loop &L, llvm::StringRef Name) {
0250     LAM.clear(L, Name);
0251     assert((&L == CurrentL || CurrentL->contains(&L)) &&
0252            "Cannot delete a loop outside of the "
0253            "subloop tree currently being processed.");
0254     if (&L == CurrentL)
0255       SkipCurrentLoop = true;
0256   }
0257 
0258   void setParentLoop(Loop *L) {
0259 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0260     ParentL = L;
0261 #endif
0262   }
0263 
0264   /// Loop passes should use this method to indicate they have added new child
0265   /// loops of the current loop.
0266   ///
0267   /// \p NewChildLoops must contain only the immediate children. Any nested
0268   /// loops within them will be visited in postorder as usual for the loop pass
0269   /// manager.
0270   void addChildLoops(ArrayRef<Loop *> NewChildLoops) {
0271     assert(!LoopNestMode &&
0272            "Child loops should not be pushed in loop-nest mode.");
0273     // Insert ourselves back into the worklist first, as this loop should be
0274     // revisited after all the children have been processed.
0275     Worklist.insert(CurrentL);
0276 
0277 #ifndef NDEBUG
0278     for (Loop *NewL : NewChildLoops)
0279       assert(NewL->getParentLoop() == CurrentL && "All of the new loops must "
0280                                                   "be immediate children of "
0281                                                   "the current loop!");
0282 #endif
0283 
0284     appendLoopsToWorklist(NewChildLoops, Worklist);
0285 
0286     // Also skip further processing of the current loop--it will be revisited
0287     // after all of its newly added children are accounted for.
0288     SkipCurrentLoop = true;
0289   }
0290 
0291   /// Loop passes should use this method to indicate they have added new
0292   /// sibling loops to the current loop.
0293   ///
0294   /// \p NewSibLoops must only contain the immediate sibling loops. Any nested
0295   /// loops within them will be visited in postorder as usual for the loop pass
0296   /// manager.
0297   void addSiblingLoops(ArrayRef<Loop *> NewSibLoops) {
0298 #if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
0299     for (Loop *NewL : NewSibLoops)
0300       assert(NewL->getParentLoop() == ParentL &&
0301              "All of the new loops must be siblings of the current loop!");
0302 #endif
0303 
0304     if (LoopNestMode)
0305       Worklist.insert(NewSibLoops);
0306     else
0307       appendLoopsToWorklist(NewSibLoops, Worklist);
0308 
0309     // No need to skip the current loop or revisit it, as sibling loops
0310     // shouldn't impact anything.
0311   }
0312 
0313   /// Restart the current loop.
0314   ///
0315   /// Loop passes should call this method to indicate the current loop has been
0316   /// sufficiently changed that it should be re-visited from the begining of
0317   /// the loop pass pipeline rather than continuing.
0318   void revisitCurrentLoop() {
0319     // Tell the currently in-flight pipeline to stop running.
0320     SkipCurrentLoop = true;
0321 
0322     // And insert ourselves back into the worklist.
0323     Worklist.insert(CurrentL);
0324   }
0325 
0326   bool isLoopNestChanged() const {
0327     return LoopNestChanged;
0328   }
0329 
0330   /// Loopnest passes should use this method to indicate if the
0331   /// loopnest has been modified.
0332   void markLoopNestChanged(bool Changed) {
0333     LoopNestChanged = Changed;
0334   }
0335 
0336 private:
0337   friend class llvm::FunctionToLoopPassAdaptor;
0338 
0339   /// The \c FunctionToLoopPassAdaptor's worklist of loops to process.
0340   SmallPriorityWorklist<Loop *, 4> &Worklist;
0341 
0342   /// The analysis manager for use in the current loop nest.
0343   LoopAnalysisManager &LAM;
0344 
0345   Loop *CurrentL;
0346   bool SkipCurrentLoop;
0347   const bool LoopNestMode;
0348   bool LoopNestChanged;
0349 
0350 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0351   // In debug builds we also track the parent loop to implement asserts even in
0352   // the face of loop deletion.
0353   Loop *ParentL;
0354 #endif
0355 
0356   LPMUpdater(SmallPriorityWorklist<Loop *, 4> &Worklist,
0357              LoopAnalysisManager &LAM, bool LoopNestMode = false,
0358              bool LoopNestChanged = false)
0359       : Worklist(Worklist), LAM(LAM), LoopNestMode(LoopNestMode),
0360         LoopNestChanged(LoopNestChanged) {}
0361 };
0362 
0363 template <typename IRUnitT, typename PassT>
0364 std::optional<PreservedAnalyses> LoopPassManager::runSinglePass(
0365     IRUnitT &IR, PassT &Pass, LoopAnalysisManager &AM,
0366     LoopStandardAnalysisResults &AR, LPMUpdater &U, PassInstrumentation &PI) {
0367   // Get the loop in case of Loop pass and outermost loop in case of LoopNest
0368   // pass which is to be passed to BeforePass and AfterPass call backs.
0369   const Loop &L = getLoopFromIR(IR);
0370   // Check the PassInstrumentation's BeforePass callbacks before running the
0371   // pass, skip its execution completely if asked to (callback returns false).
0372   if (!PI.runBeforePass<Loop>(*Pass, L))
0373     return std::nullopt;
0374 
0375   PreservedAnalyses PA = Pass->run(IR, AM, AR, U);
0376 
0377   // do not pass deleted Loop into the instrumentation
0378   if (U.skipCurrentLoop())
0379     PI.runAfterPassInvalidated<IRUnitT>(*Pass, PA);
0380   else
0381     PI.runAfterPass<Loop>(*Pass, L, PA);
0382   return PA;
0383 }
0384 
0385 /// Adaptor that maps from a function to its loops.
0386 ///
0387 /// Designed to allow composition of a LoopPass(Manager) and a
0388 /// FunctionPassManager. Note that if this pass is constructed with a \c
0389 /// FunctionAnalysisManager it will run the \c LoopAnalysisManagerFunctionProxy
0390 /// analysis prior to running the loop passes over the function to enable a \c
0391 /// LoopAnalysisManager to be used within this run safely.
0392 ///
0393 /// The adaptor comes with two modes: the loop mode and the loop-nest mode, and
0394 /// the worklist updater lived inside will be in the same mode as the adaptor
0395 /// (refer to the documentation of \c LPMUpdater for more detailed explanation).
0396 /// Specifically, in loop mode, all loops in the function will be pushed into
0397 /// the worklist and processed by \p Pass, while only top-level loops are
0398 /// processed in loop-nest mode. Please refer to the various specializations of
0399 /// \fn createLoopFunctionToLoopPassAdaptor to see when loop mode and loop-nest
0400 /// mode are used.
0401 class FunctionToLoopPassAdaptor
0402     : public PassInfoMixin<FunctionToLoopPassAdaptor> {
0403 public:
0404   using PassConceptT =
0405       detail::PassConcept<Loop, LoopAnalysisManager,
0406                           LoopStandardAnalysisResults &, LPMUpdater &>;
0407 
0408   explicit FunctionToLoopPassAdaptor(std::unique_ptr<PassConceptT> Pass,
0409                                      bool UseMemorySSA = false,
0410                                      bool UseBlockFrequencyInfo = false,
0411                                      bool UseBranchProbabilityInfo = false,
0412                                      bool LoopNestMode = false)
0413       : Pass(std::move(Pass)), UseMemorySSA(UseMemorySSA),
0414         UseBlockFrequencyInfo(UseBlockFrequencyInfo),
0415         UseBranchProbabilityInfo(UseBranchProbabilityInfo),
0416         LoopNestMode(LoopNestMode) {
0417     LoopCanonicalizationFPM.addPass(LoopSimplifyPass());
0418     LoopCanonicalizationFPM.addPass(LCSSAPass());
0419   }
0420 
0421   /// Runs the loop passes across every loop in the function.
0422   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0423   void printPipeline(raw_ostream &OS,
0424                      function_ref<StringRef(StringRef)> MapClassName2PassName);
0425 
0426   static bool isRequired() { return true; }
0427 
0428   bool isLoopNestMode() const { return LoopNestMode; }
0429 
0430 private:
0431   std::unique_ptr<PassConceptT> Pass;
0432 
0433   FunctionPassManager LoopCanonicalizationFPM;
0434 
0435   bool UseMemorySSA = false;
0436   bool UseBlockFrequencyInfo = false;
0437   bool UseBranchProbabilityInfo = false;
0438   const bool LoopNestMode;
0439 };
0440 
0441 /// A function to deduce a loop pass type and wrap it in the templated
0442 /// adaptor.
0443 ///
0444 /// If \p Pass is a loop pass, the returned adaptor will be in loop mode.
0445 template <typename LoopPassT>
0446 inline std::enable_if_t<is_detected<HasRunOnLoopT, LoopPassT>::value,
0447                         FunctionToLoopPassAdaptor>
0448 createFunctionToLoopPassAdaptor(LoopPassT &&Pass, bool UseMemorySSA = false,
0449                                 bool UseBlockFrequencyInfo = false,
0450                                 bool UseBranchProbabilityInfo = false) {
0451   using PassModelT =
0452       detail::PassModel<Loop, LoopPassT, LoopAnalysisManager,
0453                         LoopStandardAnalysisResults &, LPMUpdater &>;
0454   // Do not use make_unique, it causes too many template instantiations,
0455   // causing terrible compile times.
0456   return FunctionToLoopPassAdaptor(
0457       std::unique_ptr<FunctionToLoopPassAdaptor::PassConceptT>(
0458           new PassModelT(std::forward<LoopPassT>(Pass))),
0459       UseMemorySSA, UseBlockFrequencyInfo, UseBranchProbabilityInfo, false);
0460 }
0461 
0462 /// If \p Pass is a loop-nest pass, \p Pass will first be wrapped into a
0463 /// \c LoopPassManager and the returned adaptor will be in loop-nest mode.
0464 template <typename LoopNestPassT>
0465 inline std::enable_if_t<!is_detected<HasRunOnLoopT, LoopNestPassT>::value,
0466                         FunctionToLoopPassAdaptor>
0467 createFunctionToLoopPassAdaptor(LoopNestPassT &&Pass, bool UseMemorySSA = false,
0468                                 bool UseBlockFrequencyInfo = false,
0469                                 bool UseBranchProbabilityInfo = false) {
0470   LoopPassManager LPM;
0471   LPM.addPass(std::forward<LoopNestPassT>(Pass));
0472   using PassModelT =
0473       detail::PassModel<Loop, LoopPassManager, LoopAnalysisManager,
0474                         LoopStandardAnalysisResults &, LPMUpdater &>;
0475   // Do not use make_unique, it causes too many template instantiations,
0476   // causing terrible compile times.
0477   return FunctionToLoopPassAdaptor(
0478       std::unique_ptr<FunctionToLoopPassAdaptor::PassConceptT>(
0479           new PassModelT(std::move(LPM))),
0480       UseMemorySSA, UseBlockFrequencyInfo, UseBranchProbabilityInfo, true);
0481 }
0482 
0483 /// If \p Pass is an instance of \c LoopPassManager, the returned adaptor will
0484 /// be in loop-nest mode if the pass manager contains only loop-nest passes.
0485 template <>
0486 inline FunctionToLoopPassAdaptor
0487 createFunctionToLoopPassAdaptor<LoopPassManager>(
0488     LoopPassManager &&LPM, bool UseMemorySSA, bool UseBlockFrequencyInfo,
0489     bool UseBranchProbabilityInfo) {
0490   // Check if LPM contains any loop pass and if it does not, returns an adaptor
0491   // in loop-nest mode.
0492   using PassModelT =
0493       detail::PassModel<Loop, LoopPassManager, LoopAnalysisManager,
0494                         LoopStandardAnalysisResults &, LPMUpdater &>;
0495   bool LoopNestMode = (LPM.getNumLoopPasses() == 0);
0496   // Do not use make_unique, it causes too many template instantiations,
0497   // causing terrible compile times.
0498   return FunctionToLoopPassAdaptor(
0499       std::unique_ptr<FunctionToLoopPassAdaptor::PassConceptT>(
0500           new PassModelT(std::move(LPM))),
0501       UseMemorySSA, UseBlockFrequencyInfo, UseBranchProbabilityInfo,
0502       LoopNestMode);
0503 }
0504 
0505 /// Pass for printing a loop's contents as textual IR.
0506 class PrintLoopPass : public PassInfoMixin<PrintLoopPass> {
0507   raw_ostream &OS;
0508   std::string Banner;
0509 
0510 public:
0511   PrintLoopPass();
0512   PrintLoopPass(raw_ostream &OS, const std::string &Banner = "");
0513 
0514   PreservedAnalyses run(Loop &L, LoopAnalysisManager &,
0515                         LoopStandardAnalysisResults &, LPMUpdater &);
0516 };
0517 }
0518 
0519 #endif // LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H