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, PreservedAnalyses, LoopAnalysisManager, 110 LoopStandardAnalysisResults &, LPMUpdater &>; 111 IsLoopNestPass.push_back(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(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, PreservedAnalyses, 124 LoopAnalysisManager, LoopStandardAnalysisResults &, 125 LPMUpdater &>; 126 IsLoopNestPass.push_back(true); 127 // Do not use make_unique or emplace_back, they cause too many template 128 // instantiations, causing terrible compile times. 129 LoopNestPasses.push_back(std::unique_ptr<LoopNestPassConceptT>( 130 new LoopNestPassModelT(std::forward<PassT>(Pass)))); 131 } 132 133 // Specializations of `addPass` for `RepeatedPass`. These are necessary since 134 // `RepeatedPass` has a templated `run` method that will result in incorrect 135 // detection of `HasRunOnLoopT`. 136 template <typename PassT> 137 LLVM_ATTRIBUTE_MINSIZE 138 std::enable_if_t<is_detected<HasRunOnLoopT, PassT>::value> 139 addPass(RepeatedPass<PassT> &&Pass) { 140 using RepeatedLoopPassModelT = 141 detail::PassModel<Loop, RepeatedPass<PassT>, PreservedAnalyses, 142 LoopAnalysisManager, LoopStandardAnalysisResults &, 143 LPMUpdater &>; 144 IsLoopNestPass.push_back(false); 145 // Do not use make_unique or emplace_back, they cause too many template 146 // instantiations, causing terrible compile times. 147 LoopPasses.push_back(std::unique_ptr<LoopPassConceptT>( 148 new RepeatedLoopPassModelT(std::move(Pass)))); 149 } 150 151 template <typename PassT> 152 LLVM_ATTRIBUTE_MINSIZE 153 std::enable_if_t<!is_detected<HasRunOnLoopT, PassT>::value> 154 addPass(RepeatedPass<PassT> &&Pass) { 155 using RepeatedLoopNestPassModelT = 156 detail::PassModel<LoopNest, RepeatedPass<PassT>, PreservedAnalyses, 157 LoopAnalysisManager, LoopStandardAnalysisResults &, 158 LPMUpdater &>; 159 IsLoopNestPass.push_back(true); 160 // Do not use make_unique or emplace_back, they cause too many template 161 // instantiations, causing terrible compile times. 162 LoopNestPasses.push_back(std::unique_ptr<LoopNestPassConceptT>( 163 new RepeatedLoopNestPassModelT(std::move(Pass)))); 164 } 165 166 bool isEmpty() const { return LoopPasses.empty() && LoopNestPasses.empty(); } 167 168 static bool isRequired() { return true; } 169 170 size_t getNumLoopPasses() const { return LoopPasses.size(); } 171 size_t getNumLoopNestPasses() const { return LoopNestPasses.size(); } 172 173protected: 174 using LoopPassConceptT = 175 detail::PassConcept<Loop, LoopAnalysisManager, 176 LoopStandardAnalysisResults &, LPMUpdater &>; 177 using LoopNestPassConceptT = 178 detail::PassConcept<LoopNest, LoopAnalysisManager, 179 LoopStandardAnalysisResults &, LPMUpdater &>; 180 181 // BitVector that identifies whether the passes are loop passes or loop-nest 182 // passes (true for loop-nest passes). 183 BitVector IsLoopNestPass; 184 std::vector<std::unique_ptr<LoopPassConceptT>> LoopPasses; 185 std::vector<std::unique_ptr<LoopNestPassConceptT>> LoopNestPasses; 186 187 /// Run either a loop pass or a loop-nest pass. Returns `std::nullopt` if 188 /// PassInstrumentation's BeforePass returns false. Otherwise, returns the 189 /// preserved analyses of the pass. 190 template <typename IRUnitT, typename PassT> 191 std::optional<PreservedAnalyses> 192 runSinglePass(IRUnitT &IR, PassT &Pass, LoopAnalysisManager &AM, 193 LoopStandardAnalysisResults &AR, LPMUpdater &U, 194 PassInstrumentation &PI); 195 196 PreservedAnalyses runWithLoopNestPasses(Loop &L, LoopAnalysisManager &AM, 197 LoopStandardAnalysisResults &AR, 198 LPMUpdater &U); 199 PreservedAnalyses runWithoutLoopNestPasses(Loop &L, LoopAnalysisManager &AM, 200 LoopStandardAnalysisResults &AR, 201 LPMUpdater &U); 202 203private: 204 static const Loop &getLoopFromIR(Loop &L) { return L; } 205 static const Loop &getLoopFromIR(LoopNest &LN) { 206 return LN.getOutermostLoop(); 207 } 208}; 209 210/// The Loop pass manager. 211/// 212/// See the documentation for the PassManager template for details. It runs 213/// a sequence of Loop passes over each Loop that the manager is run over. This 214/// typedef serves as a convenient way to refer to this construct. 215typedef PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &, 216 LPMUpdater &> 217 LoopPassManager; 218 219/// A partial specialization of the require analysis template pass to forward 220/// the extra parameters from a transformation's run method to the 221/// AnalysisManager's getResult. 222template <typename AnalysisT> 223struct RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager, 224 LoopStandardAnalysisResults &, LPMUpdater &> 225 : PassInfoMixin< 226 RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager, 227 LoopStandardAnalysisResults &, LPMUpdater &>> { 228 PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, 229 LoopStandardAnalysisResults &AR, LPMUpdater &) { 230 (void)AM.template getResult<AnalysisT>(L, AR); 231 return PreservedAnalyses::all(); 232 } 233 void printPipeline(raw_ostream &OS, 234 function_ref<StringRef(StringRef)> MapClassName2PassName) { 235 auto ClassName = AnalysisT::name(); 236 auto PassName = MapClassName2PassName(ClassName); 237 OS << "require<" << PassName << ">"; 238 } 239}; 240 241/// An alias template to easily name a require analysis loop pass. 242template <typename AnalysisT> 243using RequireAnalysisLoopPass = 244 RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager, 245 LoopStandardAnalysisResults &, LPMUpdater &>; 246 247class FunctionToLoopPassAdaptor; 248 249/// This class provides an interface for updating the loop pass manager based 250/// on mutations to the loop nest. 251/// 252/// A reference to an instance of this class is passed as an argument to each 253/// Loop pass, and Loop passes should use it to update LPM infrastructure if 254/// they modify the loop nest structure. 255/// 256/// \c LPMUpdater comes with two modes: the loop mode and the loop-nest mode. In 257/// loop mode, all the loops in the function will be pushed into the worklist 258/// and when new loops are added to the pipeline, their subloops are also 259/// inserted recursively. On the other hand, in loop-nest mode, only top-level 260/// loops are contained in the worklist and the addition of new (top-level) 261/// loops will not trigger the addition of their subloops. 262class LPMUpdater { 263public: 264 /// This can be queried by loop passes which run other loop passes (like pass 265 /// managers) to know whether the loop needs to be skipped due to updates to 266 /// the loop nest. 267 /// 268 /// If this returns true, the loop object may have been deleted, so passes 269 /// should take care not to touch the object. 270 bool skipCurrentLoop() const { return SkipCurrentLoop; } 271 272 /// Loop passes should use this method to indicate they have deleted a loop 273 /// from the nest. 274 /// 275 /// Note that this loop must either be the current loop or a subloop of the 276 /// current loop. This routine must be called prior to removing the loop from 277 /// the loop nest. 278 /// 279 /// If this is called for the current loop, in addition to clearing any 280 /// state, this routine will mark that the current loop should be skipped by 281 /// the rest of the pass management infrastructure. 282 void markLoopAsDeleted(Loop &L, llvm::StringRef Name) { 283 LAM.clear(L, Name); 284 assert((&L == CurrentL || CurrentL->contains(&L)) && 285 "Cannot delete a loop outside of the " 286 "subloop tree currently being processed."); 287 if (&L == CurrentL) 288 SkipCurrentLoop = true; 289 } 290 291 void setParentLoop(Loop *L) { 292#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS 293 ParentL = L; 294#endif 295 } 296 297 /// Loop passes should use this method to indicate they have added new child 298 /// loops of the current loop. 299 /// 300 /// \p NewChildLoops must contain only the immediate children. Any nested 301 /// loops within them will be visited in postorder as usual for the loop pass 302 /// manager. 303 void addChildLoops(ArrayRef<Loop *> NewChildLoops) { 304 assert(!LoopNestMode && 305 "Child loops should not be pushed in loop-nest mode."); 306 // Insert ourselves back into the worklist first, as this loop should be 307 // revisited after all the children have been processed. 308 Worklist.insert(CurrentL); 309 310#ifndef NDEBUG 311 for (Loop *NewL : NewChildLoops) 312 assert(NewL->getParentLoop() == CurrentL && "All of the new loops must " 313 "be immediate children of " 314 "the current loop!"); 315#endif 316 317 appendLoopsToWorklist(NewChildLoops, Worklist); 318 319 // Also skip further processing of the current loop--it will be revisited 320 // after all of its newly added children are accounted for. 321 SkipCurrentLoop = true; 322 } 323 324 /// Loop passes should use this method to indicate they have added new 325 /// sibling loops to the current loop. 326 /// 327 /// \p NewSibLoops must only contain the immediate sibling loops. Any nested 328 /// loops within them will be visited in postorder as usual for the loop pass 329 /// manager. 330 void addSiblingLoops(ArrayRef<Loop *> NewSibLoops) { 331#if defined(LLVM_ENABLE_ABI_BREAKING_CHECKS) && !defined(NDEBUG) 332 for (Loop *NewL : NewSibLoops) 333 assert(NewL->getParentLoop() == ParentL && 334 "All of the new loops must be siblings of the current loop!"); 335#endif 336 337 if (LoopNestMode) 338 Worklist.insert(NewSibLoops); 339 else 340 appendLoopsToWorklist(NewSibLoops, Worklist); 341 342 // No need to skip the current loop or revisit it, as sibling loops 343 // shouldn't impact anything. 344 } 345 346 /// Restart the current loop. 347 /// 348 /// Loop passes should call this method to indicate the current loop has been 349 /// sufficiently changed that it should be re-visited from the begining of 350 /// the loop pass pipeline rather than continuing. 351 void revisitCurrentLoop() { 352 // Tell the currently in-flight pipeline to stop running. 353 SkipCurrentLoop = true; 354 355 // And insert ourselves back into the worklist. 356 Worklist.insert(CurrentL); 357 } 358 359 bool isLoopNestChanged() const { 360 return LoopNestChanged; 361 } 362 363 /// Loopnest passes should use this method to indicate if the 364 /// loopnest has been modified. 365 void markLoopNestChanged(bool Changed) { 366 LoopNestChanged = Changed; 367 } 368 369private: 370 friend class llvm::FunctionToLoopPassAdaptor; 371 372 /// The \c FunctionToLoopPassAdaptor's worklist of loops to process. 373 SmallPriorityWorklist<Loop *, 4> &Worklist; 374 375 /// The analysis manager for use in the current loop nest. 376 LoopAnalysisManager &LAM; 377 378 Loop *CurrentL; 379 bool SkipCurrentLoop; 380 const bool LoopNestMode; 381 bool LoopNestChanged; 382 383#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS 384 // In debug builds we also track the parent loop to implement asserts even in 385 // the face of loop deletion. 386 Loop *ParentL; 387#endif 388 389 LPMUpdater(SmallPriorityWorklist<Loop *, 4> &Worklist, 390 LoopAnalysisManager &LAM, bool LoopNestMode = false, 391 bool LoopNestChanged = false) 392 : Worklist(Worklist), LAM(LAM), LoopNestMode(LoopNestMode), 393 LoopNestChanged(LoopNestChanged) {} 394}; 395 396template <typename IRUnitT, typename PassT> 397std::optional<PreservedAnalyses> LoopPassManager::runSinglePass( 398 IRUnitT &IR, PassT &Pass, LoopAnalysisManager &AM, 399 LoopStandardAnalysisResults &AR, LPMUpdater &U, PassInstrumentation &PI) { 400 // Get the loop in case of Loop pass and outermost loop in case of LoopNest 401 // pass which is to be passed to BeforePass and AfterPass call backs. 402 const Loop &L = getLoopFromIR(IR); 403 // Check the PassInstrumentation's BeforePass callbacks before running the 404 // pass, skip its execution completely if asked to (callback returns false). 405 if (!PI.runBeforePass<Loop>(*Pass, L)) 406 return std::nullopt; 407 408 PreservedAnalyses PA = Pass->run(IR, AM, AR, U); 409 410 // do not pass deleted Loop into the instrumentation 411 if (U.skipCurrentLoop()) 412 PI.runAfterPassInvalidated<IRUnitT>(*Pass, PA); 413 else 414 PI.runAfterPass<Loop>(*Pass, L, PA); 415 return PA; 416} 417 418/// Adaptor that maps from a function to its loops. 419/// 420/// Designed to allow composition of a LoopPass(Manager) and a 421/// FunctionPassManager. Note that if this pass is constructed with a \c 422/// FunctionAnalysisManager it will run the \c LoopAnalysisManagerFunctionProxy 423/// analysis prior to running the loop passes over the function to enable a \c 424/// LoopAnalysisManager to be used within this run safely. 425/// 426/// The adaptor comes with two modes: the loop mode and the loop-nest mode, and 427/// the worklist updater lived inside will be in the same mode as the adaptor 428/// (refer to the documentation of \c LPMUpdater for more detailed explanation). 429/// Specifically, in loop mode, all loops in the funciton will be pushed into 430/// the worklist and processed by \p Pass, while only top-level loops are 431/// processed in loop-nest mode. Please refer to the various specializations of 432/// \fn createLoopFunctionToLoopPassAdaptor to see when loop mode and loop-nest 433/// mode are used. 434class FunctionToLoopPassAdaptor 435 : public PassInfoMixin<FunctionToLoopPassAdaptor> { 436public: 437 using PassConceptT = 438 detail::PassConcept<Loop, LoopAnalysisManager, 439 LoopStandardAnalysisResults &, LPMUpdater &>; 440 441 explicit FunctionToLoopPassAdaptor(std::unique_ptr<PassConceptT> Pass, 442 bool UseMemorySSA = false, 443 bool UseBlockFrequencyInfo = false, 444 bool UseBranchProbabilityInfo = false, 445 bool LoopNestMode = false) 446 : Pass(std::move(Pass)), UseMemorySSA(UseMemorySSA), 447 UseBlockFrequencyInfo(UseBlockFrequencyInfo), 448 UseBranchProbabilityInfo(UseBranchProbabilityInfo), 449 LoopNestMode(LoopNestMode) { 450 LoopCanonicalizationFPM.addPass(LoopSimplifyPass()); 451 LoopCanonicalizationFPM.addPass(LCSSAPass()); 452 } 453 454 /// Runs the loop passes across every loop in the function. 455 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 456 void printPipeline(raw_ostream &OS, 457 function_ref<StringRef(StringRef)> MapClassName2PassName); 458 459 static bool isRequired() { return true; } 460 461 bool isLoopNestMode() const { return LoopNestMode; } 462 463private: 464 std::unique_ptr<PassConceptT> Pass; 465 466 FunctionPassManager LoopCanonicalizationFPM; 467 468 bool UseMemorySSA = false; 469 bool UseBlockFrequencyInfo = false; 470 bool UseBranchProbabilityInfo = false; 471 const bool LoopNestMode; 472}; 473 474/// A function to deduce a loop pass type and wrap it in the templated 475/// adaptor. 476/// 477/// If \p Pass is a loop pass, the returned adaptor will be in loop mode. 478template <typename LoopPassT> 479inline std::enable_if_t<is_detected<HasRunOnLoopT, LoopPassT>::value, 480 FunctionToLoopPassAdaptor> 481createFunctionToLoopPassAdaptor(LoopPassT &&Pass, bool UseMemorySSA = false, 482 bool UseBlockFrequencyInfo = false, 483 bool UseBranchProbabilityInfo = false) { 484 using PassModelT = 485 detail::PassModel<Loop, LoopPassT, PreservedAnalyses, LoopAnalysisManager, 486 LoopStandardAnalysisResults &, LPMUpdater &>; 487 // Do not use make_unique, it causes too many template instantiations, 488 // causing terrible compile times. 489 return FunctionToLoopPassAdaptor( 490 std::unique_ptr<FunctionToLoopPassAdaptor::PassConceptT>( 491 new PassModelT(std::forward<LoopPassT>(Pass))), 492 UseMemorySSA, UseBlockFrequencyInfo, UseBranchProbabilityInfo, false); 493} 494 495/// If \p Pass is a loop-nest pass, \p Pass will first be wrapped into a 496/// \c LoopPassManager and the returned adaptor will be in loop-nest mode. 497template <typename LoopNestPassT> 498inline std::enable_if_t<!is_detected<HasRunOnLoopT, LoopNestPassT>::value, 499 FunctionToLoopPassAdaptor> 500createFunctionToLoopPassAdaptor(LoopNestPassT &&Pass, bool UseMemorySSA = false, 501 bool UseBlockFrequencyInfo = false, 502 bool UseBranchProbabilityInfo = false) { 503 LoopPassManager LPM; 504 LPM.addPass(std::forward<LoopNestPassT>(Pass)); 505 using PassModelT = 506 detail::PassModel<Loop, LoopPassManager, PreservedAnalyses, 507 LoopAnalysisManager, LoopStandardAnalysisResults &, 508 LPMUpdater &>; 509 // Do not use make_unique, it causes too many template instantiations, 510 // causing terrible compile times. 511 return FunctionToLoopPassAdaptor( 512 std::unique_ptr<FunctionToLoopPassAdaptor::PassConceptT>( 513 new PassModelT(std::move(LPM))), 514 UseMemorySSA, UseBlockFrequencyInfo, UseBranchProbabilityInfo, true); 515} 516 517/// If \p Pass is an instance of \c LoopPassManager, the returned adaptor will 518/// be in loop-nest mode if the pass manager contains only loop-nest passes. 519template <> 520inline FunctionToLoopPassAdaptor 521createFunctionToLoopPassAdaptor<LoopPassManager>( 522 LoopPassManager &&LPM, bool UseMemorySSA, bool UseBlockFrequencyInfo, 523 bool UseBranchProbabilityInfo) { 524 // Check if LPM contains any loop pass and if it does not, returns an adaptor 525 // in loop-nest mode. 526 using PassModelT = 527 detail::PassModel<Loop, LoopPassManager, PreservedAnalyses, 528 LoopAnalysisManager, LoopStandardAnalysisResults &, 529 LPMUpdater &>; 530 bool LoopNestMode = (LPM.getNumLoopPasses() == 0); 531 // Do not use make_unique, it causes too many template instantiations, 532 // causing terrible compile times. 533 return FunctionToLoopPassAdaptor( 534 std::unique_ptr<FunctionToLoopPassAdaptor::PassConceptT>( 535 new PassModelT(std::move(LPM))), 536 UseMemorySSA, UseBlockFrequencyInfo, UseBranchProbabilityInfo, 537 LoopNestMode); 538} 539 540/// Pass for printing a loop's contents as textual IR. 541class PrintLoopPass : public PassInfoMixin<PrintLoopPass> { 542 raw_ostream &OS; 543 std::string Banner; 544 545public: 546 PrintLoopPass(); 547 PrintLoopPass(raw_ostream &OS, const std::string &Banner = ""); 548 549 PreservedAnalyses run(Loop &L, LoopAnalysisManager &, 550 LoopStandardAnalysisResults &, LPMUpdater &); 551}; 552} 553 554#endif // LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H 555