xref: /freebsd-src/contrib/llvm-project/llvm/include/llvm/Transforms/Scalar/LoopUnrollPass.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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