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