1 //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "CGLoopInfo.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/Attr.h"
12 #include "llvm/IR/BasicBlock.h"
13 #include "llvm/IR/CFG.h"
14 #include "llvm/IR/Constants.h"
15 #include "llvm/IR/InstrTypes.h"
16 #include "llvm/IR/Instructions.h"
17 #include "llvm/IR/Metadata.h"
18 using namespace clang::CodeGen;
22 LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) {
23 LLVMContext &Ctx = Header->getContext();
24 SmallVector<Metadata *, 4> NewLoopProperties;
25 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
26 NewLoopProperties.push_back(TempNode.get());
27 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
29 MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties);
30 LoopID->replaceOperandWith(0, LoopID);
34 MDNode *LoopInfo::createPipeliningMetadata(const LoopAttributes &Attrs,
35 ArrayRef<Metadata *> LoopProperties,
36 bool &HasUserTransforms) {
37 LLVMContext &Ctx = Header->getContext();
39 Optional<bool> Enabled;
40 if (Attrs.PipelineDisabled)
42 else if (Attrs.PipelineInitiationInterval != 0)
45 if (Enabled != true) {
46 SmallVector<Metadata *, 4> NewLoopProperties;
47 if (Enabled == false) {
48 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
49 NewLoopProperties.push_back(
50 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"),
51 ConstantAsMetadata::get(ConstantInt::get(
52 llvm::Type::getInt1Ty(Ctx), 1))}));
53 LoopProperties = NewLoopProperties;
55 return createLoopPropertiesMetadata(LoopProperties);
58 SmallVector<Metadata *, 4> Args;
59 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
60 Args.push_back(TempNode.get());
61 Args.append(LoopProperties.begin(), LoopProperties.end());
63 if (Attrs.PipelineInitiationInterval > 0) {
65 MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
66 ConstantAsMetadata::get(ConstantInt::get(
67 llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
68 Args.push_back(MDNode::get(Ctx, Vals));
71 // No follow-up: This is the last transformation.
73 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
74 LoopID->replaceOperandWith(0, LoopID);
75 HasUserTransforms = true;
80 LoopInfo::createPartialUnrollMetadata(const LoopAttributes &Attrs,
81 ArrayRef<Metadata *> LoopProperties,
82 bool &HasUserTransforms) {
83 LLVMContext &Ctx = Header->getContext();
85 Optional<bool> Enabled;
86 if (Attrs.UnrollEnable == LoopAttributes::Disable)
88 else if (Attrs.UnrollEnable == LoopAttributes::Full)
90 else if (Attrs.UnrollEnable != LoopAttributes::Unspecified ||
91 Attrs.UnrollCount != 0)
94 if (Enabled != true) {
95 // createFullUnrollMetadata will already have added llvm.loop.unroll.disable
96 // if unrolling is disabled.
97 return createPipeliningMetadata(Attrs, LoopProperties, HasUserTransforms);
100 SmallVector<Metadata *, 4> FollowupLoopProperties;
102 // Apply all loop properties to the unrolled loop.
103 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
105 // Don't unroll an already unrolled loop.
106 FollowupLoopProperties.push_back(
107 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
109 bool FollowupHasTransforms = false;
110 MDNode *Followup = createPipeliningMetadata(Attrs, FollowupLoopProperties,
111 FollowupHasTransforms);
113 SmallVector<Metadata *, 4> Args;
114 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
115 Args.push_back(TempNode.get());
116 Args.append(LoopProperties.begin(), LoopProperties.end());
118 // Setting unroll.count
119 if (Attrs.UnrollCount > 0) {
120 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
121 ConstantAsMetadata::get(ConstantInt::get(
122 llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
123 Args.push_back(MDNode::get(Ctx, Vals));
126 // Setting unroll.full or unroll.disable
127 if (Attrs.UnrollEnable == LoopAttributes::Enable) {
128 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")};
129 Args.push_back(MDNode::get(Ctx, Vals));
132 if (FollowupHasTransforms)
133 Args.push_back(MDNode::get(
134 Ctx, {MDString::get(Ctx, "llvm.loop.unroll.followup_all"), Followup}));
136 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
137 LoopID->replaceOperandWith(0, LoopID);
138 HasUserTransforms = true;
143 LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs,
144 ArrayRef<Metadata *> LoopProperties,
145 bool &HasUserTransforms) {
146 LLVMContext &Ctx = Header->getContext();
148 Optional<bool> Enabled;
149 if (Attrs.UnrollAndJamEnable == LoopAttributes::Disable)
151 else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable ||
152 Attrs.UnrollAndJamCount != 0)
155 if (Enabled != true) {
156 SmallVector<Metadata *, 4> NewLoopProperties;
157 if (Enabled == false) {
158 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
159 NewLoopProperties.push_back(MDNode::get(
160 Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
161 LoopProperties = NewLoopProperties;
163 return createPartialUnrollMetadata(Attrs, LoopProperties,
167 SmallVector<Metadata *, 4> FollowupLoopProperties;
168 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
169 FollowupLoopProperties.push_back(
170 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
172 bool FollowupHasTransforms = false;
173 MDNode *Followup = createPartialUnrollMetadata(Attrs, FollowupLoopProperties,
174 FollowupHasTransforms);
176 SmallVector<Metadata *, 4> Args;
177 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
178 Args.push_back(TempNode.get());
179 Args.append(LoopProperties.begin(), LoopProperties.end());
181 // Setting unroll_and_jam.count
182 if (Attrs.UnrollAndJamCount > 0) {
184 MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
185 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
186 Attrs.UnrollAndJamCount))};
187 Args.push_back(MDNode::get(Ctx, Vals));
190 if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) {
191 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")};
192 Args.push_back(MDNode::get(Ctx, Vals));
195 if (FollowupHasTransforms)
196 Args.push_back(MDNode::get(
197 Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_outer"),
200 if (UnrollAndJamInnerFollowup)
201 Args.push_back(MDNode::get(
202 Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_inner"),
203 UnrollAndJamInnerFollowup}));
205 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
206 LoopID->replaceOperandWith(0, LoopID);
207 HasUserTransforms = true;
212 LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs,
213 ArrayRef<Metadata *> LoopProperties,
214 bool &HasUserTransforms) {
215 LLVMContext &Ctx = Header->getContext();
217 Optional<bool> Enabled;
218 if (Attrs.VectorizeEnable == LoopAttributes::Disable)
220 else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
221 Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified ||
222 Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0)
225 if (Enabled != true) {
226 SmallVector<Metadata *, 4> NewLoopProperties;
227 if (Enabled == false) {
228 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
229 NewLoopProperties.push_back(
230 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
231 ConstantAsMetadata::get(ConstantInt::get(
232 llvm::Type::getInt1Ty(Ctx), 0))}));
233 LoopProperties = NewLoopProperties;
235 return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms);
238 // Apply all loop properties to the vectorized loop.
239 SmallVector<Metadata *, 4> FollowupLoopProperties;
240 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
242 // Don't vectorize an already vectorized loop.
243 FollowupLoopProperties.push_back(
244 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
246 bool FollowupHasTransforms = false;
247 MDNode *Followup = createUnrollAndJamMetadata(Attrs, FollowupLoopProperties,
248 FollowupHasTransforms);
250 SmallVector<Metadata *, 4> Args;
251 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
252 Args.push_back(TempNode.get());
253 Args.append(LoopProperties.begin(), LoopProperties.end());
255 // Setting vectorize.predicate
256 bool IsVectorPredicateEnabled = false;
257 if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified &&
258 Attrs.VectorizeEnable != LoopAttributes::Disable &&
259 Attrs.VectorizeWidth < 1) {
261 IsVectorPredicateEnabled =
262 (Attrs.VectorizePredicateEnable == LoopAttributes::Enable);
265 MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"),
266 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx),
267 IsVectorPredicateEnabled))};
268 Args.push_back(MDNode::get(Ctx, Vals));
271 // Setting vectorize.width
272 if (Attrs.VectorizeWidth > 0) {
273 // This implies vectorize.enable = true, but only add it when it is not
275 if (Attrs.VectorizeEnable != LoopAttributes::Enable)
277 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
278 ConstantAsMetadata::get(ConstantInt::get(
279 llvm::Type::getInt1Ty(Ctx), 1))}));
282 MDString::get(Ctx, "llvm.loop.vectorize.width"),
283 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
284 Attrs.VectorizeWidth))};
285 Args.push_back(MDNode::get(Ctx, Vals));
288 // Setting interleave.count
289 if (Attrs.InterleaveCount > 0) {
291 MDString::get(Ctx, "llvm.loop.interleave.count"),
292 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
293 Attrs.InterleaveCount))};
294 Args.push_back(MDNode::get(Ctx, Vals));
297 // Setting vectorize.enable
298 if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
299 IsVectorPredicateEnabled) {
301 MDString::get(Ctx, "llvm.loop.vectorize.enable"),
302 ConstantAsMetadata::get(ConstantInt::get(
303 llvm::Type::getInt1Ty(Ctx),
304 IsVectorPredicateEnabled
306 : (Attrs.VectorizeEnable == LoopAttributes::Enable)))};
307 Args.push_back(MDNode::get(Ctx, Vals));
310 if (FollowupHasTransforms)
311 Args.push_back(MDNode::get(
313 {MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup}));
315 MDNode *LoopID = MDNode::get(Ctx, Args);
316 LoopID->replaceOperandWith(0, LoopID);
317 HasUserTransforms = true;
322 LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs,
323 ArrayRef<Metadata *> LoopProperties,
324 bool &HasUserTransforms) {
325 LLVMContext &Ctx = Header->getContext();
327 Optional<bool> Enabled;
328 if (Attrs.DistributeEnable == LoopAttributes::Disable)
330 if (Attrs.DistributeEnable == LoopAttributes::Enable)
333 if (Enabled != true) {
334 SmallVector<Metadata *, 4> NewLoopProperties;
335 if (Enabled == false) {
336 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
337 NewLoopProperties.push_back(
338 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),
339 ConstantAsMetadata::get(ConstantInt::get(
340 llvm::Type::getInt1Ty(Ctx), 0))}));
341 LoopProperties = NewLoopProperties;
343 return createLoopVectorizeMetadata(Attrs, LoopProperties,
347 bool FollowupHasTransforms = false;
349 createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);
351 SmallVector<Metadata *, 4> Args;
352 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
353 Args.push_back(TempNode.get());
354 Args.append(LoopProperties.begin(), LoopProperties.end());
356 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
357 ConstantAsMetadata::get(ConstantInt::get(
358 llvm::Type::getInt1Ty(Ctx),
359 (Attrs.DistributeEnable == LoopAttributes::Enable)))};
360 Args.push_back(MDNode::get(Ctx, Vals));
362 if (FollowupHasTransforms)
363 Args.push_back(MDNode::get(
365 {MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup}));
367 MDNode *LoopID = MDNode::get(Ctx, Args);
368 LoopID->replaceOperandWith(0, LoopID);
369 HasUserTransforms = true;
373 MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,
374 ArrayRef<Metadata *> LoopProperties,
375 bool &HasUserTransforms) {
376 LLVMContext &Ctx = Header->getContext();
378 Optional<bool> Enabled;
379 if (Attrs.UnrollEnable == LoopAttributes::Disable)
381 else if (Attrs.UnrollEnable == LoopAttributes::Full)
384 if (Enabled != true) {
385 SmallVector<Metadata *, 4> NewLoopProperties;
386 if (Enabled == false) {
387 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
388 NewLoopProperties.push_back(
389 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
390 LoopProperties = NewLoopProperties;
392 return createLoopDistributeMetadata(Attrs, LoopProperties,
396 SmallVector<Metadata *, 4> Args;
397 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
398 Args.push_back(TempNode.get());
399 Args.append(LoopProperties.begin(), LoopProperties.end());
400 Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));
402 // No follow-up: there is no loop after full unrolling.
403 // TODO: Warn if there are transformations after full unrolling.
405 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
406 LoopID->replaceOperandWith(0, LoopID);
407 HasUserTransforms = true;
411 MDNode *LoopInfo::createMetadata(
412 const LoopAttributes &Attrs,
413 llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,
414 bool &HasUserTransforms) {
415 SmallVector<Metadata *, 3> LoopProperties;
417 // If we have a valid start debug location for the loop, add it.
419 LoopProperties.push_back(StartLoc.getAsMDNode());
421 // If we also have a valid end debug location for the loop, add it.
423 LoopProperties.push_back(EndLoc.getAsMDNode());
426 assert(!!AccGroup == Attrs.IsParallel &&
427 "There must be an access group iff the loop is parallel");
428 if (Attrs.IsParallel) {
429 LLVMContext &Ctx = Header->getContext();
430 LoopProperties.push_back(MDNode::get(
431 Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
434 LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
435 AdditionalLoopProperties.end());
436 return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
439 LoopAttributes::LoopAttributes(bool IsParallel)
440 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
441 UnrollEnable(LoopAttributes::Unspecified),
442 UnrollAndJamEnable(LoopAttributes::Unspecified),
443 VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
444 InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0),
445 DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
446 PipelineInitiationInterval(0) {}
448 void LoopAttributes::clear() {
453 UnrollAndJamCount = 0;
454 VectorizeEnable = LoopAttributes::Unspecified;
455 UnrollEnable = LoopAttributes::Unspecified;
456 UnrollAndJamEnable = LoopAttributes::Unspecified;
457 VectorizePredicateEnable = LoopAttributes::Unspecified;
458 DistributeEnable = LoopAttributes::Unspecified;
459 PipelineDisabled = false;
460 PipelineInitiationInterval = 0;
463 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
464 const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
466 : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
469 if (Attrs.IsParallel) {
470 // Create an access group for this loop.
471 LLVMContext &Ctx = Header->getContext();
472 AccGroup = MDNode::getDistinct(Ctx, {});
475 if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
476 Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
477 Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
478 Attrs.PipelineInitiationInterval == 0 &&
479 Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified &&
480 Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
481 Attrs.UnrollEnable == LoopAttributes::Unspecified &&
482 Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
483 Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
487 TempLoopID = MDNode::getTemporary(Header->getContext(), None);
490 void LoopInfo::finish() {
491 // We did not annotate the loop body instructions because there are no
492 // attributes for this loop.
497 LoopAttributes CurLoopAttr = Attrs;
498 LLVMContext &Ctx = Header->getContext();
500 if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
501 Parent->Attrs.UnrollAndJamCount != 0)) {
502 // Parent unroll-and-jams this loop.
503 // Split the transformations in those that happens before the unroll-and-jam
506 LoopAttributes BeforeJam, AfterJam;
508 BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
510 BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
511 BeforeJam.InterleaveCount = Attrs.InterleaveCount;
512 BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
513 BeforeJam.DistributeEnable = Attrs.DistributeEnable;
514 BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
516 switch (Attrs.UnrollEnable) {
517 case LoopAttributes::Unspecified:
518 case LoopAttributes::Disable:
519 BeforeJam.UnrollEnable = Attrs.UnrollEnable;
520 AfterJam.UnrollEnable = Attrs.UnrollEnable;
522 case LoopAttributes::Full:
523 BeforeJam.UnrollEnable = LoopAttributes::Full;
525 case LoopAttributes::Enable:
526 AfterJam.UnrollEnable = LoopAttributes::Enable;
530 AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
531 AfterJam.UnrollCount = Attrs.UnrollCount;
532 AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
533 AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;
535 // If this loop is subject of an unroll-and-jam by the parent loop, and has
536 // an unroll-and-jam annotation itself, we have to decide whether to first
537 // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
538 // UnrollAndJam pass processes loops from inner to outer, so we apply the
540 BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
541 BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
543 // Set the inner followup metadata to process by the outer loop. Only
544 // consider the first inner loop.
545 if (!Parent->UnrollAndJamInnerFollowup) {
546 // Splitting the attributes into a BeforeJam and an AfterJam part will
547 // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
548 // to be forwarded to the AfterJam part. We detect the situation here and
550 SmallVector<Metadata *, 1> BeforeLoopProperties;
551 if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||
552 BeforeJam.VectorizePredicateEnable != LoopAttributes::Unspecified ||
553 BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0)
554 BeforeLoopProperties.push_back(
555 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
557 bool InnerFollowupHasTransform = false;
558 MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,
559 InnerFollowupHasTransform);
560 if (InnerFollowupHasTransform)
561 Parent->UnrollAndJamInnerFollowup = InnerFollowup;
564 CurLoopAttr = BeforeJam;
567 bool HasUserTransforms = false;
568 LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);
569 TempLoopID->replaceAllUsesWith(LoopID);
572 void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
573 const llvm::DebugLoc &EndLoc) {
575 new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
576 Active.empty() ? nullptr : Active.back().get()));
577 // Clear the attributes so nested loops do not inherit them.
581 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
582 ArrayRef<const clang::Attr *> Attrs,
583 const llvm::DebugLoc &StartLoc,
584 const llvm::DebugLoc &EndLoc) {
586 // Identify loop hint attributes from Attrs.
587 for (const auto *Attr : Attrs) {
588 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
589 const OpenCLUnrollHintAttr *OpenCLHint =
590 dyn_cast<OpenCLUnrollHintAttr>(Attr);
592 // Skip non loop hint attributes
593 if (!LH && !OpenCLHint) {
597 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
598 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
599 unsigned ValueInt = 1;
600 // Translate opencl_unroll_hint attribute argument to
601 // equivalent LoopHintAttr enums.
602 // OpenCL v2.0 s6.11.5:
603 // 0 - enable unroll (no argument).
604 // 1 - disable unroll.
605 // other positive integer n - unroll by n.
607 ValueInt = OpenCLHint->getUnrollHint();
609 State = LoopHintAttr::Enable;
610 } else if (ValueInt != 1) {
611 Option = LoopHintAttr::UnrollCount;
612 State = LoopHintAttr::Numeric;
615 auto *ValueExpr = LH->getValue();
617 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
618 ValueInt = ValueAPS.getSExtValue();
621 Option = LH->getOption();
622 State = LH->getState();
625 case LoopHintAttr::Disable:
627 case LoopHintAttr::Vectorize:
628 // Disable vectorization by specifying a width of 1.
629 setVectorizeWidth(1);
631 case LoopHintAttr::Interleave:
632 // Disable interleaving by speciyfing a count of 1.
633 setInterleaveCount(1);
635 case LoopHintAttr::Unroll:
636 setUnrollState(LoopAttributes::Disable);
638 case LoopHintAttr::UnrollAndJam:
639 setUnrollAndJamState(LoopAttributes::Disable);
641 case LoopHintAttr::VectorizePredicate:
642 setVectorizePredicateState(LoopAttributes::Disable);
644 case LoopHintAttr::Distribute:
645 setDistributeState(false);
647 case LoopHintAttr::PipelineDisabled:
648 setPipelineDisabled(true);
650 case LoopHintAttr::UnrollCount:
651 case LoopHintAttr::UnrollAndJamCount:
652 case LoopHintAttr::VectorizeWidth:
653 case LoopHintAttr::InterleaveCount:
654 case LoopHintAttr::PipelineInitiationInterval:
655 llvm_unreachable("Options cannot be disabled.");
659 case LoopHintAttr::Enable:
661 case LoopHintAttr::Vectorize:
662 case LoopHintAttr::Interleave:
663 setVectorizeEnable(true);
665 case LoopHintAttr::Unroll:
666 setUnrollState(LoopAttributes::Enable);
668 case LoopHintAttr::UnrollAndJam:
669 setUnrollAndJamState(LoopAttributes::Enable);
671 case LoopHintAttr::VectorizePredicate:
672 setVectorizePredicateState(LoopAttributes::Enable);
674 case LoopHintAttr::Distribute:
675 setDistributeState(true);
677 case LoopHintAttr::UnrollCount:
678 case LoopHintAttr::UnrollAndJamCount:
679 case LoopHintAttr::VectorizeWidth:
680 case LoopHintAttr::InterleaveCount:
681 case LoopHintAttr::PipelineDisabled:
682 case LoopHintAttr::PipelineInitiationInterval:
683 llvm_unreachable("Options cannot enabled.");
687 case LoopHintAttr::AssumeSafety:
689 case LoopHintAttr::Vectorize:
690 case LoopHintAttr::Interleave:
691 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
693 setVectorizeEnable(true);
695 case LoopHintAttr::Unroll:
696 case LoopHintAttr::UnrollAndJam:
697 case LoopHintAttr::VectorizePredicate:
698 case LoopHintAttr::UnrollCount:
699 case LoopHintAttr::UnrollAndJamCount:
700 case LoopHintAttr::VectorizeWidth:
701 case LoopHintAttr::InterleaveCount:
702 case LoopHintAttr::Distribute:
703 case LoopHintAttr::PipelineDisabled:
704 case LoopHintAttr::PipelineInitiationInterval:
705 llvm_unreachable("Options cannot be used to assume mem safety.");
709 case LoopHintAttr::Full:
711 case LoopHintAttr::Unroll:
712 setUnrollState(LoopAttributes::Full);
714 case LoopHintAttr::UnrollAndJam:
715 setUnrollAndJamState(LoopAttributes::Full);
717 case LoopHintAttr::Vectorize:
718 case LoopHintAttr::Interleave:
719 case LoopHintAttr::UnrollCount:
720 case LoopHintAttr::UnrollAndJamCount:
721 case LoopHintAttr::VectorizeWidth:
722 case LoopHintAttr::InterleaveCount:
723 case LoopHintAttr::Distribute:
724 case LoopHintAttr::PipelineDisabled:
725 case LoopHintAttr::PipelineInitiationInterval:
726 case LoopHintAttr::VectorizePredicate:
727 llvm_unreachable("Options cannot be used with 'full' hint.");
731 case LoopHintAttr::Numeric:
733 case LoopHintAttr::VectorizeWidth:
734 setVectorizeWidth(ValueInt);
736 case LoopHintAttr::InterleaveCount:
737 setInterleaveCount(ValueInt);
739 case LoopHintAttr::UnrollCount:
740 setUnrollCount(ValueInt);
742 case LoopHintAttr::UnrollAndJamCount:
743 setUnrollAndJamCount(ValueInt);
745 case LoopHintAttr::PipelineInitiationInterval:
746 setPipelineInitiationInterval(ValueInt);
748 case LoopHintAttr::Unroll:
749 case LoopHintAttr::UnrollAndJam:
750 case LoopHintAttr::VectorizePredicate:
751 case LoopHintAttr::Vectorize:
752 case LoopHintAttr::Interleave:
753 case LoopHintAttr::Distribute:
754 case LoopHintAttr::PipelineDisabled:
755 llvm_unreachable("Options cannot be assigned a value.");
762 /// Stage the attributes.
763 push(Header, StartLoc, EndLoc);
766 void LoopInfoStack::pop() {
767 assert(!Active.empty() && "No active loops to pop");
768 Active.back()->finish();
772 void LoopInfoStack::InsertHelper(Instruction *I) const {
773 if (I->mayReadOrWriteMemory()) {
774 SmallVector<Metadata *, 4> AccessGroups;
775 for (const auto &AL : Active) {
776 // Here we assume that every loop that has an access group is parallel.
777 if (MDNode *Group = AL->getAccessGroup())
778 AccessGroups.push_back(Group);
780 MDNode *UnionMD = nullptr;
781 if (AccessGroups.size() == 1)
782 UnionMD = cast<MDNode>(AccessGroups[0]);
783 else if (AccessGroups.size() >= 2)
784 UnionMD = MDNode::get(I->getContext(), AccessGroups);
785 I->setMetadata("llvm.access.group", UnionMD);
791 const LoopInfo &L = getInfo();
795 if (I->isTerminator()) {
796 for (BasicBlock *Succ : successors(I))
797 if (Succ == L.getHeader()) {
798 I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());