10b57cec5SDimitry Andric //===- LoopUnrollPass.h -----------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLVM_TRANSFORMS_SCALAR_LOOPUNROLLPASS_H 100b57cec5SDimitry Andric #define LLVM_TRANSFORMS_SCALAR_LOOPUNROLLPASS_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "llvm/Analysis/LoopAnalysisManager.h" 130b57cec5SDimitry Andric #include "llvm/IR/PassManager.h" 14480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 15*bdd1243dSDimitry Andric #include <optional> 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric namespace llvm { 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric extern cl::opt<bool> ForgetSCEVInLoopUnroll; 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric class Function; 220b57cec5SDimitry Andric class Loop; 230b57cec5SDimitry Andric class LPMUpdater; 240b57cec5SDimitry Andric 25e8d8bef9SDimitry Andric /// Loop unroll pass that only does full loop unrolling and peeling. 260b57cec5SDimitry Andric class LoopFullUnrollPass : public PassInfoMixin<LoopFullUnrollPass> { 270b57cec5SDimitry Andric const int OptLevel; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric /// If false, use a cost model to determine whether unrolling of a loop is 300b57cec5SDimitry Andric /// profitable. If true, only loops that explicitly request unrolling via 310b57cec5SDimitry Andric /// metadata are considered. All other loops are skipped. 320b57cec5SDimitry Andric const bool OnlyWhenForced; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric /// If true, forget all loops when unrolling. If false, forget top-most loop 350b57cec5SDimitry Andric /// of the currently processed loops, which removes one entry at a time from 360b57cec5SDimitry Andric /// the internal SCEV records. For large loops, the former is faster. 370b57cec5SDimitry Andric const bool ForgetSCEV; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric public: 400b57cec5SDimitry Andric explicit LoopFullUnrollPass(int OptLevel = 2, bool OnlyWhenForced = false, 410b57cec5SDimitry Andric bool ForgetSCEV = false) OptLevel(OptLevel)420b57cec5SDimitry Andric : OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced), 430b57cec5SDimitry Andric ForgetSCEV(ForgetSCEV) {} 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, 460b57cec5SDimitry Andric LoopStandardAnalysisResults &AR, LPMUpdater &U); 470b57cec5SDimitry Andric }; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric /// A set of parameters used to control various transforms performed by the 500b57cec5SDimitry Andric /// LoopUnroll pass. Each of the boolean parameters can be set to: 510b57cec5SDimitry Andric /// true - enabling the transformation. 520b57cec5SDimitry Andric /// false - disabling the transformation. 530b57cec5SDimitry Andric /// None - relying on a global default. 540b57cec5SDimitry Andric /// 550b57cec5SDimitry Andric /// There is also OptLevel parameter, which is used for additional loop unroll 560b57cec5SDimitry Andric /// tuning. 570b57cec5SDimitry Andric /// 580b57cec5SDimitry Andric /// Intended use is to create a default object, modify parameters with 590b57cec5SDimitry Andric /// additional setters and then pass it to LoopUnrollPass. 600b57cec5SDimitry Andric /// 610b57cec5SDimitry Andric struct LoopUnrollOptions { 62*bdd1243dSDimitry Andric std::optional<bool> AllowPartial; 63*bdd1243dSDimitry Andric std::optional<bool> AllowPeeling; 64*bdd1243dSDimitry Andric std::optional<bool> AllowRuntime; 65*bdd1243dSDimitry Andric std::optional<bool> AllowUpperBound; 66*bdd1243dSDimitry Andric std::optional<bool> AllowProfileBasedPeeling; 67*bdd1243dSDimitry Andric std::optional<unsigned> FullUnrollMaxCount; 680b57cec5SDimitry Andric int OptLevel; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric /// If false, use a cost model to determine whether unrolling of a loop is 710b57cec5SDimitry Andric /// profitable. If true, only loops that explicitly request unrolling via 720b57cec5SDimitry Andric /// metadata are considered. All other loops are skipped. 730b57cec5SDimitry Andric bool OnlyWhenForced; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric /// If true, forget all loops when unrolling. If false, forget top-most loop 760b57cec5SDimitry Andric /// of the currently processed loops, which removes one entry at a time from 770b57cec5SDimitry Andric /// the internal SCEV records. For large loops, the former is faster. 780b57cec5SDimitry Andric const bool ForgetSCEV; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric LoopUnrollOptions(int OptLevel = 2, bool OnlyWhenForced = false, 810b57cec5SDimitry Andric bool ForgetSCEV = false) OptLevelLoopUnrollOptions820b57cec5SDimitry Andric : OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced), 830b57cec5SDimitry Andric ForgetSCEV(ForgetSCEV) {} 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric /// Enables or disables partial unrolling. When disabled only full unrolling 860b57cec5SDimitry Andric /// is allowed. setPartialLoopUnrollOptions870b57cec5SDimitry Andric LoopUnrollOptions &setPartial(bool Partial) { 880b57cec5SDimitry Andric AllowPartial = Partial; 890b57cec5SDimitry Andric return *this; 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric /// Enables or disables unrolling of loops with runtime trip count. setRuntimeLoopUnrollOptions930b57cec5SDimitry Andric LoopUnrollOptions &setRuntime(bool Runtime) { 940b57cec5SDimitry Andric AllowRuntime = Runtime; 950b57cec5SDimitry Andric return *this; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric /// Enables or disables loop peeling. setPeelingLoopUnrollOptions990b57cec5SDimitry Andric LoopUnrollOptions &setPeeling(bool Peeling) { 1000b57cec5SDimitry Andric AllowPeeling = Peeling; 1010b57cec5SDimitry Andric return *this; 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric /// Enables or disables the use of trip count upper bound 1050b57cec5SDimitry Andric /// in loop unrolling. setUpperBoundLoopUnrollOptions1060b57cec5SDimitry Andric LoopUnrollOptions &setUpperBound(bool UpperBound) { 1070b57cec5SDimitry Andric AllowUpperBound = UpperBound; 1080b57cec5SDimitry Andric return *this; 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric // Sets "optimization level" tuning parameter for loop unrolling. setOptLevelLoopUnrollOptions1120b57cec5SDimitry Andric LoopUnrollOptions &setOptLevel(int O) { 1130b57cec5SDimitry Andric OptLevel = O; 1140b57cec5SDimitry Andric return *this; 1150b57cec5SDimitry Andric } 1168bcb0991SDimitry Andric 1178bcb0991SDimitry Andric // Enables or disables loop peeling basing on profile. setProfileBasedPeelingLoopUnrollOptions1188bcb0991SDimitry Andric LoopUnrollOptions &setProfileBasedPeeling(int O) { 1198bcb0991SDimitry Andric AllowProfileBasedPeeling = O; 1208bcb0991SDimitry Andric return *this; 1218bcb0991SDimitry Andric } 1228bcb0991SDimitry Andric 1238bcb0991SDimitry Andric // Sets the max full unroll count. setFullUnrollMaxCountLoopUnrollOptions1248bcb0991SDimitry Andric LoopUnrollOptions &setFullUnrollMaxCount(unsigned O) { 1258bcb0991SDimitry Andric FullUnrollMaxCount = O; 1268bcb0991SDimitry Andric return *this; 1278bcb0991SDimitry Andric } 1280b57cec5SDimitry Andric }; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric /// Loop unroll pass that will support both full and partial unrolling. 1310b57cec5SDimitry Andric /// It is a function pass to have access to function and module analyses. 1320b57cec5SDimitry Andric /// It will also put loops into canonical form (simplified and LCSSA). 1330b57cec5SDimitry Andric class LoopUnrollPass : public PassInfoMixin<LoopUnrollPass> { 1340b57cec5SDimitry Andric LoopUnrollOptions UnrollOpts; 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric public: 1370b57cec5SDimitry Andric /// This uses the target information (or flags) to control the thresholds for 1380b57cec5SDimitry Andric /// different unrolling stategies but supports all of them. 1390b57cec5SDimitry Andric explicit LoopUnrollPass(LoopUnrollOptions UnrollOpts = {}) UnrollOpts(UnrollOpts)1400b57cec5SDimitry Andric : UnrollOpts(UnrollOpts) {} 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 143349cc55cSDimitry Andric void printPipeline(raw_ostream &OS, 144349cc55cSDimitry Andric function_ref<StringRef(StringRef)> MapClassName2PassName); 1450b57cec5SDimitry Andric }; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric } // end namespace llvm 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric #endif // LLVM_TRANSFORMS_SCALAR_LOOPUNROLLPASS_H 150