1 | //===- LoopUnrollPass.h -----------------------------------------*- 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 | |
9 | #ifndef LLVM_TRANSFORMS_SCALAR_LOOPUNROLLPASS_H |
10 | #define LLVM_TRANSFORMS_SCALAR_LOOPUNROLLPASS_H |
11 | |
12 | #include "llvm/Analysis/LoopAnalysisManager.h" |
13 | #include "llvm/IR/PassManager.h" |
14 | #include "llvm/Support/CommandLine.h" |
15 | #include <optional> |
16 | |
17 | namespace llvm { |
18 | |
19 | extern cl::opt<bool> ForgetSCEVInLoopUnroll; |
20 | |
21 | class Function; |
22 | class Loop; |
23 | class LPMUpdater; |
24 | |
25 | /// Loop unroll pass that only does full loop unrolling and peeling. |
26 | class LoopFullUnrollPass : public PassInfoMixin<LoopFullUnrollPass> { |
27 | const int OptLevel; |
28 | |
29 | /// If false, use a cost model to determine whether unrolling of a loop is |
30 | /// profitable. If true, only loops that explicitly request unrolling via |
31 | /// metadata are considered. All other loops are skipped. |
32 | const bool OnlyWhenForced; |
33 | |
34 | /// If true, forget all loops when unrolling. If false, forget top-most loop |
35 | /// of the currently processed loops, which removes one entry at a time from |
36 | /// the internal SCEV records. For large loops, the former is faster. |
37 | const bool ForgetSCEV; |
38 | |
39 | public: |
40 | explicit LoopFullUnrollPass(int OptLevel = 2, bool OnlyWhenForced = false, |
41 | bool ForgetSCEV = false) |
42 | : OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced), |
43 | ForgetSCEV(ForgetSCEV) {} |
44 | |
45 | PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, |
46 | LoopStandardAnalysisResults &AR, LPMUpdater &U); |
47 | }; |
48 | |
49 | /// A set of parameters used to control various transforms performed by the |
50 | /// LoopUnroll pass. Each of the boolean parameters can be set to: |
51 | /// true - enabling the transformation. |
52 | /// false - disabling the transformation. |
53 | /// None - relying on a global default. |
54 | /// |
55 | /// There is also OptLevel parameter, which is used for additional loop unroll |
56 | /// tuning. |
57 | /// |
58 | /// Intended use is to create a default object, modify parameters with |
59 | /// additional setters and then pass it to LoopUnrollPass. |
60 | /// |
61 | struct LoopUnrollOptions { |
62 | std::optional<bool> AllowPartial; |
63 | std::optional<bool> AllowPeeling; |
64 | std::optional<bool> AllowRuntime; |
65 | std::optional<bool> AllowUpperBound; |
66 | std::optional<bool> AllowProfileBasedPeeling; |
67 | std::optional<unsigned> FullUnrollMaxCount; |
68 | int OptLevel; |
69 | |
70 | /// If false, use a cost model to determine whether unrolling of a loop is |
71 | /// profitable. If true, only loops that explicitly request unrolling via |
72 | /// metadata are considered. All other loops are skipped. |
73 | bool OnlyWhenForced; |
74 | |
75 | /// If true, forget all loops when unrolling. If false, forget top-most loop |
76 | /// of the currently processed loops, which removes one entry at a time from |
77 | /// the internal SCEV records. For large loops, the former is faster. |
78 | const bool ForgetSCEV; |
79 | |
80 | LoopUnrollOptions(int OptLevel = 2, bool OnlyWhenForced = false, |
81 | bool ForgetSCEV = false) |
82 | : OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced), |
83 | ForgetSCEV(ForgetSCEV) {} |
84 | |
85 | /// Enables or disables partial unrolling. When disabled only full unrolling |
86 | /// is allowed. |
87 | LoopUnrollOptions &setPartial(bool Partial) { |
88 | AllowPartial = Partial; |
89 | return *this; |
90 | } |
91 | |
92 | /// Enables or disables unrolling of loops with runtime trip count. |
93 | LoopUnrollOptions &setRuntime(bool Runtime) { |
94 | AllowRuntime = Runtime; |
95 | return *this; |
96 | } |
97 | |
98 | /// Enables or disables loop peeling. |
99 | LoopUnrollOptions &setPeeling(bool Peeling) { |
100 | AllowPeeling = Peeling; |
101 | return *this; |
102 | } |
103 | |
104 | /// Enables or disables the use of trip count upper bound |
105 | /// in loop unrolling. |
106 | LoopUnrollOptions &setUpperBound(bool UpperBound) { |
107 | AllowUpperBound = UpperBound; |
108 | return *this; |
109 | } |
110 | |
111 | // Sets "optimization level" tuning parameter for loop unrolling. |
112 | LoopUnrollOptions &setOptLevel(int O) { |
113 | OptLevel = O; |
114 | return *this; |
115 | } |
116 | |
117 | // Enables or disables loop peeling basing on profile. |
118 | LoopUnrollOptions &setProfileBasedPeeling(int O) { |
119 | AllowProfileBasedPeeling = O; |
120 | return *this; |
121 | } |
122 | |
123 | // Sets the max full unroll count. |
124 | LoopUnrollOptions &setFullUnrollMaxCount(unsigned O) { |
125 | FullUnrollMaxCount = O; |
126 | return *this; |
127 | } |
128 | }; |
129 | |
130 | /// Loop unroll pass that will support both full and partial unrolling. |
131 | /// It is a function pass to have access to function and module analyses. |
132 | /// It will also put loops into canonical form (simplified and LCSSA). |
133 | class LoopUnrollPass : public PassInfoMixin<LoopUnrollPass> { |
134 | LoopUnrollOptions UnrollOpts; |
135 | |
136 | public: |
137 | /// This uses the target information (or flags) to control the thresholds for |
138 | /// different unrolling stategies but supports all of them. |
139 | explicit LoopUnrollPass(LoopUnrollOptions UnrollOpts = {}) |
140 | : UnrollOpts(UnrollOpts) {} |
141 | |
142 | PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); |
143 | void printPipeline(raw_ostream &OS, |
144 | function_ref<StringRef(StringRef)> MapClassName2PassName); |
145 | }; |
146 | |
147 | } // end namespace llvm |
148 | |
149 | #endif // LLVM_TRANSFORMS_SCALAR_LOOPUNROLLPASS_H |
150 | |