//===- LoopPassManager.h - Loop pass management -----------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file /// /// This header provides classes for managing a pipeline of passes over loops /// in LLVM IR. /// /// The primary loop pass pipeline is managed in a very particular way to /// provide a set of core guarantees: /// 1) Loops are, where possible, in simplified form. /// 2) Loops are *always* in LCSSA form. /// 3) A collection of Loop-specific analysis results are available: /// - LoopInfo /// - DominatorTree /// - ScalarEvolution /// - AAManager /// 4) All loop passes preserve #1 (where possible), #2, and #3. /// 5) Loop passes run over each loop in the loop nest from the innermost to /// the outermost. Specifically, all inner loops are processed before /// passes run over outer loops. When running the pipeline across an inner /// loop creates new inner loops, those are added and processed in this /// order as well. /// /// This process is designed to facilitate transformations which simplify, /// reduce, and remove loops. For passes which are more oriented towards /// optimizing loops, especially optimizing loop *nests* instead of single /// loops in isolation, this framework is less interesting. /// //===----------------------------------------------------------------------===// #ifndef LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H #define LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H #include "llvm/ADT/PriorityWorklist.h" #include "llvm/Analysis/LoopAnalysisManager.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopNestAnalysis.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/PassInstrumentation.h" #include "llvm/Transforms/Utils/LCSSA.h" #include "llvm/Transforms/Utils/LoopSimplify.h" #include "llvm/Transforms/Utils/LoopUtils.h" #include <memory> namespace llvm { // Forward declarations of an update tracking API used in the pass manager. class LPMUpdater; class PassInstrumentation; namespace { HasRunOnLoopT; } // namespace // Explicit specialization and instantiation declarations for the pass manager. // See the comments on the definition of the specialization for details on how // it differs from the primary template. template <> class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &, LPMUpdater &> : public PassInfoMixin< PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &, LPMUpdater &>> { … }; /// The Loop pass manager. /// /// See the documentation for the PassManager template for details. It runs /// a sequence of Loop passes over each Loop that the manager is run over. This /// typedef serves as a convenient way to refer to this construct. LoopPassManager; /// A partial specialization of the require analysis template pass to forward /// the extra parameters from a transformation's run method to the /// AnalysisManager's getResult. RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager, LoopStandardAnalysisResults &, LPMUpdater &>; /// An alias template to easily name a require analysis loop pass. RequireAnalysisLoopPass; class FunctionToLoopPassAdaptor; /// This class provides an interface for updating the loop pass manager based /// on mutations to the loop nest. /// /// A reference to an instance of this class is passed as an argument to each /// Loop pass, and Loop passes should use it to update LPM infrastructure if /// they modify the loop nest structure. /// /// \c LPMUpdater comes with two modes: the loop mode and the loop-nest mode. In /// loop mode, all the loops in the function will be pushed into the worklist /// and when new loops are added to the pipeline, their subloops are also /// inserted recursively. On the other hand, in loop-nest mode, only top-level /// loops are contained in the worklist and the addition of new (top-level) /// loops will not trigger the addition of their subloops. class LPMUpdater { … }; template <typename IRUnitT, typename PassT> std::optional<PreservedAnalyses> LoopPassManager::runSinglePass( IRUnitT &IR, PassT &Pass, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U, PassInstrumentation &PI) { … } /// Adaptor that maps from a function to its loops. /// /// Designed to allow composition of a LoopPass(Manager) and a /// FunctionPassManager. Note that if this pass is constructed with a \c /// FunctionAnalysisManager it will run the \c LoopAnalysisManagerFunctionProxy /// analysis prior to running the loop passes over the function to enable a \c /// LoopAnalysisManager to be used within this run safely. /// /// The adaptor comes with two modes: the loop mode and the loop-nest mode, and /// the worklist updater lived inside will be in the same mode as the adaptor /// (refer to the documentation of \c LPMUpdater for more detailed explanation). /// Specifically, in loop mode, all loops in the function will be pushed into /// the worklist and processed by \p Pass, while only top-level loops are /// processed in loop-nest mode. Please refer to the various specializations of /// \fn createLoopFunctionToLoopPassAdaptor to see when loop mode and loop-nest /// mode are used. class FunctionToLoopPassAdaptor : public PassInfoMixin<FunctionToLoopPassAdaptor> { … }; /// A function to deduce a loop pass type and wrap it in the templated /// adaptor. /// /// If \p Pass is a loop pass, the returned adaptor will be in loop mode. template <typename LoopPassT> inline std::enable_if_t<is_detected<HasRunOnLoopT, LoopPassT>::value, FunctionToLoopPassAdaptor> createFunctionToLoopPassAdaptor(LoopPassT &&Pass, bool UseMemorySSA = false, bool UseBlockFrequencyInfo = false, bool UseBranchProbabilityInfo = false) { … } /// If \p Pass is a loop-nest pass, \p Pass will first be wrapped into a /// \c LoopPassManager and the returned adaptor will be in loop-nest mode. template <typename LoopNestPassT> inline std::enable_if_t<!is_detected<HasRunOnLoopT, LoopNestPassT>::value, FunctionToLoopPassAdaptor> createFunctionToLoopPassAdaptor(LoopNestPassT &&Pass, bool UseMemorySSA = false, bool UseBlockFrequencyInfo = false, bool UseBranchProbabilityInfo = false) { … } /// If \p Pass is an instance of \c LoopPassManager, the returned adaptor will /// be in loop-nest mode if the pass manager contains only loop-nest passes. template <> inline FunctionToLoopPassAdaptor createFunctionToLoopPassAdaptor<LoopPassManager>( LoopPassManager &&LPM, bool UseMemorySSA, bool UseBlockFrequencyInfo, bool UseBranchProbabilityInfo) { … } /// Pass for printing a loop's contents as textual IR. class PrintLoopPass : public PassInfoMixin<PrintLoopPass> { … }; } #endif // LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H