clang 24.0.0git
CGLoopInfo.cpp
Go to the documentation of this file.
1//===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- 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#include "CGLoopInfo.h"
11#include "clang/AST/Attr.h"
12#include "clang/AST/Expr.h"
14#include "llvm/IR/BasicBlock.h"
15#include "llvm/IR/CFG.h"
16#include "llvm/IR/Constants.h"
17#include "llvm/IR/InstrTypes.h"
18#include "llvm/IR/Instructions.h"
19#include "llvm/IR/Metadata.h"
20#include <optional>
21using namespace clang::CodeGen;
22using namespace llvm;
23
24MDNode *clang::CodeGen::LoopInfo::createFollowupMetadata(
25 const char *FollowupName, ArrayRef<llvm::Metadata *> LoopProperties) {
26 LLVMContext &Ctx = Header->getContext();
27
28 SmallVector<Metadata *, 4> Args;
29 Args.push_back(MDString::get(Ctx, FollowupName));
30 Args.append(LoopProperties.begin(), LoopProperties.end());
31 return MDNode::get(Ctx, Args);
32}
33
34SmallVector<Metadata *, 4> clang::CodeGen::LoopInfo::createPipeliningMetadata(
35 const LoopAttributes &Attrs, ArrayRef<Metadata *> LoopProperties,
36 bool &HasUserTransforms) {
37 LLVMContext &Ctx = Header->getContext();
38
39 std::optional<bool> Enabled;
40 if (Attrs.PipelineDisabled)
41 Enabled = false;
42 else if (Attrs.PipelineInitiationInterval != 0)
43 Enabled = true;
44
45 SmallVector<Metadata *, 4> Args;
46 Args.append(LoopProperties.begin(), LoopProperties.end());
47
48 if (Enabled != true) {
49 if (Enabled == false) {
50 Args.push_back(
51 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"),
52 ConstantAsMetadata::get(ConstantInt::get(
53 llvm::Type::getInt1Ty(Ctx), 1))}));
54 }
55 return Args;
56 }
57
58 if (Attrs.PipelineInitiationInterval > 0) {
59 Metadata *Vals[] = {
60 MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
61 ConstantAsMetadata::get(ConstantInt::get(
62 llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
63 Args.push_back(MDNode::get(Ctx, Vals));
64 }
65
66 // No follow-up: This is the last transformation.
67
68 HasUserTransforms = true;
69 return Args;
70}
71
72SmallVector<Metadata *, 4>
73clang::CodeGen::LoopInfo::createPartialUnrollMetadata(
74 const LoopAttributes &Attrs, ArrayRef<Metadata *> LoopProperties,
75 bool &HasUserTransforms) {
76 LLVMContext &Ctx = Header->getContext();
77
78 std::optional<bool> Enabled;
80 Enabled = false;
81 else if (Attrs.UnrollEnable == LoopAttributes::Full)
82 Enabled = std::nullopt;
83 else if (Attrs.UnrollEnable != LoopAttributes::Unspecified ||
84 Attrs.UnrollCount != 0)
85 Enabled = true;
86
87 if (Enabled != true) {
88 // createFullUnrollMetadata will already have added llvm.loop.unroll.disable
89 // if unrolling is disabled.
90 return createPipeliningMetadata(Attrs, LoopProperties, HasUserTransforms);
91 }
92
93 SmallVector<Metadata *, 4> FollowupLoopProperties;
94
95 // Apply all loop properties to the unrolled loop.
96 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
97
98 // Don't unroll an already unrolled loop.
99 FollowupLoopProperties.push_back(
100 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
101
102 bool FollowupHasTransforms = false;
103 SmallVector<Metadata *, 4> Followup = createPipeliningMetadata(
104 Attrs, FollowupLoopProperties, FollowupHasTransforms);
105
106 SmallVector<Metadata *, 4> Args;
107 Args.append(LoopProperties.begin(), LoopProperties.end());
108
109 // Setting unroll.count
110 if (Attrs.UnrollCount > 0) {
111 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
112 ConstantAsMetadata::get(ConstantInt::get(
113 llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
114 Args.push_back(MDNode::get(Ctx, Vals));
115 }
116
117 // Setting unroll.full or unroll.disable
119 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")};
120 Args.push_back(MDNode::get(Ctx, Vals));
121 }
122
123 if (FollowupHasTransforms)
124 Args.push_back(
125 createFollowupMetadata("llvm.loop.unroll.followup_all", Followup));
126
127 HasUserTransforms = true;
128 return Args;
129}
130
131SmallVector<Metadata *, 4> clang::CodeGen::LoopInfo::createUnrollAndJamMetadata(
132 const LoopAttributes &Attrs, ArrayRef<Metadata *> LoopProperties,
133 bool &HasUserTransforms) {
134 LLVMContext &Ctx = Header->getContext();
135
136 std::optional<bool> Enabled;
138 Enabled = false;
139 else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable ||
140 Attrs.UnrollAndJamCount != 0)
141 Enabled = true;
142
143 if (Enabled != true) {
144 SmallVector<Metadata *, 4> NewLoopProperties;
145 if (Enabled == false) {
146 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
147 NewLoopProperties.push_back(MDNode::get(
148 Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
149 LoopProperties = NewLoopProperties;
150 }
151 return createPartialUnrollMetadata(Attrs, LoopProperties,
152 HasUserTransforms);
153 }
154
155 SmallVector<Metadata *, 4> FollowupLoopProperties;
156 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
157 FollowupLoopProperties.push_back(
158 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
159
160 bool FollowupHasTransforms = false;
161 SmallVector<Metadata *, 4> Followup = createPartialUnrollMetadata(
162 Attrs, FollowupLoopProperties, FollowupHasTransforms);
163
164 SmallVector<Metadata *, 4> Args;
165 Args.append(LoopProperties.begin(), LoopProperties.end());
166
167 // Setting unroll_and_jam.count
168 if (Attrs.UnrollAndJamCount > 0) {
169 Metadata *Vals[] = {
170 MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
171 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
172 Attrs.UnrollAndJamCount))};
173 Args.push_back(MDNode::get(Ctx, Vals));
174 }
175
177 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")};
178 Args.push_back(MDNode::get(Ctx, Vals));
179 }
180
181 if (FollowupHasTransforms)
182 Args.push_back(createFollowupMetadata(
183 "llvm.loop.unroll_and_jam.followup_outer", Followup));
184
185 if (UnrollAndJamInnerFollowup.has_value())
186 Args.push_back(createFollowupMetadata(
187 "llvm.loop.unroll_and_jam.followup_inner", *UnrollAndJamInnerFollowup));
188
189 HasUserTransforms = true;
190 return Args;
191}
192
193SmallVector<Metadata *, 4>
194clang::CodeGen::LoopInfo::createLoopVectorizeMetadata(
195 const LoopAttributes &Attrs, ArrayRef<Metadata *> LoopProperties,
196 bool &HasUserTransforms) {
197 LLVMContext &Ctx = Header->getContext();
198
199 std::optional<bool> Enabled;
201 Enabled = false;
204 Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0 ||
206 Enabled = true;
207
208 if (Enabled != true) {
209 SmallVector<Metadata *, 4> NewLoopProperties;
210 if (Enabled == false) {
211 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
212 NewLoopProperties.push_back(MDNode::get(
213 Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.disable")}));
214 LoopProperties = NewLoopProperties;
215 }
216 return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms);
217 }
218
219 SmallVector<Metadata *, 4> Args;
220 Args.append(LoopProperties.begin(), LoopProperties.end());
221
222 // Setting vectorize.predicate when it has been specified and vectorization
223 // has not been disabled.
224 bool IsVectorPredicateEnabled = false;
226 IsVectorPredicateEnabled =
228
229 Args.push_back(MDNode::get(
230 Ctx,
231 {MDString::get(Ctx, IsVectorPredicateEnabled
232 ? "llvm.loop.vectorize.predicate.enable"
233 : "llvm.loop.vectorize.predicate.disable")}));
234 }
235
236 // Setting vectorize.width
237 if (Attrs.VectorizeWidth > 0) {
238 Metadata *Vals[] = {
239 MDString::get(Ctx, "llvm.loop.vectorize.width"),
240 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
241 Attrs.VectorizeWidth))};
242
243 Args.push_back(MDNode::get(Ctx, Vals));
244 }
245
247 bool IsScalable = Attrs.VectorizeScalable == LoopAttributes::Enable;
248 Args.push_back(MDNode::get(
249 Ctx, {MDString::get(
250 Ctx, IsScalable ? "llvm.loop.vectorize.scalable.enable"
251 : "llvm.loop.vectorize.scalable.disable")}));
252 }
253
254 // Setting interleave.count
255 if (Attrs.InterleaveCount > 0) {
256 Metadata *Vals[] = {
257 MDString::get(Ctx, "llvm.loop.interleave.count"),
258 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
259 Attrs.InterleaveCount))};
260 Args.push_back(MDNode::get(Ctx, Vals));
261 }
262
263 // vectorize.enable is set if:
264 // 1) loop hint vectorize.enable is set, or
265 // 2) it is implied when vectorize.predicate is set, or
266 // 3) it is implied when vectorize.width is set to a value > 1
267 // 4) it is implied when vectorize.scalable.enable is true
268 // 5) it is implied when vectorize.width is unset (0) and the user
269 // explicitly requested fixed-width vectorization, i.e.
270 // vectorize.scalable.enable is false.
271 bool VectorizeEnabled = false;
273 (IsVectorPredicateEnabled && Attrs.VectorizeWidth != 1) ||
274 Attrs.VectorizeWidth > 1 ||
277 Attrs.VectorizeWidth != 1)) {
278 VectorizeEnabled = Attrs.VectorizeEnable != LoopAttributes::Disable;
279 Args.push_back(MDNode::get(
280 Ctx, {MDString::get(Ctx, VectorizeEnabled
281 ? "llvm.loop.vectorize.enable"
282 : "llvm.loop.vectorize.disable")}));
283 }
284
285 // Apply all loop properties to the vectorized loop.
286 SmallVector<Metadata *, 4> FollowupLoopProperties;
287
288 // If vectorization is not explicitly enabled, the follow-up metadata will be
289 // directly appended to the list currently being created. In that case, adding
290 // LoopProperties to FollowupLoopProperties would result in duplication.
291 if (VectorizeEnabled)
292 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
293
294 // Don't vectorize an already vectorized loop.
295 FollowupLoopProperties.push_back(
296 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
297
298 bool FollowupHasTransforms = false;
299 SmallVector<Metadata *, 4> Followup = createUnrollAndJamMetadata(
300 Attrs, FollowupLoopProperties, FollowupHasTransforms);
301
302 if (FollowupHasTransforms) {
303 // If vectorization is explicitly enabled, we create a follow-up metadata,
304 // otherwise directly add the contents of it to Args.
305 if (VectorizeEnabled)
306 Args.push_back(
307 createFollowupMetadata("llvm.loop.vectorize.followup_all", Followup));
308 else
309 Args.append(Followup.begin(), Followup.end());
310 }
311
312 HasUserTransforms = true;
313 return Args;
314}
315
316SmallVector<Metadata *, 4>
317clang::CodeGen::LoopInfo::createLoopDistributeMetadata(
318 const LoopAttributes &Attrs, ArrayRef<Metadata *> LoopProperties,
319 bool &HasUserTransforms) {
320 LLVMContext &Ctx = Header->getContext();
321
322 std::optional<bool> Enabled;
324 Enabled = false;
326 Enabled = true;
327
328 if (Enabled != true) {
329 SmallVector<Metadata *, 4> NewLoopProperties;
330 if (Enabled == false) {
331 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
332 NewLoopProperties.push_back(MDNode::get(
333 Ctx, {MDString::get(Ctx, "llvm.loop.distribute.disable")}));
334 LoopProperties = NewLoopProperties;
335 }
336 return createLoopVectorizeMetadata(Attrs, LoopProperties,
337 HasUserTransforms);
338 }
339
340 bool FollowupHasTransforms = false;
341 SmallVector<Metadata *, 4> Followup =
342 createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);
343
344 SmallVector<Metadata *, 4> Args;
345 Args.append(LoopProperties.begin(), LoopProperties.end());
346
347 Args.push_back(
348 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable")}));
349
350 if (FollowupHasTransforms)
351 Args.push_back(
352 createFollowupMetadata("llvm.loop.distribute.followup_all", Followup));
353
354 HasUserTransforms = true;
355 return Args;
356}
357
358SmallVector<Metadata *, 4> clang::CodeGen::LoopInfo::createFullUnrollMetadata(
359 const LoopAttributes &Attrs, ArrayRef<Metadata *> LoopProperties,
360 bool &HasUserTransforms) {
361 LLVMContext &Ctx = Header->getContext();
362
363 std::optional<bool> Enabled;
365 Enabled = false;
366 else if (Attrs.UnrollEnable == LoopAttributes::Full)
367 Enabled = true;
368
369 if (Enabled != true) {
370 SmallVector<Metadata *, 4> NewLoopProperties;
371 if (Enabled == false) {
372 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
373 NewLoopProperties.push_back(
374 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
375 LoopProperties = NewLoopProperties;
376 }
377 return createLoopDistributeMetadata(Attrs, LoopProperties,
378 HasUserTransforms);
379 }
380
381 SmallVector<Metadata *, 4> Args;
382 Args.append(LoopProperties.begin(), LoopProperties.end());
383 Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));
384
385 // No follow-up: there is no loop after full unrolling.
386 // TODO: Warn if there are transformations after full unrolling.
387
388 HasUserTransforms = true;
389 return Args;
390}
391
392SmallVector<Metadata *, 4> clang::CodeGen::LoopInfo::createMetadata(
393 const LoopAttributes &Attrs,
394 llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,
395 bool &HasUserTransforms) {
396 SmallVector<Metadata *, 3> LoopProperties;
397
398 // If we have a valid start debug location for the loop, add it.
399 if (StartLoc) {
400 LoopProperties.push_back(StartLoc.getAsMDNode());
401
402 // If we also have a valid end debug location for the loop, add it.
403 if (EndLoc)
404 LoopProperties.push_back(EndLoc.getAsMDNode());
405 }
406
407 LLVMContext &Ctx = Header->getContext();
408 if (Attrs.MustProgress)
409 LoopProperties.push_back(
410 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.mustprogress")));
411
412 if (Attrs.LICMDisabled)
413 LoopProperties.push_back(
414 MDNode::get(Ctx, MDString::get(Ctx, "llvm.licm.disable")));
415
416 assert(!!AccGroup == Attrs.IsParallel &&
417 "There must be an access group iff the loop is parallel");
418 if (Attrs.IsParallel) {
419 LoopProperties.push_back(MDNode::get(
420 Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
421 }
422
423 // Setting clang::code_align attribute.
424 if (Attrs.CodeAlign > 0) {
425 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.align"),
426 ConstantAsMetadata::get(ConstantInt::get(
427 llvm::Type::getInt32Ty(Ctx), Attrs.CodeAlign))};
428 LoopProperties.push_back(MDNode::get(Ctx, Vals));
429 }
430
431 llvm::append_range(LoopProperties, AdditionalLoopProperties);
432 return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
433}
434
445
464
466 const LoopAttributes &Attrs,
467 const llvm::DebugLoc &StartLoc,
468 const llvm::DebugLoc &EndLoc,
469 LoopInfo *Parent)
470 : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
471 Parent(Parent) {
472
473 if (Attrs.IsParallel) {
474 // Create an access group for this loop.
475 LLVMContext &Ctx = Header->getContext();
476 AccGroup = MDNode::getDistinct(Ctx, {});
477 }
478
479 if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
481 Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
482 Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
483 !Attrs.LICMDisabled && Attrs.PipelineInitiationInterval == 0 &&
489 Attrs.CodeAlign == 0 && !StartLoc && !EndLoc && !Attrs.MustProgress)
490 return;
491
492 TempLoopID = MDNode::getTemporary(Header->getContext(), {});
493}
494
496 // We did not annotate the loop body instructions because there are no
497 // attributes for this loop.
498 if (!TempLoopID)
499 return;
500
501 MDNode *LoopID;
502 LoopAttributes CurLoopAttr = Attrs;
503 LLVMContext &Ctx = Header->getContext();
504
505 if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
506 Parent->Attrs.UnrollAndJamCount != 0)) {
507 // Parent unroll-and-jams this loop.
508 // Split the transformations in those that happens before the unroll-and-jam
509 // and those after.
510
511 LoopAttributes BeforeJam, AfterJam;
512
513 BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
514
515 BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
516 BeforeJam.VectorizeScalable = Attrs.VectorizeScalable;
517 BeforeJam.InterleaveCount = Attrs.InterleaveCount;
518 BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
519 BeforeJam.DistributeEnable = Attrs.DistributeEnable;
520 BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
521 BeforeJam.LICMDisabled = Attrs.LICMDisabled;
522
523 switch (Attrs.UnrollEnable) {
526 BeforeJam.UnrollEnable = Attrs.UnrollEnable;
527 AfterJam.UnrollEnable = Attrs.UnrollEnable;
528 break;
531 break;
534 break;
535 }
536
537 AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
538 AfterJam.UnrollCount = Attrs.UnrollCount;
539 AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
540 AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;
541
542 // If this loop is subject of an unroll-and-jam by the parent loop, and has
543 // an unroll-and-jam annotation itself, we have to decide whether to first
544 // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
545 // UnrollAndJam pass processes loops from inner to outer, so we apply the
546 // inner first.
547 BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
548 BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
549
550 // Set the inner followup metadata to process by the outer loop. Only
551 // consider the first inner loop.
552 if (!Parent->UnrollAndJamInnerFollowup) {
553 // Splitting the attributes into a BeforeJam and an AfterJam part will
554 // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
555 // to be forwarded to the AfterJam part. We detect the situation here and
556 // add it manually.
557 SmallVector<Metadata *, 1> BeforeLoopProperties;
560 BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0 ||
562 BeforeLoopProperties.push_back(
563 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
564
565 bool InnerFollowupHasTransform = false;
566 SmallVector<Metadata *, 4> InnerFollowup = createMetadata(
567 AfterJam, BeforeLoopProperties, InnerFollowupHasTransform);
568 if (InnerFollowupHasTransform)
569 Parent->UnrollAndJamInnerFollowup = InnerFollowup;
570 }
571
572 CurLoopAttr = BeforeJam;
573 }
574
575 bool HasUserTransforms = false;
576 SmallVector<Metadata *, 4> Properties =
577 createMetadata(CurLoopAttr, {}, HasUserTransforms);
579 Args.push_back(nullptr);
580 Args.append(Properties.begin(), Properties.end());
581 LoopID = MDNode::getDistinct(Ctx, Args);
582 LoopID->replaceOperandWith(0, LoopID);
583
584 TempLoopID->replaceAllUsesWith(LoopID);
585}
586
587void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
588 const llvm::DebugLoc &EndLoc) {
589 Active.emplace_back(
590 new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
591 Active.empty() ? nullptr : Active.back().get()));
592 // Clear the attributes so nested loops do not inherit them.
593 StagedAttrs.clear();
594}
595
596void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
597 const clang::CodeGenOptions &CGOpts,
599 const llvm::DebugLoc &StartLoc,
600 const llvm::DebugLoc &EndLoc, bool MustProgress) {
601 // Identify loop hint attributes from Attrs.
602 for (const auto *Attr : Attrs) {
603 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
604 const OpenCLUnrollHintAttr *OpenCLHint =
605 dyn_cast<OpenCLUnrollHintAttr>(Attr);
606 const HLSLLoopHintAttr *HLSLLoopHint = dyn_cast<HLSLLoopHintAttr>(Attr);
607 // Skip non loop hint attributes
608 if (!LH && !OpenCLHint && !HLSLLoopHint) {
609 continue;
610 }
611
612 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
613 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
614 unsigned ValueInt = 1;
615 // Translate opencl_unroll_hint attribute argument to
616 // equivalent LoopHintAttr enums.
617 // OpenCL v2.0 s6.11.5:
618 // 0 - enable unroll (no argument).
619 // 1 - disable unroll.
620 // other positive integer n - unroll by n.
621 if (OpenCLHint) {
622 ValueInt = OpenCLHint->getUnrollHint();
623 if (ValueInt == 0) {
624 State = LoopHintAttr::Enable;
625 } else if (ValueInt != 1) {
626 Option = LoopHintAttr::UnrollCount;
627 State = LoopHintAttr::Numeric;
628 }
629 } else if (HLSLLoopHint) {
630 ValueInt = HLSLLoopHint->getDirective();
631 if (HLSLLoopHint->getSemanticSpelling() ==
632 HLSLLoopHintAttr::Spelling::Microsoft_unroll) {
633 if (ValueInt == 0)
634 State = LoopHintAttr::Enable;
635 if (ValueInt > 0) {
636 Option = LoopHintAttr::UnrollCount;
637 State = LoopHintAttr::Numeric;
638 }
639 }
640 } else if (LH) {
641 auto *ValueExpr = LH->getValue();
642 if (ValueExpr) {
643 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
644 ValueInt = ValueAPS.getSExtValue();
645 }
646
647 Option = LH->getOption();
648 State = LH->getState();
649 }
650 switch (State) {
651 case LoopHintAttr::Disable:
652 switch (Option) {
653 case LoopHintAttr::Vectorize:
654 // Disable vectorization by specifying a width of 1.
657 break;
658 case LoopHintAttr::Interleave:
659 // Disable interleaving by speciyfing a count of 1.
661 break;
662 case LoopHintAttr::Unroll:
664 break;
665 case LoopHintAttr::UnrollAndJam:
667 break;
668 case LoopHintAttr::VectorizePredicate:
670 break;
671 case LoopHintAttr::Distribute:
672 setDistributeState(false);
673 break;
674 case LoopHintAttr::PipelineDisabled:
676 break;
677 case LoopHintAttr::LICMDisabled:
678 setLICMDisabled(true);
679 break;
680 case LoopHintAttr::UnrollCount:
681 case LoopHintAttr::UnrollAndJamCount:
682 case LoopHintAttr::VectorizeWidth:
683 case LoopHintAttr::InterleaveCount:
684 case LoopHintAttr::PipelineInitiationInterval:
685 llvm_unreachable("Options cannot be disabled.");
686 break;
687 }
688 break;
689 case LoopHintAttr::Enable:
690 switch (Option) {
691 case LoopHintAttr::Vectorize:
692 case LoopHintAttr::Interleave:
693 setVectorizeEnable(true);
694 break;
695 case LoopHintAttr::Unroll:
697 break;
698 case LoopHintAttr::UnrollAndJam:
700 break;
701 case LoopHintAttr::VectorizePredicate:
703 break;
704 case LoopHintAttr::Distribute:
705 setDistributeState(true);
706 break;
707 case LoopHintAttr::UnrollCount:
708 case LoopHintAttr::UnrollAndJamCount:
709 case LoopHintAttr::VectorizeWidth:
710 case LoopHintAttr::InterleaveCount:
711 case LoopHintAttr::PipelineDisabled:
712 case LoopHintAttr::PipelineInitiationInterval:
713 case LoopHintAttr::LICMDisabled:
714 llvm_unreachable("Options cannot enabled.");
715 break;
716 }
717 break;
718 case LoopHintAttr::AssumeSafety:
719 switch (Option) {
720 case LoopHintAttr::Vectorize:
721 case LoopHintAttr::Interleave:
722 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
723 setParallel(true);
724 setVectorizeEnable(true);
725 break;
726 case LoopHintAttr::Unroll:
727 case LoopHintAttr::UnrollAndJam:
728 case LoopHintAttr::VectorizePredicate:
729 case LoopHintAttr::UnrollCount:
730 case LoopHintAttr::UnrollAndJamCount:
731 case LoopHintAttr::VectorizeWidth:
732 case LoopHintAttr::InterleaveCount:
733 case LoopHintAttr::Distribute:
734 case LoopHintAttr::PipelineDisabled:
735 case LoopHintAttr::PipelineInitiationInterval:
736 case LoopHintAttr::LICMDisabled:
737 llvm_unreachable("Options cannot be used to assume mem safety.");
738 break;
739 }
740 break;
741 case LoopHintAttr::Full:
742 switch (Option) {
743 case LoopHintAttr::Unroll:
745 break;
746 case LoopHintAttr::UnrollAndJam:
748 break;
749 case LoopHintAttr::Vectorize:
750 case LoopHintAttr::Interleave:
751 case LoopHintAttr::UnrollCount:
752 case LoopHintAttr::UnrollAndJamCount:
753 case LoopHintAttr::VectorizeWidth:
754 case LoopHintAttr::InterleaveCount:
755 case LoopHintAttr::Distribute:
756 case LoopHintAttr::PipelineDisabled:
757 case LoopHintAttr::PipelineInitiationInterval:
758 case LoopHintAttr::VectorizePredicate:
759 case LoopHintAttr::LICMDisabled:
760 llvm_unreachable("Options cannot be used with 'full' hint.");
761 break;
762 }
763 break;
764 case LoopHintAttr::FixedWidth:
765 case LoopHintAttr::ScalableWidth:
766 switch (Option) {
767 case LoopHintAttr::VectorizeWidth:
768 setVectorizeScalable(State == LoopHintAttr::ScalableWidth
771 if (LH->getValue())
772 setVectorizeWidth(ValueInt);
773 break;
774 default:
775 llvm_unreachable("Options cannot be used with 'scalable' hint.");
776 break;
777 }
778 break;
779 case LoopHintAttr::Numeric:
780 switch (Option) {
781 case LoopHintAttr::InterleaveCount:
782 setInterleaveCount(ValueInt);
783 break;
784 case LoopHintAttr::UnrollCount:
785 setUnrollCount(ValueInt);
786 break;
787 case LoopHintAttr::UnrollAndJamCount:
788 setUnrollAndJamCount(ValueInt);
789 break;
790 case LoopHintAttr::PipelineInitiationInterval:
792 break;
793 case LoopHintAttr::Unroll:
794 case LoopHintAttr::UnrollAndJam:
795 case LoopHintAttr::VectorizePredicate:
796 case LoopHintAttr::Vectorize:
797 case LoopHintAttr::VectorizeWidth:
798 case LoopHintAttr::Interleave:
799 case LoopHintAttr::Distribute:
800 case LoopHintAttr::PipelineDisabled:
801 case LoopHintAttr::LICMDisabled:
802 llvm_unreachable("Options cannot be assigned a value.");
803 break;
804 }
805 break;
806 }
807 }
808
809 // Identify loop attribute 'code_align' from Attrs.
810 // For attribute code_align:
811 // n - 'llvm.loop.align i32 n' metadata will be emitted.
812 if (const auto *CodeAlign = getSpecificAttr<CodeAlignAttr>(Attrs)) {
813 const auto *CE = cast<ConstantExpr>(CodeAlign->getAlignment());
814 llvm::APSInt ArgVal = CE->getResultAsAPSInt();
815 setCodeAlign(ArgVal.getSExtValue());
816 }
817
818 setMustProgress(MustProgress);
819
820 if (CGOpts.OptimizationLevel > 0)
821 // Disable unrolling for the loop, if unrolling is disabled (via
822 // -fno-unroll-loops) and no pragmas override the decision.
823 if (!CGOpts.UnrollLoops &&
824 (StagedAttrs.UnrollEnable == LoopAttributes::Unspecified &&
825 StagedAttrs.UnrollCount == 0))
827
828 /// Stage the attributes.
829 push(Header, StartLoc, EndLoc);
830}
831
833 assert(!Active.empty() && "No active loops to pop");
834 Active.back()->finish();
835 Active.pop_back();
836}
837
838void LoopInfoStack::InsertHelper(Instruction *I) const {
839 if (I->mayReadOrWriteMemory()) {
840 SmallVector<Metadata *, 4> AccessGroups;
841 for (const auto &AL : Active) {
842 // Here we assume that every loop that has an access group is parallel.
843 if (MDNode *Group = AL->getAccessGroup())
844 AccessGroups.push_back(Group);
845 }
846 MDNode *UnionMD = nullptr;
847 if (AccessGroups.size() == 1)
848 UnionMD = cast<MDNode>(AccessGroups[0]);
849 else if (AccessGroups.size() >= 2)
850 UnionMD = MDNode::get(I->getContext(), AccessGroups);
851 I->setMetadata("llvm.access.group", UnionMD);
852 }
853
854 if (!hasInfo())
855 return;
856
857 const LoopInfo &L = getInfo();
858 if (!L.getLoopID())
859 return;
860
861 if (I->isTerminator()) {
862 for (BasicBlock *Succ : successors(I))
863 if (Succ == L.getHeader()) {
864 I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
865 break;
866 }
867 return;
868 }
869}
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:223
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 setPipelineDisabled(bool S)
Set the pipeline disabled state.
Definition CGLoopInfo.h:296
void setUnrollCount(unsigned C)
Set the unroll count for the next loop pushed.
Definition CGLoopInfo.h:290
bool hasInfo() const
Returns true if there is LoopInfo on the stack.
Definition CGLoopInfo.h:310
void setVectorizeWidth(unsigned W)
Set the vectorize width for the next loop pushed.
Definition CGLoopInfo.h:280
void InsertHelper(llvm::Instruction *I) const
Function called by the CodeGenFunction when an instruction is created.
void setDistributeState(bool Enable=true)
Set the next pushed loop as a distribution candidate.
Definition CGLoopInfo.h:254
void setParallel(bool Enable=true)
Set the next pushed loop as parallel.
Definition CGLoopInfo.h:245
void setInterleaveCount(unsigned C)
Set the interleave count for the next loop pushed.
Definition CGLoopInfo.h:287
void setUnrollState(const LoopAttributes::LVEnableState &State)
Set the next pushed loop unroll state.
Definition CGLoopInfo.h:265
void setVectorizeScalable(const LoopAttributes::LVEnableState &State)
Definition CGLoopInfo.h:282
void setVectorizePredicateState(const LoopAttributes::LVEnableState &State)
Set the next pushed vectorize predicate state.
Definition CGLoopInfo.h:270
void pop()
End the current loop.
void setCodeAlign(unsigned C)
Set value of code align for the next loop pushed.
Definition CGLoopInfo.h:304
void setLICMDisabled(bool Disabled=true)
Set the next pushed loop LICM disable state.
Definition CGLoopInfo.h:260
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
void setMustProgress(bool P)
Set no progress for the next loop pushed.
Definition CGLoopInfo.h:307
void setUnrollAndJamState(const LoopAttributes::LVEnableState &State)
Set the next pushed loop unroll_and_jam state.
Definition CGLoopInfo.h:275
void setUnrollAndJamCount(unsigned C)
Set the unroll count for the next loop pushed.
Definition CGLoopInfo.h:293
const LoopInfo & getInfo() const
Return the LoopInfo for the current loop.
Definition CGLoopInfo.h:313
void setPipelineInitiationInterval(unsigned C)
Set the pipeline initiation interval.
Definition CGLoopInfo.h:299
void setVectorizeEnable(bool Enable=true)
Set the next pushed loop 'vectorize.enable'.
Definition CGLoopInfo.h:248
Information used when generating a structured loop.
Definition CGLoopInfo.h:93
void finish()
Create the loop's metadata.
llvm::BasicBlock * getHeader() const
Get the header block of this loop.
Definition CGLoopInfo.h:104
LoopInfo(llvm::BasicBlock *Header, const LoopAttributes &Attrs, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc, LoopInfo *Parent)
Construct a new LoopInfo for the loop with entry Header.
llvm::MDNode * getLoopID() const
Get the loop id metadata for this loop.
Definition CGLoopInfo.h:101
auto * getSpecificAttr(const Container &container)
U cast(CodeGen::Address addr)
Definition Address.h:327
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
#define false
Definition stdbool.h:26
Attributes that may be specified on loops.
Definition CGLoopInfo.h:36
unsigned UnrollCount
llvm.unroll.
Definition CGLoopInfo.h:68
bool MustProgress
Value for whether the loop is required to make progress.
Definition CGLoopInfo.h:89
unsigned InterleaveCount
Value for llvm.loop.interleave.count metadata.
Definition CGLoopInfo.h:65
LoopAttributes(bool IsParallel=false)
bool IsParallel
Generate llvm.loop.parallel metadata for loads and stores.
Definition CGLoopInfo.h:41
bool LICMDisabled
Value for llvm.licm.disable metadata.
Definition CGLoopInfo.h:80
LVEnableState UnrollAndJamEnable
Value for llvm.loop.unroll_and_jam.* metadata (enable, disable, or full).
Definition CGLoopInfo.h:53
unsigned UnrollAndJamCount
llvm.unroll.
Definition CGLoopInfo.h:71
LVEnableState VectorizePredicateEnable
Value for llvm.loop.vectorize.predicate metadata.
Definition CGLoopInfo.h:56
LVEnableState DistributeEnable
Value for llvm.loop.distribute.enable metadata.
Definition CGLoopInfo.h:74
bool PipelineDisabled
Value for llvm.loop.pipeline.disable metadata.
Definition CGLoopInfo.h:77
unsigned CodeAlign
Value for 'llvm.loop.align' metadata.
Definition CGLoopInfo.h:86
LVEnableState UnrollEnable
Value for llvm.loop.unroll.* metadata (enable, disable, or full).
Definition CGLoopInfo.h:50
unsigned VectorizeWidth
Value for llvm.loop.vectorize.width metadata.
Definition CGLoopInfo.h:59
unsigned PipelineInitiationInterval
Value for llvm.loop.pipeline.iicount metadata.
Definition CGLoopInfo.h:83
LVEnableState VectorizeEnable
Value for llvm.loop.vectorize.enable metadata.
Definition CGLoopInfo.h:47