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