1515ad8c4SAlexander Musman //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
2515ad8c4SAlexander Musman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6515ad8c4SAlexander Musman //
7515ad8c4SAlexander Musman //===----------------------------------------------------------------------===//
8515ad8c4SAlexander Musman 
9515ad8c4SAlexander Musman #include "CGLoopInfo.h"
1054c020d3STyler Nowicki #include "clang/AST/ASTContext.h"
119d268e17STyler Nowicki #include "clang/AST/Attr.h"
1226d254f0SReid Kleckner #include "clang/AST/Expr.h"
13338be9c5SFlorian Hahn #include "clang/Basic/CodeGenOptions.h"
14515ad8c4SAlexander Musman #include "llvm/IR/BasicBlock.h"
154aaaaabeSChandler Carruth #include "llvm/IR/CFG.h"
16515ad8c4SAlexander Musman #include "llvm/IR/Constants.h"
17515ad8c4SAlexander Musman #include "llvm/IR/InstrTypes.h"
18515ad8c4SAlexander Musman #include "llvm/IR/Instructions.h"
19515ad8c4SAlexander Musman #include "llvm/IR/Metadata.h"
204e8e900dSTyler Nowicki using namespace clang::CodeGen;
21515ad8c4SAlexander Musman using namespace llvm;
22515ad8c4SAlexander Musman 
2358e76426SMichael Kruse MDNode *
createLoopPropertiesMetadata(ArrayRef<Metadata * > LoopProperties)2458e76426SMichael Kruse LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) {
2558e76426SMichael Kruse   LLVMContext &Ctx = Header->getContext();
2658e76426SMichael Kruse   SmallVector<Metadata *, 4> NewLoopProperties;
27d4c667c9SDuncan P. N. Exon Smith   NewLoopProperties.push_back(nullptr);
2858e76426SMichael Kruse   NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
29515ad8c4SAlexander Musman 
3058e76426SMichael Kruse   MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties);
3158e76426SMichael Kruse   LoopID->replaceOperandWith(0, LoopID);
3258e76426SMichael Kruse   return LoopID;
3358e76426SMichael Kruse }
3458e76426SMichael Kruse 
createPipeliningMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)3558e76426SMichael Kruse MDNode *LoopInfo::createPipeliningMetadata(const LoopAttributes &Attrs,
3658e76426SMichael Kruse                                            ArrayRef<Metadata *> LoopProperties,
3758e76426SMichael Kruse                                            bool &HasUserTransforms) {
3858e76426SMichael Kruse   LLVMContext &Ctx = Header->getContext();
3958e76426SMichael Kruse 
4058e76426SMichael Kruse   Optional<bool> Enabled;
4158e76426SMichael Kruse   if (Attrs.PipelineDisabled)
4258e76426SMichael Kruse     Enabled = false;
4358e76426SMichael Kruse   else if (Attrs.PipelineInitiationInterval != 0)
4458e76426SMichael Kruse     Enabled = true;
4558e76426SMichael Kruse 
4658e76426SMichael Kruse   if (Enabled != true) {
4758e76426SMichael Kruse     SmallVector<Metadata *, 4> NewLoopProperties;
4858e76426SMichael Kruse     if (Enabled == false) {
4958e76426SMichael Kruse       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
5058e76426SMichael Kruse       NewLoopProperties.push_back(
5158e76426SMichael Kruse           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"),
5258e76426SMichael Kruse                             ConstantAsMetadata::get(ConstantInt::get(
5358e76426SMichael Kruse                                 llvm::Type::getInt1Ty(Ctx), 1))}));
5458e76426SMichael Kruse       LoopProperties = NewLoopProperties;
5558e76426SMichael Kruse     }
5658e76426SMichael Kruse     return createLoopPropertiesMetadata(LoopProperties);
5758e76426SMichael Kruse   }
58515ad8c4SAlexander Musman 
59fb494914SDuncan P. N. Exon Smith   SmallVector<Metadata *, 4> Args;
60d4c667c9SDuncan P. N. Exon Smith   Args.push_back(nullptr);
6158e76426SMichael Kruse   Args.append(LoopProperties.begin(), LoopProperties.end());
629bdf515cSAaron Ballman 
639bdf515cSAaron Ballman   if (Attrs.PipelineInitiationInterval > 0) {
649bdf515cSAaron Ballman     Metadata *Vals[] = {
659bdf515cSAaron Ballman         MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
669bdf515cSAaron Ballman         ConstantAsMetadata::get(ConstantInt::get(
6758e76426SMichael Kruse             llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
689bdf515cSAaron Ballman     Args.push_back(MDNode::get(Ctx, Vals));
699bdf515cSAaron Ballman   }
709bdf515cSAaron Ballman 
7158e76426SMichael Kruse   // No follow-up: This is the last transformation.
7258e76426SMichael Kruse 
7358e76426SMichael Kruse   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
7458e76426SMichael Kruse   LoopID->replaceOperandWith(0, LoopID);
7558e76426SMichael Kruse   HasUserTransforms = true;
7658e76426SMichael Kruse   return LoopID;
7758e76426SMichael Kruse }
7858e76426SMichael Kruse 
7958e76426SMichael Kruse MDNode *
createPartialUnrollMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)8058e76426SMichael Kruse LoopInfo::createPartialUnrollMetadata(const LoopAttributes &Attrs,
8158e76426SMichael Kruse                                       ArrayRef<Metadata *> LoopProperties,
8258e76426SMichael Kruse                                       bool &HasUserTransforms) {
8358e76426SMichael Kruse   LLVMContext &Ctx = Header->getContext();
8458e76426SMichael Kruse 
8558e76426SMichael Kruse   Optional<bool> Enabled;
8658e76426SMichael Kruse   if (Attrs.UnrollEnable == LoopAttributes::Disable)
8758e76426SMichael Kruse     Enabled = false;
8858e76426SMichael Kruse   else if (Attrs.UnrollEnable == LoopAttributes::Full)
8958e76426SMichael Kruse     Enabled = None;
9058e76426SMichael Kruse   else if (Attrs.UnrollEnable != LoopAttributes::Unspecified ||
9158e76426SMichael Kruse            Attrs.UnrollCount != 0)
9258e76426SMichael Kruse     Enabled = true;
9358e76426SMichael Kruse 
9458e76426SMichael Kruse   if (Enabled != true) {
9558e76426SMichael Kruse     // createFullUnrollMetadata will already have added llvm.loop.unroll.disable
9658e76426SMichael Kruse     // if unrolling is disabled.
9758e76426SMichael Kruse     return createPipeliningMetadata(Attrs, LoopProperties, HasUserTransforms);
9858e76426SMichael Kruse   }
9958e76426SMichael Kruse 
10058e76426SMichael Kruse   SmallVector<Metadata *, 4> FollowupLoopProperties;
10158e76426SMichael Kruse 
10258e76426SMichael Kruse   // Apply all loop properties to the unrolled loop.
10358e76426SMichael Kruse   FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
10458e76426SMichael Kruse 
10558e76426SMichael Kruse   // Don't unroll an already unrolled loop.
10658e76426SMichael Kruse   FollowupLoopProperties.push_back(
10758e76426SMichael Kruse       MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
10858e76426SMichael Kruse 
10958e76426SMichael Kruse   bool FollowupHasTransforms = false;
11058e76426SMichael Kruse   MDNode *Followup = createPipeliningMetadata(Attrs, FollowupLoopProperties,
11158e76426SMichael Kruse                                               FollowupHasTransforms);
11258e76426SMichael Kruse 
11358e76426SMichael Kruse   SmallVector<Metadata *, 4> Args;
114d4c667c9SDuncan P. N. Exon Smith   Args.push_back(nullptr);
11558e76426SMichael Kruse   Args.append(LoopProperties.begin(), LoopProperties.end());
11658e76426SMichael Kruse 
11758e76426SMichael Kruse   // Setting unroll.count
11858e76426SMichael Kruse   if (Attrs.UnrollCount > 0) {
11958e76426SMichael Kruse     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
12058e76426SMichael Kruse                         ConstantAsMetadata::get(ConstantInt::get(
12158e76426SMichael Kruse                             llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
12258e76426SMichael Kruse     Args.push_back(MDNode::get(Ctx, Vals));
12358e76426SMichael Kruse   }
12458e76426SMichael Kruse 
12558e76426SMichael Kruse   // Setting unroll.full or unroll.disable
12658e76426SMichael Kruse   if (Attrs.UnrollEnable == LoopAttributes::Enable) {
12758e76426SMichael Kruse     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")};
12858e76426SMichael Kruse     Args.push_back(MDNode::get(Ctx, Vals));
12958e76426SMichael Kruse   }
13058e76426SMichael Kruse 
13158e76426SMichael Kruse   if (FollowupHasTransforms)
13258e76426SMichael Kruse     Args.push_back(MDNode::get(
13358e76426SMichael Kruse         Ctx, {MDString::get(Ctx, "llvm.loop.unroll.followup_all"), Followup}));
13458e76426SMichael Kruse 
13558e76426SMichael Kruse   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
13658e76426SMichael Kruse   LoopID->replaceOperandWith(0, LoopID);
13758e76426SMichael Kruse   HasUserTransforms = true;
13858e76426SMichael Kruse   return LoopID;
13958e76426SMichael Kruse }
14058e76426SMichael Kruse 
14158e76426SMichael Kruse MDNode *
createUnrollAndJamMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)14258e76426SMichael Kruse LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs,
14358e76426SMichael Kruse                                      ArrayRef<Metadata *> LoopProperties,
14458e76426SMichael Kruse                                      bool &HasUserTransforms) {
14558e76426SMichael Kruse   LLVMContext &Ctx = Header->getContext();
14658e76426SMichael Kruse 
14758e76426SMichael Kruse   Optional<bool> Enabled;
14858e76426SMichael Kruse   if (Attrs.UnrollAndJamEnable == LoopAttributes::Disable)
14958e76426SMichael Kruse     Enabled = false;
15058e76426SMichael Kruse   else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable ||
15158e76426SMichael Kruse            Attrs.UnrollAndJamCount != 0)
15258e76426SMichael Kruse     Enabled = true;
15358e76426SMichael Kruse 
15458e76426SMichael Kruse   if (Enabled != true) {
15558e76426SMichael Kruse     SmallVector<Metadata *, 4> NewLoopProperties;
15658e76426SMichael Kruse     if (Enabled == false) {
15758e76426SMichael Kruse       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
15858e76426SMichael Kruse       NewLoopProperties.push_back(MDNode::get(
15958e76426SMichael Kruse           Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
16058e76426SMichael Kruse       LoopProperties = NewLoopProperties;
16158e76426SMichael Kruse     }
16258e76426SMichael Kruse     return createPartialUnrollMetadata(Attrs, LoopProperties,
16358e76426SMichael Kruse                                        HasUserTransforms);
16458e76426SMichael Kruse   }
16558e76426SMichael Kruse 
16658e76426SMichael Kruse   SmallVector<Metadata *, 4> FollowupLoopProperties;
16758e76426SMichael Kruse   FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
16858e76426SMichael Kruse   FollowupLoopProperties.push_back(
16958e76426SMichael Kruse       MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
17058e76426SMichael Kruse 
17158e76426SMichael Kruse   bool FollowupHasTransforms = false;
17258e76426SMichael Kruse   MDNode *Followup = createPartialUnrollMetadata(Attrs, FollowupLoopProperties,
17358e76426SMichael Kruse                                                  FollowupHasTransforms);
17458e76426SMichael Kruse 
17558e76426SMichael Kruse   SmallVector<Metadata *, 4> Args;
176d4c667c9SDuncan P. N. Exon Smith   Args.push_back(nullptr);
17758e76426SMichael Kruse   Args.append(LoopProperties.begin(), LoopProperties.end());
17858e76426SMichael Kruse 
17958e76426SMichael Kruse   // Setting unroll_and_jam.count
18058e76426SMichael Kruse   if (Attrs.UnrollAndJamCount > 0) {
18158e76426SMichael Kruse     Metadata *Vals[] = {
18258e76426SMichael Kruse         MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
18358e76426SMichael Kruse         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
18458e76426SMichael Kruse                                                  Attrs.UnrollAndJamCount))};
18558e76426SMichael Kruse     Args.push_back(MDNode::get(Ctx, Vals));
18658e76426SMichael Kruse   }
18758e76426SMichael Kruse 
18858e76426SMichael Kruse   if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) {
18958e76426SMichael Kruse     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")};
19058e76426SMichael Kruse     Args.push_back(MDNode::get(Ctx, Vals));
19158e76426SMichael Kruse   }
19258e76426SMichael Kruse 
19358e76426SMichael Kruse   if (FollowupHasTransforms)
19458e76426SMichael Kruse     Args.push_back(MDNode::get(
19558e76426SMichael Kruse         Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_outer"),
19658e76426SMichael Kruse               Followup}));
19758e76426SMichael Kruse 
19858e76426SMichael Kruse   if (UnrollAndJamInnerFollowup)
19958e76426SMichael Kruse     Args.push_back(MDNode::get(
20058e76426SMichael Kruse         Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_inner"),
20158e76426SMichael Kruse               UnrollAndJamInnerFollowup}));
20258e76426SMichael Kruse 
20358e76426SMichael Kruse   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
20458e76426SMichael Kruse   LoopID->replaceOperandWith(0, LoopID);
20558e76426SMichael Kruse   HasUserTransforms = true;
20658e76426SMichael Kruse   return LoopID;
20758e76426SMichael Kruse }
20858e76426SMichael Kruse 
20958e76426SMichael Kruse MDNode *
createLoopVectorizeMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)21058e76426SMichael Kruse LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs,
21158e76426SMichael Kruse                                       ArrayRef<Metadata *> LoopProperties,
21258e76426SMichael Kruse                                       bool &HasUserTransforms) {
21358e76426SMichael Kruse   LLVMContext &Ctx = Header->getContext();
21458e76426SMichael Kruse 
21558e76426SMichael Kruse   Optional<bool> Enabled;
21658e76426SMichael Kruse   if (Attrs.VectorizeEnable == LoopAttributes::Disable)
21758e76426SMichael Kruse     Enabled = false;
21858e76426SMichael Kruse   else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
219a48f58c9SSjoerd Meijer            Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified ||
22038d18d93SDavid Sherwood            Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0 ||
22138d18d93SDavid Sherwood            Attrs.VectorizeScalable != LoopAttributes::Unspecified)
22258e76426SMichael Kruse     Enabled = true;
22358e76426SMichael Kruse 
22458e76426SMichael Kruse   if (Enabled != true) {
22558e76426SMichael Kruse     SmallVector<Metadata *, 4> NewLoopProperties;
22658e76426SMichael Kruse     if (Enabled == false) {
22758e76426SMichael Kruse       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
22858e76426SMichael Kruse       NewLoopProperties.push_back(
22958e76426SMichael Kruse           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
23058e76426SMichael Kruse                             ConstantAsMetadata::get(ConstantInt::get(
23158e76426SMichael Kruse                                 llvm::Type::getInt1Ty(Ctx), 0))}));
23258e76426SMichael Kruse       LoopProperties = NewLoopProperties;
23358e76426SMichael Kruse     }
23458e76426SMichael Kruse     return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms);
23558e76426SMichael Kruse   }
23658e76426SMichael Kruse 
23758e76426SMichael Kruse   // Apply all loop properties to the vectorized loop.
23858e76426SMichael Kruse   SmallVector<Metadata *, 4> FollowupLoopProperties;
23958e76426SMichael Kruse   FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
24058e76426SMichael Kruse 
24158e76426SMichael Kruse   // Don't vectorize an already vectorized loop.
24258e76426SMichael Kruse   FollowupLoopProperties.push_back(
24358e76426SMichael Kruse       MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
24458e76426SMichael Kruse 
24558e76426SMichael Kruse   bool FollowupHasTransforms = false;
24658e76426SMichael Kruse   MDNode *Followup = createUnrollAndJamMetadata(Attrs, FollowupLoopProperties,
24758e76426SMichael Kruse                                                 FollowupHasTransforms);
24858e76426SMichael Kruse 
24958e76426SMichael Kruse   SmallVector<Metadata *, 4> Args;
250d4c667c9SDuncan P. N. Exon Smith   Args.push_back(nullptr);
25158e76426SMichael Kruse   Args.append(LoopProperties.begin(), LoopProperties.end());
25258e76426SMichael Kruse 
253*74ddacd3SMalhar   // Setting vectorize.predicate when it has been specified and vectorization
254*74ddacd3SMalhar   // has not been disabled.
255535efab2SSjoerd Meijer   bool IsVectorPredicateEnabled = false;
256*74ddacd3SMalhar   if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified) {
257535efab2SSjoerd Meijer     IsVectorPredicateEnabled =
258535efab2SSjoerd Meijer         (Attrs.VectorizePredicateEnable == LoopAttributes::Enable);
259535efab2SSjoerd Meijer 
260a48f58c9SSjoerd Meijer     Metadata *Vals[] = {
261a48f58c9SSjoerd Meijer         MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"),
262535efab2SSjoerd Meijer         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx),
263535efab2SSjoerd Meijer                                                  IsVectorPredicateEnabled))};
264a48f58c9SSjoerd Meijer     Args.push_back(MDNode::get(Ctx, Vals));
265a48f58c9SSjoerd Meijer   }
266a48f58c9SSjoerd Meijer 
26758e76426SMichael Kruse   // Setting vectorize.width
26858e76426SMichael Kruse   if (Attrs.VectorizeWidth > 0) {
26958e76426SMichael Kruse     Metadata *Vals[] = {
27058e76426SMichael Kruse         MDString::get(Ctx, "llvm.loop.vectorize.width"),
27158e76426SMichael Kruse         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
27258e76426SMichael Kruse                                                  Attrs.VectorizeWidth))};
27338d18d93SDavid Sherwood 
27438d18d93SDavid Sherwood     Args.push_back(MDNode::get(Ctx, Vals));
27538d18d93SDavid Sherwood   }
27638d18d93SDavid Sherwood 
27738d18d93SDavid Sherwood   if (Attrs.VectorizeScalable != LoopAttributes::Unspecified) {
27838d18d93SDavid Sherwood     bool IsScalable = Attrs.VectorizeScalable == LoopAttributes::Enable;
27938d18d93SDavid Sherwood     Metadata *Vals[] = {
28038d18d93SDavid Sherwood         MDString::get(Ctx, "llvm.loop.vectorize.scalable.enable"),
28138d18d93SDavid Sherwood         ConstantAsMetadata::get(
28238d18d93SDavid Sherwood             ConstantInt::get(llvm::Type::getInt1Ty(Ctx), IsScalable))};
28358e76426SMichael Kruse     Args.push_back(MDNode::get(Ctx, Vals));
28458e76426SMichael Kruse   }
28558e76426SMichael Kruse 
28658e76426SMichael Kruse   // Setting interleave.count
28758e76426SMichael Kruse   if (Attrs.InterleaveCount > 0) {
28858e76426SMichael Kruse     Metadata *Vals[] = {
28958e76426SMichael Kruse         MDString::get(Ctx, "llvm.loop.interleave.count"),
29058e76426SMichael Kruse         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
29158e76426SMichael Kruse                                                  Attrs.InterleaveCount))};
29258e76426SMichael Kruse     Args.push_back(MDNode::get(Ctx, Vals));
29358e76426SMichael Kruse   }
29458e76426SMichael Kruse 
29502168549SSjoerd Meijer   // vectorize.enable is set if:
29602168549SSjoerd Meijer   // 1) loop hint vectorize.enable is set, or
29702168549SSjoerd Meijer   // 2) it is implied when vectorize.predicate is set, or
29838d18d93SDavid Sherwood   // 3) it is implied when vectorize.width is set to a value > 1
29938d18d93SDavid Sherwood   // 4) it is implied when vectorize.scalable.enable is true
30038d18d93SDavid Sherwood   // 5) it is implied when vectorize.width is unset (0) and the user
30138d18d93SDavid Sherwood   //    explicitly requested fixed-width vectorization, i.e.
30238d18d93SDavid Sherwood   //    vectorize.scalable.enable is false.
303535efab2SSjoerd Meijer   if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
304*74ddacd3SMalhar       (IsVectorPredicateEnabled && Attrs.VectorizeWidth != 1) ||
305*74ddacd3SMalhar       Attrs.VectorizeWidth > 1 ||
30638d18d93SDavid Sherwood       Attrs.VectorizeScalable == LoopAttributes::Enable ||
30738d18d93SDavid Sherwood       (Attrs.VectorizeScalable == LoopAttributes::Disable &&
30838d18d93SDavid Sherwood        Attrs.VectorizeWidth != 1)) {
30902168549SSjoerd Meijer     bool AttrVal = Attrs.VectorizeEnable != LoopAttributes::Disable;
31002168549SSjoerd Meijer     Args.push_back(
31102168549SSjoerd Meijer         MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
31258e76426SMichael Kruse                           ConstantAsMetadata::get(ConstantInt::get(
31302168549SSjoerd Meijer                               llvm::Type::getInt1Ty(Ctx), AttrVal))}));
31458e76426SMichael Kruse   }
31558e76426SMichael Kruse 
31658e76426SMichael Kruse   if (FollowupHasTransforms)
31758e76426SMichael Kruse     Args.push_back(MDNode::get(
31858e76426SMichael Kruse         Ctx,
31958e76426SMichael Kruse         {MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup}));
32058e76426SMichael Kruse 
321d4c667c9SDuncan P. N. Exon Smith   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
322515ad8c4SAlexander Musman   LoopID->replaceOperandWith(0, LoopID);
32358e76426SMichael Kruse   HasUserTransforms = true;
324515ad8c4SAlexander Musman   return LoopID;
325515ad8c4SAlexander Musman }
326515ad8c4SAlexander Musman 
32758e76426SMichael Kruse MDNode *
createLoopDistributeMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)32858e76426SMichael Kruse LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs,
32958e76426SMichael Kruse                                        ArrayRef<Metadata *> LoopProperties,
33058e76426SMichael Kruse                                        bool &HasUserTransforms) {
33158e76426SMichael Kruse   LLVMContext &Ctx = Header->getContext();
33258e76426SMichael Kruse 
33358e76426SMichael Kruse   Optional<bool> Enabled;
33458e76426SMichael Kruse   if (Attrs.DistributeEnable == LoopAttributes::Disable)
33558e76426SMichael Kruse     Enabled = false;
33658e76426SMichael Kruse   if (Attrs.DistributeEnable == LoopAttributes::Enable)
33758e76426SMichael Kruse     Enabled = true;
33858e76426SMichael Kruse 
33958e76426SMichael Kruse   if (Enabled != true) {
34058e76426SMichael Kruse     SmallVector<Metadata *, 4> NewLoopProperties;
34158e76426SMichael Kruse     if (Enabled == false) {
34258e76426SMichael Kruse       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
34358e76426SMichael Kruse       NewLoopProperties.push_back(
34458e76426SMichael Kruse           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),
34558e76426SMichael Kruse                             ConstantAsMetadata::get(ConstantInt::get(
34658e76426SMichael Kruse                                 llvm::Type::getInt1Ty(Ctx), 0))}));
34758e76426SMichael Kruse       LoopProperties = NewLoopProperties;
34858e76426SMichael Kruse     }
34958e76426SMichael Kruse     return createLoopVectorizeMetadata(Attrs, LoopProperties,
35058e76426SMichael Kruse                                        HasUserTransforms);
35158e76426SMichael Kruse   }
35258e76426SMichael Kruse 
35358e76426SMichael Kruse   bool FollowupHasTransforms = false;
35458e76426SMichael Kruse   MDNode *Followup =
35558e76426SMichael Kruse       createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);
35658e76426SMichael Kruse 
35758e76426SMichael Kruse   SmallVector<Metadata *, 4> Args;
358d4c667c9SDuncan P. N. Exon Smith   Args.push_back(nullptr);
35958e76426SMichael Kruse   Args.append(LoopProperties.begin(), LoopProperties.end());
36058e76426SMichael Kruse 
36158e76426SMichael Kruse   Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
36258e76426SMichael Kruse                       ConstantAsMetadata::get(ConstantInt::get(
36358e76426SMichael Kruse                           llvm::Type::getInt1Ty(Ctx),
36458e76426SMichael Kruse                           (Attrs.DistributeEnable == LoopAttributes::Enable)))};
36558e76426SMichael Kruse   Args.push_back(MDNode::get(Ctx, Vals));
36658e76426SMichael Kruse 
36758e76426SMichael Kruse   if (FollowupHasTransforms)
36858e76426SMichael Kruse     Args.push_back(MDNode::get(
36958e76426SMichael Kruse         Ctx,
37058e76426SMichael Kruse         {MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup}));
37158e76426SMichael Kruse 
372d4c667c9SDuncan P. N. Exon Smith   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
37358e76426SMichael Kruse   LoopID->replaceOperandWith(0, LoopID);
37458e76426SMichael Kruse   HasUserTransforms = true;
37558e76426SMichael Kruse   return LoopID;
37658e76426SMichael Kruse }
37758e76426SMichael Kruse 
createFullUnrollMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)37858e76426SMichael Kruse MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,
37958e76426SMichael Kruse                                            ArrayRef<Metadata *> LoopProperties,
38058e76426SMichael Kruse                                            bool &HasUserTransforms) {
38158e76426SMichael Kruse   LLVMContext &Ctx = Header->getContext();
38258e76426SMichael Kruse 
38358e76426SMichael Kruse   Optional<bool> Enabled;
38458e76426SMichael Kruse   if (Attrs.UnrollEnable == LoopAttributes::Disable)
38558e76426SMichael Kruse     Enabled = false;
38658e76426SMichael Kruse   else if (Attrs.UnrollEnable == LoopAttributes::Full)
38758e76426SMichael Kruse     Enabled = true;
38858e76426SMichael Kruse 
38958e76426SMichael Kruse   if (Enabled != true) {
39058e76426SMichael Kruse     SmallVector<Metadata *, 4> NewLoopProperties;
39158e76426SMichael Kruse     if (Enabled == false) {
39258e76426SMichael Kruse       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
39358e76426SMichael Kruse       NewLoopProperties.push_back(
39458e76426SMichael Kruse           MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
39558e76426SMichael Kruse       LoopProperties = NewLoopProperties;
39658e76426SMichael Kruse     }
39758e76426SMichael Kruse     return createLoopDistributeMetadata(Attrs, LoopProperties,
39858e76426SMichael Kruse                                         HasUserTransforms);
39958e76426SMichael Kruse   }
40058e76426SMichael Kruse 
40158e76426SMichael Kruse   SmallVector<Metadata *, 4> Args;
402d4c667c9SDuncan P. N. Exon Smith   Args.push_back(nullptr);
40358e76426SMichael Kruse   Args.append(LoopProperties.begin(), LoopProperties.end());
40458e76426SMichael Kruse   Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));
40558e76426SMichael Kruse 
40658e76426SMichael Kruse   // No follow-up: there is no loop after full unrolling.
40758e76426SMichael Kruse   // TODO: Warn if there are transformations after full unrolling.
40858e76426SMichael Kruse 
40958e76426SMichael Kruse   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
41058e76426SMichael Kruse   LoopID->replaceOperandWith(0, LoopID);
41158e76426SMichael Kruse   HasUserTransforms = true;
41258e76426SMichael Kruse   return LoopID;
41358e76426SMichael Kruse }
41458e76426SMichael Kruse 
createMetadata(const LoopAttributes & Attrs,llvm::ArrayRef<llvm::Metadata * > AdditionalLoopProperties,bool & HasUserTransforms)41558e76426SMichael Kruse MDNode *LoopInfo::createMetadata(
41658e76426SMichael Kruse     const LoopAttributes &Attrs,
41758e76426SMichael Kruse     llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,
41858e76426SMichael Kruse     bool &HasUserTransforms) {
41958e76426SMichael Kruse   SmallVector<Metadata *, 3> LoopProperties;
42058e76426SMichael Kruse 
42158e76426SMichael Kruse   // If we have a valid start debug location for the loop, add it.
42258e76426SMichael Kruse   if (StartLoc) {
42358e76426SMichael Kruse     LoopProperties.push_back(StartLoc.getAsMDNode());
42458e76426SMichael Kruse 
42558e76426SMichael Kruse     // If we also have a valid end debug location for the loop, add it.
42658e76426SMichael Kruse     if (EndLoc)
42758e76426SMichael Kruse       LoopProperties.push_back(EndLoc.getAsMDNode());
42858e76426SMichael Kruse   }
42958e76426SMichael Kruse 
430ac73b73cSAtmn Patel   LLVMContext &Ctx = Header->getContext();
431ac73b73cSAtmn Patel   if (Attrs.MustProgress)
432ac73b73cSAtmn Patel     LoopProperties.push_back(
433ac73b73cSAtmn Patel         MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.mustprogress")));
434ac73b73cSAtmn Patel 
43558e76426SMichael Kruse   assert(!!AccGroup == Attrs.IsParallel &&
43658e76426SMichael Kruse          "There must be an access group iff the loop is parallel");
43758e76426SMichael Kruse   if (Attrs.IsParallel) {
43858e76426SMichael Kruse     LoopProperties.push_back(MDNode::get(
43958e76426SMichael Kruse         Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
44058e76426SMichael Kruse   }
44158e76426SMichael Kruse 
44258e76426SMichael Kruse   LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
44358e76426SMichael Kruse                         AdditionalLoopProperties.end());
44458e76426SMichael Kruse   return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
44558e76426SMichael Kruse }
44658e76426SMichael Kruse 
LoopAttributes(bool IsParallel)447515ad8c4SAlexander Musman LoopAttributes::LoopAttributes(bool IsParallel)
448da46d0eaSTyler Nowicki     : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
449c8e3924bSDavid Green       UnrollEnable(LoopAttributes::Unspecified),
450a48f58c9SSjoerd Meijer       UnrollAndJamEnable(LoopAttributes::Unspecified),
451a48f58c9SSjoerd Meijer       VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
45238d18d93SDavid Sherwood       VectorizeScalable(LoopAttributes::Unspecified), InterleaveCount(0),
45338d18d93SDavid Sherwood       UnrollCount(0), UnrollAndJamCount(0),
4549bdf515cSAaron Ballman       DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
455ac73b73cSAtmn Patel       PipelineInitiationInterval(0), MustProgress(false) {}
456515ad8c4SAlexander Musman 
clear()457515ad8c4SAlexander Musman void LoopAttributes::clear() {
458515ad8c4SAlexander Musman   IsParallel = false;
459da46d0eaSTyler Nowicki   VectorizeWidth = 0;
46038d18d93SDavid Sherwood   VectorizeScalable = LoopAttributes::Unspecified;
461da46d0eaSTyler Nowicki   InterleaveCount = 0;
46254c020d3STyler Nowicki   UnrollCount = 0;
463c8e3924bSDavid Green   UnrollAndJamCount = 0;
464da46d0eaSTyler Nowicki   VectorizeEnable = LoopAttributes::Unspecified;
46554c020d3STyler Nowicki   UnrollEnable = LoopAttributes::Unspecified;
466c8e3924bSDavid Green   UnrollAndJamEnable = LoopAttributes::Unspecified;
467a48f58c9SSjoerd Meijer   VectorizePredicateEnable = LoopAttributes::Unspecified;
4689c848590SAdam Nemet   DistributeEnable = LoopAttributes::Unspecified;
4699bdf515cSAaron Ballman   PipelineDisabled = false;
4709bdf515cSAaron Ballman   PipelineInitiationInterval = 0;
471ac73b73cSAtmn Patel   MustProgress = false;
472515ad8c4SAlexander Musman }
473515ad8c4SAlexander Musman 
LoopInfo(BasicBlock * Header,const LoopAttributes & Attrs,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc,LoopInfo * Parent)474c07e19b2SHal Finkel LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
47558e76426SMichael Kruse                    const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
47658e76426SMichael Kruse                    LoopInfo *Parent)
47758e76426SMichael Kruse     : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
47858e76426SMichael Kruse       Parent(Parent) {
47958e76426SMichael Kruse 
48058e76426SMichael Kruse   if (Attrs.IsParallel) {
48158e76426SMichael Kruse     // Create an access group for this loop.
48258e76426SMichael Kruse     LLVMContext &Ctx = Header->getContext();
48358e76426SMichael Kruse     AccGroup = MDNode::getDistinct(Ctx, {});
48458e76426SMichael Kruse   }
48558e76426SMichael Kruse 
48658e76426SMichael Kruse   if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
48738d18d93SDavid Sherwood       Attrs.VectorizeScalable == LoopAttributes::Unspecified &&
48858e76426SMichael Kruse       Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
48958e76426SMichael Kruse       Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
49058e76426SMichael Kruse       Attrs.PipelineInitiationInterval == 0 &&
491a48f58c9SSjoerd Meijer       Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified &&
49258e76426SMichael Kruse       Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
49358e76426SMichael Kruse       Attrs.UnrollEnable == LoopAttributes::Unspecified &&
49458e76426SMichael Kruse       Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
49558e76426SMichael Kruse       Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
496ac73b73cSAtmn Patel       !EndLoc && !Attrs.MustProgress)
49758e76426SMichael Kruse     return;
49858e76426SMichael Kruse 
49958e76426SMichael Kruse   TempLoopID = MDNode::getTemporary(Header->getContext(), None);
50058e76426SMichael Kruse }
50158e76426SMichael Kruse 
finish()50258e76426SMichael Kruse void LoopInfo::finish() {
50358e76426SMichael Kruse   // We did not annotate the loop body instructions because there are no
50458e76426SMichael Kruse   // attributes for this loop.
50558e76426SMichael Kruse   if (!TempLoopID)
50658e76426SMichael Kruse     return;
50758e76426SMichael Kruse 
50858e76426SMichael Kruse   MDNode *LoopID;
50958e76426SMichael Kruse   LoopAttributes CurLoopAttr = Attrs;
51058e76426SMichael Kruse   LLVMContext &Ctx = Header->getContext();
51158e76426SMichael Kruse 
51258e76426SMichael Kruse   if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
51358e76426SMichael Kruse                  Parent->Attrs.UnrollAndJamCount != 0)) {
51458e76426SMichael Kruse     // Parent unroll-and-jams this loop.
51558e76426SMichael Kruse     // Split the transformations in those that happens before the unroll-and-jam
51658e76426SMichael Kruse     // and those after.
51758e76426SMichael Kruse 
51858e76426SMichael Kruse     LoopAttributes BeforeJam, AfterJam;
51958e76426SMichael Kruse 
52058e76426SMichael Kruse     BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
52158e76426SMichael Kruse 
52258e76426SMichael Kruse     BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
52338d18d93SDavid Sherwood     BeforeJam.VectorizeScalable = Attrs.VectorizeScalable;
52458e76426SMichael Kruse     BeforeJam.InterleaveCount = Attrs.InterleaveCount;
52558e76426SMichael Kruse     BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
52658e76426SMichael Kruse     BeforeJam.DistributeEnable = Attrs.DistributeEnable;
527a48f58c9SSjoerd Meijer     BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
52858e76426SMichael Kruse 
52958e76426SMichael Kruse     switch (Attrs.UnrollEnable) {
53058e76426SMichael Kruse     case LoopAttributes::Unspecified:
53158e76426SMichael Kruse     case LoopAttributes::Disable:
53258e76426SMichael Kruse       BeforeJam.UnrollEnable = Attrs.UnrollEnable;
53358e76426SMichael Kruse       AfterJam.UnrollEnable = Attrs.UnrollEnable;
53458e76426SMichael Kruse       break;
53558e76426SMichael Kruse     case LoopAttributes::Full:
53658e76426SMichael Kruse       BeforeJam.UnrollEnable = LoopAttributes::Full;
53758e76426SMichael Kruse       break;
53858e76426SMichael Kruse     case LoopAttributes::Enable:
53958e76426SMichael Kruse       AfterJam.UnrollEnable = LoopAttributes::Enable;
54058e76426SMichael Kruse       break;
54158e76426SMichael Kruse     }
54258e76426SMichael Kruse 
543a48f58c9SSjoerd Meijer     AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
54458e76426SMichael Kruse     AfterJam.UnrollCount = Attrs.UnrollCount;
54558e76426SMichael Kruse     AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
54658e76426SMichael Kruse     AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;
54758e76426SMichael Kruse 
54858e76426SMichael Kruse     // If this loop is subject of an unroll-and-jam by the parent loop, and has
54958e76426SMichael Kruse     // an unroll-and-jam annotation itself, we have to decide whether to first
55058e76426SMichael Kruse     // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
55158e76426SMichael Kruse     // UnrollAndJam pass processes loops from inner to outer, so we apply the
55258e76426SMichael Kruse     // inner first.
55358e76426SMichael Kruse     BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
55458e76426SMichael Kruse     BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
55558e76426SMichael Kruse 
55658e76426SMichael Kruse     // Set the inner followup metadata to process by the outer loop. Only
55758e76426SMichael Kruse     // consider the first inner loop.
55858e76426SMichael Kruse     if (!Parent->UnrollAndJamInnerFollowup) {
55958e76426SMichael Kruse       // Splitting the attributes into a BeforeJam and an AfterJam part will
56058e76426SMichael Kruse       // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
56158e76426SMichael Kruse       // to be forwarded to the AfterJam part. We detect the situation here and
56258e76426SMichael Kruse       // add it manually.
56358e76426SMichael Kruse       SmallVector<Metadata *, 1> BeforeLoopProperties;
56458e76426SMichael Kruse       if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||
565a48f58c9SSjoerd Meijer           BeforeJam.VectorizePredicateEnable != LoopAttributes::Unspecified ||
56638d18d93SDavid Sherwood           BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0 ||
56738d18d93SDavid Sherwood           BeforeJam.VectorizeScalable == LoopAttributes::Enable)
56858e76426SMichael Kruse         BeforeLoopProperties.push_back(
56958e76426SMichael Kruse             MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
57058e76426SMichael Kruse 
57158e76426SMichael Kruse       bool InnerFollowupHasTransform = false;
57258e76426SMichael Kruse       MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,
57358e76426SMichael Kruse                                              InnerFollowupHasTransform);
57458e76426SMichael Kruse       if (InnerFollowupHasTransform)
57558e76426SMichael Kruse         Parent->UnrollAndJamInnerFollowup = InnerFollowup;
57658e76426SMichael Kruse     }
57758e76426SMichael Kruse 
57858e76426SMichael Kruse     CurLoopAttr = BeforeJam;
57958e76426SMichael Kruse   }
58058e76426SMichael Kruse 
58158e76426SMichael Kruse   bool HasUserTransforms = false;
58258e76426SMichael Kruse   LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);
58358e76426SMichael Kruse   TempLoopID->replaceAllUsesWith(LoopID);
584515ad8c4SAlexander Musman }
585515ad8c4SAlexander Musman 
push(BasicBlock * Header,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc)58681cb4b71SBenjamin Kramer void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
58781cb4b71SBenjamin Kramer                          const llvm::DebugLoc &EndLoc) {
588b6ab533bSAaron Ballman   Active.emplace_back(
589b6ab533bSAaron Ballman       new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
590b6ab533bSAaron Ballman                    Active.empty() ? nullptr : Active.back().get()));
59154c020d3STyler Nowicki   // Clear the attributes so nested loops do not inherit them.
59254c020d3STyler Nowicki   StagedAttrs.clear();
59354c020d3STyler Nowicki }
59454c020d3STyler Nowicki 
push(BasicBlock * Header,clang::ASTContext & Ctx,const clang::CodeGenOptions & CGOpts,ArrayRef<const clang::Attr * > Attrs,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc,bool MustProgress)59554c020d3STyler Nowicki void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
596338be9c5SFlorian Hahn                          const clang::CodeGenOptions &CGOpts,
597c07e19b2SHal Finkel                          ArrayRef<const clang::Attr *> Attrs,
59881cb4b71SBenjamin Kramer                          const llvm::DebugLoc &StartLoc,
599ac73b73cSAtmn Patel                          const llvm::DebugLoc &EndLoc, bool MustProgress) {
60054c020d3STyler Nowicki   // Identify loop hint attributes from Attrs.
6019d268e17STyler Nowicki   for (const auto *Attr : Attrs) {
6029d268e17STyler Nowicki     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
6036bdbcbb3SAnastasia Stulova     const OpenCLUnrollHintAttr *OpenCLHint =
6046bdbcbb3SAnastasia Stulova         dyn_cast<OpenCLUnrollHintAttr>(Attr);
6059d268e17STyler Nowicki 
6069d268e17STyler Nowicki     // Skip non loop hint attributes
6076bdbcbb3SAnastasia Stulova     if (!LH && !OpenCLHint) {
6089d268e17STyler Nowicki       continue;
6096bdbcbb3SAnastasia Stulova     }
6109d268e17STyler Nowicki 
6116bdbcbb3SAnastasia Stulova     LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
6126bdbcbb3SAnastasia Stulova     LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
61354c020d3STyler Nowicki     unsigned ValueInt = 1;
6146bdbcbb3SAnastasia Stulova     // Translate opencl_unroll_hint attribute argument to
6156bdbcbb3SAnastasia Stulova     // equivalent LoopHintAttr enums.
6166bdbcbb3SAnastasia Stulova     // OpenCL v2.0 s6.11.5:
61776b178d9SAndrew Savonichev     // 0 - enable unroll (no argument).
6186bdbcbb3SAnastasia Stulova     // 1 - disable unroll.
6196bdbcbb3SAnastasia Stulova     // other positive integer n - unroll by n.
6206bdbcbb3SAnastasia Stulova     if (OpenCLHint) {
6216bdbcbb3SAnastasia Stulova       ValueInt = OpenCLHint->getUnrollHint();
6226bdbcbb3SAnastasia Stulova       if (ValueInt == 0) {
62376b178d9SAndrew Savonichev         State = LoopHintAttr::Enable;
6246bdbcbb3SAnastasia Stulova       } else if (ValueInt != 1) {
6256bdbcbb3SAnastasia Stulova         Option = LoopHintAttr::UnrollCount;
6266bdbcbb3SAnastasia Stulova         State = LoopHintAttr::Numeric;
6276bdbcbb3SAnastasia Stulova       }
6286bdbcbb3SAnastasia Stulova     } else if (LH) {
6296bdbcbb3SAnastasia Stulova       auto *ValueExpr = LH->getValue();
63054c020d3STyler Nowicki       if (ValueExpr) {
63154c020d3STyler Nowicki         llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
63254c020d3STyler Nowicki         ValueInt = ValueAPS.getSExtValue();
63354c020d3STyler Nowicki       }
63454c020d3STyler Nowicki 
6356bdbcbb3SAnastasia Stulova       Option = LH->getOption();
6366bdbcbb3SAnastasia Stulova       State = LH->getState();
6376bdbcbb3SAnastasia Stulova     }
63854c020d3STyler Nowicki     switch (State) {
63954c020d3STyler Nowicki     case LoopHintAttr::Disable:
64054c020d3STyler Nowicki       switch (Option) {
64154c020d3STyler Nowicki       case LoopHintAttr::Vectorize:
64254c020d3STyler Nowicki         // Disable vectorization by specifying a width of 1.
64354c020d3STyler Nowicki         setVectorizeWidth(1);
64438d18d93SDavid Sherwood         setVectorizeScalable(LoopAttributes::Unspecified);
64554c020d3STyler Nowicki         break;
64654c020d3STyler Nowicki       case LoopHintAttr::Interleave:
64754c020d3STyler Nowicki         // Disable interleaving by speciyfing a count of 1.
64854c020d3STyler Nowicki         setInterleaveCount(1);
64954c020d3STyler Nowicki         break;
65054c020d3STyler Nowicki       case LoopHintAttr::Unroll:
651397a98d8SMark Heffernan         setUnrollState(LoopAttributes::Disable);
65254c020d3STyler Nowicki         break;
653c8e3924bSDavid Green       case LoopHintAttr::UnrollAndJam:
654c8e3924bSDavid Green         setUnrollAndJamState(LoopAttributes::Disable);
655c8e3924bSDavid Green         break;
656a48f58c9SSjoerd Meijer       case LoopHintAttr::VectorizePredicate:
657a48f58c9SSjoerd Meijer         setVectorizePredicateState(LoopAttributes::Disable);
658a48f58c9SSjoerd Meijer         break;
6592de463ecSAdam Nemet       case LoopHintAttr::Distribute:
6602de463ecSAdam Nemet         setDistributeState(false);
6612de463ecSAdam Nemet         break;
6629bdf515cSAaron Ballman       case LoopHintAttr::PipelineDisabled:
6639bdf515cSAaron Ballman         setPipelineDisabled(true);
6649bdf515cSAaron Ballman         break;
66554c020d3STyler Nowicki       case LoopHintAttr::UnrollCount:
666c8e3924bSDavid Green       case LoopHintAttr::UnrollAndJamCount:
66754c020d3STyler Nowicki       case LoopHintAttr::VectorizeWidth:
66854c020d3STyler Nowicki       case LoopHintAttr::InterleaveCount:
6699bdf515cSAaron Ballman       case LoopHintAttr::PipelineInitiationInterval:
67054c020d3STyler Nowicki         llvm_unreachable("Options cannot be disabled.");
67154c020d3STyler Nowicki         break;
67254c020d3STyler Nowicki       }
67354c020d3STyler Nowicki       break;
67454c020d3STyler Nowicki     case LoopHintAttr::Enable:
6759d268e17STyler Nowicki       switch (Option) {
6769d268e17STyler Nowicki       case LoopHintAttr::Vectorize:
6779d268e17STyler Nowicki       case LoopHintAttr::Interleave:
67854c020d3STyler Nowicki         setVectorizeEnable(true);
6799d268e17STyler Nowicki         break;
68054c020d3STyler Nowicki       case LoopHintAttr::Unroll:
681397a98d8SMark Heffernan         setUnrollState(LoopAttributes::Enable);
68254c020d3STyler Nowicki         break;
683c8e3924bSDavid Green       case LoopHintAttr::UnrollAndJam:
684c8e3924bSDavid Green         setUnrollAndJamState(LoopAttributes::Enable);
685c8e3924bSDavid Green         break;
686a48f58c9SSjoerd Meijer       case LoopHintAttr::VectorizePredicate:
687a48f58c9SSjoerd Meijer         setVectorizePredicateState(LoopAttributes::Enable);
688a48f58c9SSjoerd Meijer         break;
6892de463ecSAdam Nemet       case LoopHintAttr::Distribute:
6902de463ecSAdam Nemet         setDistributeState(true);
6912de463ecSAdam Nemet         break;
69254c020d3STyler Nowicki       case LoopHintAttr::UnrollCount:
693c8e3924bSDavid Green       case LoopHintAttr::UnrollAndJamCount:
6949d268e17STyler Nowicki       case LoopHintAttr::VectorizeWidth:
6959d268e17STyler Nowicki       case LoopHintAttr::InterleaveCount:
6969bdf515cSAaron Ballman       case LoopHintAttr::PipelineDisabled:
6979bdf515cSAaron Ballman       case LoopHintAttr::PipelineInitiationInterval:
69854c020d3STyler Nowicki         llvm_unreachable("Options cannot enabled.");
69954c020d3STyler Nowicki         break;
70054c020d3STyler Nowicki       }
70154c020d3STyler Nowicki       break;
70254c020d3STyler Nowicki     case LoopHintAttr::AssumeSafety:
70354c020d3STyler Nowicki       switch (Option) {
70454c020d3STyler Nowicki       case LoopHintAttr::Vectorize:
70554c020d3STyler Nowicki       case LoopHintAttr::Interleave:
70654c020d3STyler Nowicki         // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
70754c020d3STyler Nowicki         setParallel(true);
70854c020d3STyler Nowicki         setVectorizeEnable(true);
70954c020d3STyler Nowicki         break;
7109d268e17STyler Nowicki       case LoopHintAttr::Unroll:
711c8e3924bSDavid Green       case LoopHintAttr::UnrollAndJam:
712a48f58c9SSjoerd Meijer       case LoopHintAttr::VectorizePredicate:
7139d268e17STyler Nowicki       case LoopHintAttr::UnrollCount:
714c8e3924bSDavid Green       case LoopHintAttr::UnrollAndJamCount:
71554c020d3STyler Nowicki       case LoopHintAttr::VectorizeWidth:
71654c020d3STyler Nowicki       case LoopHintAttr::InterleaveCount:
7172de463ecSAdam Nemet       case LoopHintAttr::Distribute:
7189bdf515cSAaron Ballman       case LoopHintAttr::PipelineDisabled:
7199bdf515cSAaron Ballman       case LoopHintAttr::PipelineInitiationInterval:
72054c020d3STyler Nowicki         llvm_unreachable("Options cannot be used to assume mem safety.");
72154c020d3STyler Nowicki         break;
72254c020d3STyler Nowicki       }
72354c020d3STyler Nowicki       break;
724397a98d8SMark Heffernan     case LoopHintAttr::Full:
725397a98d8SMark Heffernan       switch (Option) {
726397a98d8SMark Heffernan       case LoopHintAttr::Unroll:
727397a98d8SMark Heffernan         setUnrollState(LoopAttributes::Full);
728397a98d8SMark Heffernan         break;
729c8e3924bSDavid Green       case LoopHintAttr::UnrollAndJam:
730c8e3924bSDavid Green         setUnrollAndJamState(LoopAttributes::Full);
731c8e3924bSDavid Green         break;
732397a98d8SMark Heffernan       case LoopHintAttr::Vectorize:
733397a98d8SMark Heffernan       case LoopHintAttr::Interleave:
734397a98d8SMark Heffernan       case LoopHintAttr::UnrollCount:
735c8e3924bSDavid Green       case LoopHintAttr::UnrollAndJamCount:
736397a98d8SMark Heffernan       case LoopHintAttr::VectorizeWidth:
737397a98d8SMark Heffernan       case LoopHintAttr::InterleaveCount:
7382de463ecSAdam Nemet       case LoopHintAttr::Distribute:
7399bdf515cSAaron Ballman       case LoopHintAttr::PipelineDisabled:
7409bdf515cSAaron Ballman       case LoopHintAttr::PipelineInitiationInterval:
741a48f58c9SSjoerd Meijer       case LoopHintAttr::VectorizePredicate:
742397a98d8SMark Heffernan         llvm_unreachable("Options cannot be used with 'full' hint.");
743397a98d8SMark Heffernan         break;
744397a98d8SMark Heffernan       }
745397a98d8SMark Heffernan       break;
74638d18d93SDavid Sherwood     case LoopHintAttr::FixedWidth:
74738d18d93SDavid Sherwood     case LoopHintAttr::ScalableWidth:
74854c020d3STyler Nowicki       switch (Option) {
74954c020d3STyler Nowicki       case LoopHintAttr::VectorizeWidth:
75038d18d93SDavid Sherwood         setVectorizeScalable(State == LoopHintAttr::ScalableWidth
75138d18d93SDavid Sherwood                                  ? LoopAttributes::Enable
75238d18d93SDavid Sherwood                                  : LoopAttributes::Disable);
75338d18d93SDavid Sherwood         if (LH->getValue())
75454c020d3STyler Nowicki           setVectorizeWidth(ValueInt);
75554c020d3STyler Nowicki         break;
75638d18d93SDavid Sherwood       default:
75738d18d93SDavid Sherwood         llvm_unreachable("Options cannot be used with 'scalable' hint.");
75838d18d93SDavid Sherwood         break;
75938d18d93SDavid Sherwood       }
76038d18d93SDavid Sherwood       break;
76138d18d93SDavid Sherwood     case LoopHintAttr::Numeric:
76238d18d93SDavid Sherwood       switch (Option) {
76354c020d3STyler Nowicki       case LoopHintAttr::InterleaveCount:
76454c020d3STyler Nowicki         setInterleaveCount(ValueInt);
76554c020d3STyler Nowicki         break;
76654c020d3STyler Nowicki       case LoopHintAttr::UnrollCount:
76754c020d3STyler Nowicki         setUnrollCount(ValueInt);
76854c020d3STyler Nowicki         break;
769c8e3924bSDavid Green       case LoopHintAttr::UnrollAndJamCount:
770c8e3924bSDavid Green         setUnrollAndJamCount(ValueInt);
771c8e3924bSDavid Green         break;
7729bdf515cSAaron Ballman       case LoopHintAttr::PipelineInitiationInterval:
7739bdf515cSAaron Ballman         setPipelineInitiationInterval(ValueInt);
7749bdf515cSAaron Ballman         break;
77554c020d3STyler Nowicki       case LoopHintAttr::Unroll:
776c8e3924bSDavid Green       case LoopHintAttr::UnrollAndJam:
777a48f58c9SSjoerd Meijer       case LoopHintAttr::VectorizePredicate:
77854c020d3STyler Nowicki       case LoopHintAttr::Vectorize:
77938d18d93SDavid Sherwood       case LoopHintAttr::VectorizeWidth:
78054c020d3STyler Nowicki       case LoopHintAttr::Interleave:
7812de463ecSAdam Nemet       case LoopHintAttr::Distribute:
7829bdf515cSAaron Ballman       case LoopHintAttr::PipelineDisabled:
783397a98d8SMark Heffernan         llvm_unreachable("Options cannot be assigned a value.");
78454c020d3STyler Nowicki         break;
78554c020d3STyler Nowicki       }
7869d268e17STyler Nowicki       break;
7879d268e17STyler Nowicki     }
7889d268e17STyler Nowicki   }
7899d268e17STyler Nowicki 
790ac73b73cSAtmn Patel   setMustProgress(MustProgress);
791ac73b73cSAtmn Patel 
792338be9c5SFlorian Hahn   if (CGOpts.OptimizationLevel > 0)
793338be9c5SFlorian Hahn     // Disable unrolling for the loop, if unrolling is disabled (via
794338be9c5SFlorian Hahn     // -fno-unroll-loops) and no pragmas override the decision.
795338be9c5SFlorian Hahn     if (!CGOpts.UnrollLoops &&
796338be9c5SFlorian Hahn         (StagedAttrs.UnrollEnable == LoopAttributes::Unspecified &&
797338be9c5SFlorian Hahn          StagedAttrs.UnrollCount == 0))
798338be9c5SFlorian Hahn       setUnrollState(LoopAttributes::Disable);
799338be9c5SFlorian Hahn 
80054c020d3STyler Nowicki   /// Stage the attributes.
801652795dbSAmara Emerson   push(Header, StartLoc, EndLoc);
802515ad8c4SAlexander Musman }
803515ad8c4SAlexander Musman 
pop()804515ad8c4SAlexander Musman void LoopInfoStack::pop() {
805515ad8c4SAlexander Musman   assert(!Active.empty() && "No active loops to pop");
806b6ab533bSAaron Ballman   Active.back()->finish();
807515ad8c4SAlexander Musman   Active.pop_back();
808515ad8c4SAlexander Musman }
809515ad8c4SAlexander Musman 
InsertHelper(Instruction * I) const810515ad8c4SAlexander Musman void LoopInfoStack::InsertHelper(Instruction *I) const {
8110535137eSMichael Kruse   if (I->mayReadOrWriteMemory()) {
8120535137eSMichael Kruse     SmallVector<Metadata *, 4> AccessGroups;
813b6ab533bSAaron Ballman     for (const auto &AL : Active) {
8140535137eSMichael Kruse       // Here we assume that every loop that has an access group is parallel.
815b6ab533bSAaron Ballman       if (MDNode *Group = AL->getAccessGroup())
8160535137eSMichael Kruse         AccessGroups.push_back(Group);
8170535137eSMichael Kruse     }
8180535137eSMichael Kruse     MDNode *UnionMD = nullptr;
8190535137eSMichael Kruse     if (AccessGroups.size() == 1)
8200535137eSMichael Kruse       UnionMD = cast<MDNode>(AccessGroups[0]);
8210535137eSMichael Kruse     else if (AccessGroups.size() >= 2)
8220535137eSMichael Kruse       UnionMD = MDNode::get(I->getContext(), AccessGroups);
8230535137eSMichael Kruse     I->setMetadata("llvm.access.group", UnionMD);
8240535137eSMichael Kruse   }
8250535137eSMichael Kruse 
826515ad8c4SAlexander Musman   if (!hasInfo())
827515ad8c4SAlexander Musman     return;
828515ad8c4SAlexander Musman 
829515ad8c4SAlexander Musman   const LoopInfo &L = getInfo();
830515ad8c4SAlexander Musman   if (!L.getLoopID())
831515ad8c4SAlexander Musman     return;
832515ad8c4SAlexander Musman 
8334aaaaabeSChandler Carruth   if (I->isTerminator()) {
8344aaaaabeSChandler Carruth     for (BasicBlock *Succ : successors(I))
8354aaaaabeSChandler Carruth       if (Succ == L.getHeader()) {
8364aaaaabeSChandler Carruth         I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
837515ad8c4SAlexander Musman         break;
838515ad8c4SAlexander Musman       }
839515ad8c4SAlexander Musman     return;
840515ad8c4SAlexander Musman   }
841515ad8c4SAlexander Musman }
842