clang 24.0.0git
LoopAttributes.cpp
Go to the documentation of this file.
1//===--- LoopAttributes.cpp - Shared loop hint state ----------------------===//
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
11#include "clang/AST/Attr.h"
12#include "clang/AST/Expr.h"
14#include "llvm/Support/ErrorHandling.h"
15
16namespace clang::CodeGenUtils {
17
28
47
49 const CodeGenOptions &CGOpts,
51 bool MustProgress) {
52 // Identify loop hint attributes from Attrs.
53 for (const auto *Attr : StmtAttrs) {
54 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
55 const OpenCLUnrollHintAttr *OpenCLHint =
56 dyn_cast<OpenCLUnrollHintAttr>(Attr);
57 const HLSLLoopHintAttr *HLSLLoopHint = dyn_cast<HLSLLoopHintAttr>(Attr);
58 // Skip non loop hint attributes
59 if (!LH && !OpenCLHint && !HLSLLoopHint) {
60 continue;
61 }
62
63 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
64 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
65 unsigned ValueInt = 1;
66 // Translate opencl_unroll_hint attribute argument to
67 // equivalent LoopHintAttr enums.
68 // OpenCL v2.0 s6.11.5:
69 // 0 - enable unroll (no argument).
70 // 1 - disable unroll.
71 // other positive integer n - unroll by n.
72 if (OpenCLHint) {
73 ValueInt = OpenCLHint->getUnrollHint();
74 if (ValueInt == 0) {
75 State = LoopHintAttr::Enable;
76 } else if (ValueInt != 1) {
77 Option = LoopHintAttr::UnrollCount;
78 State = LoopHintAttr::Numeric;
79 }
80 } else if (HLSLLoopHint) {
81 ValueInt = HLSLLoopHint->getDirective();
82 if (HLSLLoopHint->getSemanticSpelling() ==
83 HLSLLoopHintAttr::Spelling::Microsoft_unroll) {
84 if (ValueInt == 0)
85 State = LoopHintAttr::Enable;
86 if (ValueInt > 0) {
87 Option = LoopHintAttr::UnrollCount;
88 State = LoopHintAttr::Numeric;
89 }
90 }
91 } else if (LH) {
92 auto *ValueExpr = LH->getValue();
93 if (ValueExpr) {
94 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
95 ValueInt = ValueAPS.getSExtValue();
96 }
97
98 Option = LH->getOption();
99 State = LH->getState();
100 }
101 switch (State) {
102 case LoopHintAttr::Disable:
103 switch (Option) {
104 case LoopHintAttr::Vectorize:
105 // Disable vectorization by specifying a width of 1 and disabling
106 // scalable vectorization explicitly.
107 Attrs.VectorizeWidth = 1;
109 break;
110 case LoopHintAttr::Interleave:
111 // Disable interleaving by speciyfing a count of 1.
112 Attrs.InterleaveCount = 1;
113 break;
114 case LoopHintAttr::Unroll:
116 break;
117 case LoopHintAttr::UnrollAndJam:
119 break;
120 case LoopHintAttr::VectorizePredicate:
122 break;
123 case LoopHintAttr::Distribute:
125 break;
126 case LoopHintAttr::PipelineDisabled:
127 Attrs.PipelineDisabled = true;
128 break;
129 case LoopHintAttr::LICMDisabled:
130 Attrs.LICMDisabled = true;
131 break;
132 case LoopHintAttr::UnrollCount:
133 case LoopHintAttr::UnrollAndJamCount:
134 case LoopHintAttr::VectorizeWidth:
135 case LoopHintAttr::InterleaveCount:
136 case LoopHintAttr::PipelineInitiationInterval:
137 llvm_unreachable("Options cannot be disabled.");
138 break;
139 }
140 break;
141 case LoopHintAttr::Enable:
142 switch (Option) {
143 case LoopHintAttr::Vectorize:
144 case LoopHintAttr::Interleave:
146 break;
147 case LoopHintAttr::Unroll:
149 break;
150 case LoopHintAttr::UnrollAndJam:
152 break;
153 case LoopHintAttr::VectorizePredicate:
155 break;
156 case LoopHintAttr::Distribute:
158 break;
159 case LoopHintAttr::UnrollCount:
160 case LoopHintAttr::UnrollAndJamCount:
161 case LoopHintAttr::VectorizeWidth:
162 case LoopHintAttr::InterleaveCount:
163 case LoopHintAttr::PipelineDisabled:
164 case LoopHintAttr::PipelineInitiationInterval:
165 case LoopHintAttr::LICMDisabled:
166 llvm_unreachable("Options cannot enabled.");
167 break;
168 }
169 break;
170 case LoopHintAttr::AssumeSafety:
171 switch (Option) {
172 case LoopHintAttr::Vectorize:
173 case LoopHintAttr::Interleave:
174 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
175 Attrs.IsParallel = true;
177 break;
178 case LoopHintAttr::Unroll:
179 case LoopHintAttr::UnrollAndJam:
180 case LoopHintAttr::VectorizePredicate:
181 case LoopHintAttr::UnrollCount:
182 case LoopHintAttr::UnrollAndJamCount:
183 case LoopHintAttr::VectorizeWidth:
184 case LoopHintAttr::InterleaveCount:
185 case LoopHintAttr::Distribute:
186 case LoopHintAttr::PipelineDisabled:
187 case LoopHintAttr::PipelineInitiationInterval:
188 case LoopHintAttr::LICMDisabled:
189 llvm_unreachable("Options cannot be used to assume mem safety.");
190 break;
191 }
192 break;
193 case LoopHintAttr::Full:
194 switch (Option) {
195 case LoopHintAttr::Unroll:
197 break;
198 case LoopHintAttr::UnrollAndJam:
200 break;
201 case LoopHintAttr::Vectorize:
202 case LoopHintAttr::Interleave:
203 case LoopHintAttr::UnrollCount:
204 case LoopHintAttr::UnrollAndJamCount:
205 case LoopHintAttr::VectorizeWidth:
206 case LoopHintAttr::InterleaveCount:
207 case LoopHintAttr::Distribute:
208 case LoopHintAttr::PipelineDisabled:
209 case LoopHintAttr::PipelineInitiationInterval:
210 case LoopHintAttr::VectorizePredicate:
211 case LoopHintAttr::LICMDisabled:
212 llvm_unreachable("Options cannot be used with 'full' hint.");
213 break;
214 }
215 break;
216 case LoopHintAttr::FixedWidth:
217 case LoopHintAttr::ScalableWidth:
218 switch (Option) {
219 case LoopHintAttr::VectorizeWidth:
220 Attrs.VectorizeScalable = State == LoopHintAttr::ScalableWidth
223 if (LH->getValue())
224 Attrs.VectorizeWidth = ValueInt;
225 break;
226 default:
227 llvm_unreachable("Options cannot be used with 'scalable' hint.");
228 break;
229 }
230 break;
231 case LoopHintAttr::Numeric:
232 switch (Option) {
233 case LoopHintAttr::InterleaveCount:
234 Attrs.InterleaveCount = ValueInt;
235 break;
236 case LoopHintAttr::UnrollCount:
237 Attrs.UnrollCount = ValueInt;
238 break;
239 case LoopHintAttr::UnrollAndJamCount:
240 Attrs.UnrollAndJamCount = ValueInt;
241 break;
242 case LoopHintAttr::PipelineInitiationInterval:
243 Attrs.PipelineInitiationInterval = ValueInt;
244 break;
245 case LoopHintAttr::Unroll:
246 case LoopHintAttr::UnrollAndJam:
247 case LoopHintAttr::VectorizePredicate:
248 case LoopHintAttr::Vectorize:
249 case LoopHintAttr::VectorizeWidth:
250 case LoopHintAttr::Interleave:
251 case LoopHintAttr::Distribute:
252 case LoopHintAttr::PipelineDisabled:
253 case LoopHintAttr::LICMDisabled:
254 llvm_unreachable("Options cannot be assigned a value.");
255 break;
256 }
257 break;
258 }
259 }
260
261 // Identify loop attribute 'code_align' from Attrs.
262 // For attribute code_align:
263 // n - 'llvm.loop.align i32 n' metadata will be emitted.
264 // A source-level [[clang::code_align]] attribute takes precedence over the
265 // -falign-loops=N command-line default.
266 if (const auto *CodeAlign = getSpecificAttr<CodeAlignAttr>(StmtAttrs)) {
267 const auto *CE = cast<ConstantExpr>(CodeAlign->getAlignment());
268 llvm::APSInt ArgVal = CE->getResultAsAPSInt();
269 Attrs.CodeAlign = ArgVal.getSExtValue();
270 } else if (CGOpts.LoopAlignment) {
271 Attrs.CodeAlign = CGOpts.LoopAlignment;
272 }
273
274 Attrs.MustProgress = MustProgress;
275
276 if (CGOpts.OptimizationLevel > 0)
277 // Disable unrolling for the loop, if unrolling is disabled (via
278 // -fno-unroll-loops) and no pragmas override the decision.
279 if (!CGOpts.UnrollLoops &&
281 Attrs.UnrollCount == 0))
283}
284
285} // namespace clang::CodeGenUtils
Defines the clang::ASTContext interface.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
Attr - This represents one attribute.
Definition Attr.h:46
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
void updateLoopAttributes(LoopAttributes &Attrs, ASTContext &Ctx, const CodeGenOptions &CGOpts, llvm::ArrayRef< const Attr * > StmtAttrs, bool MustProgress)
Update Attrs with the loop hints in StmtAttrs (#pragma clang loop, #pragma unroll,...
auto * getSpecificAttr(const Container &container)
U cast(CodeGen::Address addr)
Definition Address.h:327
#define false
Definition stdbool.h:26
Attributes that may be specified on loops.
bool LICMDisabled
Value for llvm.licm.disable metadata.
LVEnableState VectorizeEnable
Value for llvm.loop.vectorize.enable metadata.
LVEnableState UnrollEnable
Value for llvm.loop.unroll.* metadata (enable, disable, or full).
unsigned PipelineInitiationInterval
Value for llvm.loop.pipeline.iicount metadata.
unsigned UnrollAndJamCount
llvm.unroll.
LoopAttributes(bool IsParallel=false)
unsigned CodeAlign
Value for 'llvm.loop.align' metadata.
unsigned VectorizeWidth
Value for llvm.loop.vectorize.width metadata.
LVEnableState UnrollAndJamEnable
Value for llvm.loop.unroll_and_jam.* metadata (enable, disable, or full).
LVEnableState VectorizePredicateEnable
Value for llvm.loop.vectorize.predicate metadata.
bool PipelineDisabled
Value for llvm.loop.pipeline.disable metadata.
bool IsParallel
Generate llvm.loop.parallel metadata for loads and stores.
bool MustProgress
Value for whether the loop is required to make progress.
LVEnableState DistributeEnable
Value for llvm.loop.distribute.enable metadata.
unsigned InterleaveCount
Value for llvm.loop.interleave.count metadata.