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