123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841 |
- //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "CGLoopInfo.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/Attr.h"
- #include "clang/AST/Expr.h"
- #include "clang/Basic/CodeGenOptions.h"
- #include "llvm/IR/BasicBlock.h"
- #include "llvm/IR/CFG.h"
- #include "llvm/IR/Constants.h"
- #include "llvm/IR/InstrTypes.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/Metadata.h"
- using namespace clang::CodeGen;
- using namespace llvm;
- MDNode *
- LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) {
- LLVMContext &Ctx = Header->getContext();
- SmallVector<Metadata *, 4> NewLoopProperties;
- NewLoopProperties.push_back(nullptr);
- NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
- MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties);
- LoopID->replaceOperandWith(0, LoopID);
- return LoopID;
- }
- MDNode *LoopInfo::createPipeliningMetadata(const LoopAttributes &Attrs,
- ArrayRef<Metadata *> LoopProperties,
- bool &HasUserTransforms) {
- LLVMContext &Ctx = Header->getContext();
- Optional<bool> Enabled;
- if (Attrs.PipelineDisabled)
- Enabled = false;
- else if (Attrs.PipelineInitiationInterval != 0)
- Enabled = true;
- if (Enabled != true) {
- SmallVector<Metadata *, 4> NewLoopProperties;
- if (Enabled == false) {
- NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
- NewLoopProperties.push_back(
- MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"),
- ConstantAsMetadata::get(ConstantInt::get(
- llvm::Type::getInt1Ty(Ctx), 1))}));
- LoopProperties = NewLoopProperties;
- }
- return createLoopPropertiesMetadata(LoopProperties);
- }
- SmallVector<Metadata *, 4> Args;
- Args.push_back(nullptr);
- Args.append(LoopProperties.begin(), LoopProperties.end());
- if (Attrs.PipelineInitiationInterval > 0) {
- Metadata *Vals[] = {
- MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
- ConstantAsMetadata::get(ConstantInt::get(
- llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
- Args.push_back(MDNode::get(Ctx, Vals));
- }
- // No follow-up: This is the last transformation.
- MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
- LoopID->replaceOperandWith(0, LoopID);
- HasUserTransforms = true;
- return LoopID;
- }
- MDNode *
- LoopInfo::createPartialUnrollMetadata(const LoopAttributes &Attrs,
- ArrayRef<Metadata *> LoopProperties,
- bool &HasUserTransforms) {
- LLVMContext &Ctx = Header->getContext();
- Optional<bool> Enabled;
- if (Attrs.UnrollEnable == LoopAttributes::Disable)
- Enabled = false;
- else if (Attrs.UnrollEnable == LoopAttributes::Full)
- Enabled = None;
- else if (Attrs.UnrollEnable != LoopAttributes::Unspecified ||
- Attrs.UnrollCount != 0)
- Enabled = true;
- if (Enabled != true) {
- // createFullUnrollMetadata will already have added llvm.loop.unroll.disable
- // if unrolling is disabled.
- return createPipeliningMetadata(Attrs, LoopProperties, HasUserTransforms);
- }
- SmallVector<Metadata *, 4> FollowupLoopProperties;
- // Apply all loop properties to the unrolled loop.
- FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
- // Don't unroll an already unrolled loop.
- FollowupLoopProperties.push_back(
- MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
- bool FollowupHasTransforms = false;
- MDNode *Followup = createPipeliningMetadata(Attrs, FollowupLoopProperties,
- FollowupHasTransforms);
- SmallVector<Metadata *, 4> Args;
- Args.push_back(nullptr);
- Args.append(LoopProperties.begin(), LoopProperties.end());
- // Setting unroll.count
- if (Attrs.UnrollCount > 0) {
- Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
- ConstantAsMetadata::get(ConstantInt::get(
- llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
- Args.push_back(MDNode::get(Ctx, Vals));
- }
- // Setting unroll.full or unroll.disable
- if (Attrs.UnrollEnable == LoopAttributes::Enable) {
- Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")};
- Args.push_back(MDNode::get(Ctx, Vals));
- }
- if (FollowupHasTransforms)
- Args.push_back(MDNode::get(
- Ctx, {MDString::get(Ctx, "llvm.loop.unroll.followup_all"), Followup}));
- MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
- LoopID->replaceOperandWith(0, LoopID);
- HasUserTransforms = true;
- return LoopID;
- }
- MDNode *
- LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs,
- ArrayRef<Metadata *> LoopProperties,
- bool &HasUserTransforms) {
- LLVMContext &Ctx = Header->getContext();
- Optional<bool> Enabled;
- if (Attrs.UnrollAndJamEnable == LoopAttributes::Disable)
- Enabled = false;
- else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable ||
- Attrs.UnrollAndJamCount != 0)
- Enabled = true;
- if (Enabled != true) {
- SmallVector<Metadata *, 4> NewLoopProperties;
- if (Enabled == false) {
- NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
- NewLoopProperties.push_back(MDNode::get(
- Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
- LoopProperties = NewLoopProperties;
- }
- return createPartialUnrollMetadata(Attrs, LoopProperties,
- HasUserTransforms);
- }
- SmallVector<Metadata *, 4> FollowupLoopProperties;
- FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
- FollowupLoopProperties.push_back(
- MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
- bool FollowupHasTransforms = false;
- MDNode *Followup = createPartialUnrollMetadata(Attrs, FollowupLoopProperties,
- FollowupHasTransforms);
- SmallVector<Metadata *, 4> Args;
- Args.push_back(nullptr);
- Args.append(LoopProperties.begin(), LoopProperties.end());
- // Setting unroll_and_jam.count
- if (Attrs.UnrollAndJamCount > 0) {
- Metadata *Vals[] = {
- MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
- ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
- Attrs.UnrollAndJamCount))};
- Args.push_back(MDNode::get(Ctx, Vals));
- }
- if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) {
- Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")};
- Args.push_back(MDNode::get(Ctx, Vals));
- }
- if (FollowupHasTransforms)
- Args.push_back(MDNode::get(
- Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_outer"),
- Followup}));
- if (UnrollAndJamInnerFollowup)
- Args.push_back(MDNode::get(
- Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_inner"),
- UnrollAndJamInnerFollowup}));
- MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
- LoopID->replaceOperandWith(0, LoopID);
- HasUserTransforms = true;
- return LoopID;
- }
- MDNode *
- LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs,
- ArrayRef<Metadata *> LoopProperties,
- bool &HasUserTransforms) {
- LLVMContext &Ctx = Header->getContext();
- Optional<bool> Enabled;
- if (Attrs.VectorizeEnable == LoopAttributes::Disable)
- Enabled = false;
- else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
- Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified ||
- Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0 ||
- Attrs.VectorizeScalable != LoopAttributes::Unspecified)
- Enabled = true;
- if (Enabled != true) {
- SmallVector<Metadata *, 4> NewLoopProperties;
- if (Enabled == false) {
- NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
- NewLoopProperties.push_back(
- MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
- ConstantAsMetadata::get(ConstantInt::get(
- llvm::Type::getInt1Ty(Ctx), 0))}));
- LoopProperties = NewLoopProperties;
- }
- return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms);
- }
- // Apply all loop properties to the vectorized loop.
- SmallVector<Metadata *, 4> FollowupLoopProperties;
- FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
- // Don't vectorize an already vectorized loop.
- FollowupLoopProperties.push_back(
- MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
- bool FollowupHasTransforms = false;
- MDNode *Followup = createUnrollAndJamMetadata(Attrs, FollowupLoopProperties,
- FollowupHasTransforms);
- SmallVector<Metadata *, 4> Args;
- Args.push_back(nullptr);
- Args.append(LoopProperties.begin(), LoopProperties.end());
- // Setting vectorize.predicate when it has been specified and vectorization
- // has not been disabled.
- bool IsVectorPredicateEnabled = false;
- if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified) {
- IsVectorPredicateEnabled =
- (Attrs.VectorizePredicateEnable == LoopAttributes::Enable);
- Metadata *Vals[] = {
- MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"),
- ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx),
- IsVectorPredicateEnabled))};
- Args.push_back(MDNode::get(Ctx, Vals));
- }
- // Setting vectorize.width
- if (Attrs.VectorizeWidth > 0) {
- Metadata *Vals[] = {
- MDString::get(Ctx, "llvm.loop.vectorize.width"),
- ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
- Attrs.VectorizeWidth))};
- Args.push_back(MDNode::get(Ctx, Vals));
- }
- if (Attrs.VectorizeScalable != LoopAttributes::Unspecified) {
- bool IsScalable = Attrs.VectorizeScalable == LoopAttributes::Enable;
- Metadata *Vals[] = {
- MDString::get(Ctx, "llvm.loop.vectorize.scalable.enable"),
- ConstantAsMetadata::get(
- ConstantInt::get(llvm::Type::getInt1Ty(Ctx), IsScalable))};
- Args.push_back(MDNode::get(Ctx, Vals));
- }
- // Setting interleave.count
- if (Attrs.InterleaveCount > 0) {
- Metadata *Vals[] = {
- MDString::get(Ctx, "llvm.loop.interleave.count"),
- ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
- Attrs.InterleaveCount))};
- Args.push_back(MDNode::get(Ctx, Vals));
- }
- // vectorize.enable is set if:
- // 1) loop hint vectorize.enable is set, or
- // 2) it is implied when vectorize.predicate is set, or
- // 3) it is implied when vectorize.width is set to a value > 1
- // 4) it is implied when vectorize.scalable.enable is true
- // 5) it is implied when vectorize.width is unset (0) and the user
- // explicitly requested fixed-width vectorization, i.e.
- // vectorize.scalable.enable is false.
- if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
- (IsVectorPredicateEnabled && Attrs.VectorizeWidth != 1) ||
- Attrs.VectorizeWidth > 1 ||
- Attrs.VectorizeScalable == LoopAttributes::Enable ||
- (Attrs.VectorizeScalable == LoopAttributes::Disable &&
- Attrs.VectorizeWidth != 1)) {
- bool AttrVal = Attrs.VectorizeEnable != LoopAttributes::Disable;
- Args.push_back(
- MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
- ConstantAsMetadata::get(ConstantInt::get(
- llvm::Type::getInt1Ty(Ctx), AttrVal))}));
- }
- if (FollowupHasTransforms)
- Args.push_back(MDNode::get(
- Ctx,
- {MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup}));
- MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
- LoopID->replaceOperandWith(0, LoopID);
- HasUserTransforms = true;
- return LoopID;
- }
- MDNode *
- LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs,
- ArrayRef<Metadata *> LoopProperties,
- bool &HasUserTransforms) {
- LLVMContext &Ctx = Header->getContext();
- Optional<bool> Enabled;
- if (Attrs.DistributeEnable == LoopAttributes::Disable)
- Enabled = false;
- if (Attrs.DistributeEnable == LoopAttributes::Enable)
- Enabled = true;
- if (Enabled != true) {
- SmallVector<Metadata *, 4> NewLoopProperties;
- if (Enabled == false) {
- NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
- NewLoopProperties.push_back(
- MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),
- ConstantAsMetadata::get(ConstantInt::get(
- llvm::Type::getInt1Ty(Ctx), 0))}));
- LoopProperties = NewLoopProperties;
- }
- return createLoopVectorizeMetadata(Attrs, LoopProperties,
- HasUserTransforms);
- }
- bool FollowupHasTransforms = false;
- MDNode *Followup =
- createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);
- SmallVector<Metadata *, 4> Args;
- Args.push_back(nullptr);
- Args.append(LoopProperties.begin(), LoopProperties.end());
- Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
- ConstantAsMetadata::get(ConstantInt::get(
- llvm::Type::getInt1Ty(Ctx),
- (Attrs.DistributeEnable == LoopAttributes::Enable)))};
- Args.push_back(MDNode::get(Ctx, Vals));
- if (FollowupHasTransforms)
- Args.push_back(MDNode::get(
- Ctx,
- {MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup}));
- MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
- LoopID->replaceOperandWith(0, LoopID);
- HasUserTransforms = true;
- return LoopID;
- }
- MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,
- ArrayRef<Metadata *> LoopProperties,
- bool &HasUserTransforms) {
- LLVMContext &Ctx = Header->getContext();
- Optional<bool> Enabled;
- if (Attrs.UnrollEnable == LoopAttributes::Disable)
- Enabled = false;
- else if (Attrs.UnrollEnable == LoopAttributes::Full)
- Enabled = true;
- if (Enabled != true) {
- SmallVector<Metadata *, 4> NewLoopProperties;
- if (Enabled == false) {
- NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
- NewLoopProperties.push_back(
- MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
- LoopProperties = NewLoopProperties;
- }
- return createLoopDistributeMetadata(Attrs, LoopProperties,
- HasUserTransforms);
- }
- SmallVector<Metadata *, 4> Args;
- Args.push_back(nullptr);
- Args.append(LoopProperties.begin(), LoopProperties.end());
- Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));
- // No follow-up: there is no loop after full unrolling.
- // TODO: Warn if there are transformations after full unrolling.
- MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
- LoopID->replaceOperandWith(0, LoopID);
- HasUserTransforms = true;
- return LoopID;
- }
- MDNode *LoopInfo::createMetadata(
- const LoopAttributes &Attrs,
- llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,
- bool &HasUserTransforms) {
- SmallVector<Metadata *, 3> LoopProperties;
- // If we have a valid start debug location for the loop, add it.
- if (StartLoc) {
- LoopProperties.push_back(StartLoc.getAsMDNode());
- // If we also have a valid end debug location for the loop, add it.
- if (EndLoc)
- LoopProperties.push_back(EndLoc.getAsMDNode());
- }
- LLVMContext &Ctx = Header->getContext();
- if (Attrs.MustProgress)
- LoopProperties.push_back(
- MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.mustprogress")));
- assert(!!AccGroup == Attrs.IsParallel &&
- "There must be an access group iff the loop is parallel");
- if (Attrs.IsParallel) {
- LoopProperties.push_back(MDNode::get(
- Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
- }
- LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
- AdditionalLoopProperties.end());
- return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
- }
- LoopAttributes::LoopAttributes(bool IsParallel)
- : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
- UnrollEnable(LoopAttributes::Unspecified),
- UnrollAndJamEnable(LoopAttributes::Unspecified),
- VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
- VectorizeScalable(LoopAttributes::Unspecified), InterleaveCount(0),
- UnrollCount(0), UnrollAndJamCount(0),
- DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
- PipelineInitiationInterval(0), MustProgress(false) {}
- void LoopAttributes::clear() {
- IsParallel = false;
- VectorizeWidth = 0;
- VectorizeScalable = LoopAttributes::Unspecified;
- InterleaveCount = 0;
- UnrollCount = 0;
- UnrollAndJamCount = 0;
- VectorizeEnable = LoopAttributes::Unspecified;
- UnrollEnable = LoopAttributes::Unspecified;
- UnrollAndJamEnable = LoopAttributes::Unspecified;
- VectorizePredicateEnable = LoopAttributes::Unspecified;
- DistributeEnable = LoopAttributes::Unspecified;
- PipelineDisabled = false;
- PipelineInitiationInterval = 0;
- MustProgress = false;
- }
- LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
- const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
- LoopInfo *Parent)
- : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
- Parent(Parent) {
- if (Attrs.IsParallel) {
- // Create an access group for this loop.
- LLVMContext &Ctx = Header->getContext();
- AccGroup = MDNode::getDistinct(Ctx, {});
- }
- if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
- Attrs.VectorizeScalable == LoopAttributes::Unspecified &&
- Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
- Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
- Attrs.PipelineInitiationInterval == 0 &&
- Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified &&
- Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
- Attrs.UnrollEnable == LoopAttributes::Unspecified &&
- Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
- Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
- !EndLoc && !Attrs.MustProgress)
- return;
- TempLoopID = MDNode::getTemporary(Header->getContext(), None);
- }
- void LoopInfo::finish() {
- // We did not annotate the loop body instructions because there are no
- // attributes for this loop.
- if (!TempLoopID)
- return;
- MDNode *LoopID;
- LoopAttributes CurLoopAttr = Attrs;
- LLVMContext &Ctx = Header->getContext();
- if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
- Parent->Attrs.UnrollAndJamCount != 0)) {
- // Parent unroll-and-jams this loop.
- // Split the transformations in those that happens before the unroll-and-jam
- // and those after.
- LoopAttributes BeforeJam, AfterJam;
- BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
- BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
- BeforeJam.VectorizeScalable = Attrs.VectorizeScalable;
- BeforeJam.InterleaveCount = Attrs.InterleaveCount;
- BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
- BeforeJam.DistributeEnable = Attrs.DistributeEnable;
- BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
- switch (Attrs.UnrollEnable) {
- case LoopAttributes::Unspecified:
- case LoopAttributes::Disable:
- BeforeJam.UnrollEnable = Attrs.UnrollEnable;
- AfterJam.UnrollEnable = Attrs.UnrollEnable;
- break;
- case LoopAttributes::Full:
- BeforeJam.UnrollEnable = LoopAttributes::Full;
- break;
- case LoopAttributes::Enable:
- AfterJam.UnrollEnable = LoopAttributes::Enable;
- break;
- }
- AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
- AfterJam.UnrollCount = Attrs.UnrollCount;
- AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
- AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;
- // If this loop is subject of an unroll-and-jam by the parent loop, and has
- // an unroll-and-jam annotation itself, we have to decide whether to first
- // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
- // UnrollAndJam pass processes loops from inner to outer, so we apply the
- // inner first.
- BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
- BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
- // Set the inner followup metadata to process by the outer loop. Only
- // consider the first inner loop.
- if (!Parent->UnrollAndJamInnerFollowup) {
- // Splitting the attributes into a BeforeJam and an AfterJam part will
- // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
- // to be forwarded to the AfterJam part. We detect the situation here and
- // add it manually.
- SmallVector<Metadata *, 1> BeforeLoopProperties;
- if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||
- BeforeJam.VectorizePredicateEnable != LoopAttributes::Unspecified ||
- BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0 ||
- BeforeJam.VectorizeScalable == LoopAttributes::Enable)
- BeforeLoopProperties.push_back(
- MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
- bool InnerFollowupHasTransform = false;
- MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,
- InnerFollowupHasTransform);
- if (InnerFollowupHasTransform)
- Parent->UnrollAndJamInnerFollowup = InnerFollowup;
- }
- CurLoopAttr = BeforeJam;
- }
- bool HasUserTransforms = false;
- LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);
- TempLoopID->replaceAllUsesWith(LoopID);
- }
- void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
- const llvm::DebugLoc &EndLoc) {
- Active.emplace_back(
- new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
- Active.empty() ? nullptr : Active.back().get()));
- // Clear the attributes so nested loops do not inherit them.
- StagedAttrs.clear();
- }
- void LoopInfoStack::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) {
- // Identify loop hint attributes from Attrs.
- for (const auto *Attr : Attrs) {
- const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
- const OpenCLUnrollHintAttr *OpenCLHint =
- dyn_cast<OpenCLUnrollHintAttr>(Attr);
- // Skip non loop hint attributes
- if (!LH && !OpenCLHint) {
- continue;
- }
- LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
- LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
- unsigned ValueInt = 1;
- // Translate opencl_unroll_hint attribute argument to
- // equivalent LoopHintAttr enums.
- // OpenCL v2.0 s6.11.5:
- // 0 - enable unroll (no argument).
- // 1 - disable unroll.
- // other positive integer n - unroll by n.
- if (OpenCLHint) {
- ValueInt = OpenCLHint->getUnrollHint();
- if (ValueInt == 0) {
- State = LoopHintAttr::Enable;
- } else if (ValueInt != 1) {
- Option = LoopHintAttr::UnrollCount;
- State = LoopHintAttr::Numeric;
- }
- } else if (LH) {
- auto *ValueExpr = LH->getValue();
- if (ValueExpr) {
- llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
- ValueInt = ValueAPS.getSExtValue();
- }
- Option = LH->getOption();
- State = LH->getState();
- }
- switch (State) {
- case LoopHintAttr::Disable:
- switch (Option) {
- case LoopHintAttr::Vectorize:
- // Disable vectorization by specifying a width of 1.
- setVectorizeWidth(1);
- setVectorizeScalable(LoopAttributes::Unspecified);
- break;
- case LoopHintAttr::Interleave:
- // Disable interleaving by speciyfing a count of 1.
- setInterleaveCount(1);
- break;
- case LoopHintAttr::Unroll:
- setUnrollState(LoopAttributes::Disable);
- break;
- case LoopHintAttr::UnrollAndJam:
- setUnrollAndJamState(LoopAttributes::Disable);
- break;
- case LoopHintAttr::VectorizePredicate:
- setVectorizePredicateState(LoopAttributes::Disable);
- break;
- case LoopHintAttr::Distribute:
- setDistributeState(false);
- break;
- case LoopHintAttr::PipelineDisabled:
- setPipelineDisabled(true);
- break;
- case LoopHintAttr::UnrollCount:
- case LoopHintAttr::UnrollAndJamCount:
- case LoopHintAttr::VectorizeWidth:
- case LoopHintAttr::InterleaveCount:
- case LoopHintAttr::PipelineInitiationInterval:
- llvm_unreachable("Options cannot be disabled.");
- break;
- }
- break;
- case LoopHintAttr::Enable:
- switch (Option) {
- case LoopHintAttr::Vectorize:
- case LoopHintAttr::Interleave:
- setVectorizeEnable(true);
- break;
- case LoopHintAttr::Unroll:
- setUnrollState(LoopAttributes::Enable);
- break;
- case LoopHintAttr::UnrollAndJam:
- setUnrollAndJamState(LoopAttributes::Enable);
- break;
- case LoopHintAttr::VectorizePredicate:
- setVectorizePredicateState(LoopAttributes::Enable);
- break;
- case LoopHintAttr::Distribute:
- setDistributeState(true);
- break;
- case LoopHintAttr::UnrollCount:
- case LoopHintAttr::UnrollAndJamCount:
- case LoopHintAttr::VectorizeWidth:
- case LoopHintAttr::InterleaveCount:
- case LoopHintAttr::PipelineDisabled:
- case LoopHintAttr::PipelineInitiationInterval:
- llvm_unreachable("Options cannot enabled.");
- break;
- }
- break;
- case LoopHintAttr::AssumeSafety:
- switch (Option) {
- case LoopHintAttr::Vectorize:
- case LoopHintAttr::Interleave:
- // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
- setParallel(true);
- setVectorizeEnable(true);
- break;
- case LoopHintAttr::Unroll:
- case LoopHintAttr::UnrollAndJam:
- case LoopHintAttr::VectorizePredicate:
- case LoopHintAttr::UnrollCount:
- case LoopHintAttr::UnrollAndJamCount:
- case LoopHintAttr::VectorizeWidth:
- case LoopHintAttr::InterleaveCount:
- case LoopHintAttr::Distribute:
- case LoopHintAttr::PipelineDisabled:
- case LoopHintAttr::PipelineInitiationInterval:
- llvm_unreachable("Options cannot be used to assume mem safety.");
- break;
- }
- break;
- case LoopHintAttr::Full:
- switch (Option) {
- case LoopHintAttr::Unroll:
- setUnrollState(LoopAttributes::Full);
- break;
- case LoopHintAttr::UnrollAndJam:
- setUnrollAndJamState(LoopAttributes::Full);
- break;
- case LoopHintAttr::Vectorize:
- case LoopHintAttr::Interleave:
- case LoopHintAttr::UnrollCount:
- case LoopHintAttr::UnrollAndJamCount:
- case LoopHintAttr::VectorizeWidth:
- case LoopHintAttr::InterleaveCount:
- case LoopHintAttr::Distribute:
- case LoopHintAttr::PipelineDisabled:
- case LoopHintAttr::PipelineInitiationInterval:
- case LoopHintAttr::VectorizePredicate:
- llvm_unreachable("Options cannot be used with 'full' hint.");
- break;
- }
- break;
- case LoopHintAttr::FixedWidth:
- case LoopHintAttr::ScalableWidth:
- switch (Option) {
- case LoopHintAttr::VectorizeWidth:
- setVectorizeScalable(State == LoopHintAttr::ScalableWidth
- ? LoopAttributes::Enable
- : LoopAttributes::Disable);
- if (LH->getValue())
- setVectorizeWidth(ValueInt);
- break;
- default:
- llvm_unreachable("Options cannot be used with 'scalable' hint.");
- break;
- }
- break;
- case LoopHintAttr::Numeric:
- switch (Option) {
- case LoopHintAttr::InterleaveCount:
- setInterleaveCount(ValueInt);
- break;
- case LoopHintAttr::UnrollCount:
- setUnrollCount(ValueInt);
- break;
- case LoopHintAttr::UnrollAndJamCount:
- setUnrollAndJamCount(ValueInt);
- break;
- case LoopHintAttr::PipelineInitiationInterval:
- setPipelineInitiationInterval(ValueInt);
- break;
- case LoopHintAttr::Unroll:
- case LoopHintAttr::UnrollAndJam:
- case LoopHintAttr::VectorizePredicate:
- case LoopHintAttr::Vectorize:
- case LoopHintAttr::VectorizeWidth:
- case LoopHintAttr::Interleave:
- case LoopHintAttr::Distribute:
- case LoopHintAttr::PipelineDisabled:
- llvm_unreachable("Options cannot be assigned a value.");
- break;
- }
- break;
- }
- }
- setMustProgress(MustProgress);
- if (CGOpts.OptimizationLevel > 0)
- // Disable unrolling for the loop, if unrolling is disabled (via
- // -fno-unroll-loops) and no pragmas override the decision.
- if (!CGOpts.UnrollLoops &&
- (StagedAttrs.UnrollEnable == LoopAttributes::Unspecified &&
- StagedAttrs.UnrollCount == 0))
- setUnrollState(LoopAttributes::Disable);
- /// Stage the attributes.
- push(Header, StartLoc, EndLoc);
- }
- void LoopInfoStack::pop() {
- assert(!Active.empty() && "No active loops to pop");
- Active.back()->finish();
- Active.pop_back();
- }
- void LoopInfoStack::InsertHelper(Instruction *I) const {
- if (I->mayReadOrWriteMemory()) {
- SmallVector<Metadata *, 4> AccessGroups;
- for (const auto &AL : Active) {
- // Here we assume that every loop that has an access group is parallel.
- if (MDNode *Group = AL->getAccessGroup())
- AccessGroups.push_back(Group);
- }
- MDNode *UnionMD = nullptr;
- if (AccessGroups.size() == 1)
- UnionMD = cast<MDNode>(AccessGroups[0]);
- else if (AccessGroups.size() >= 2)
- UnionMD = MDNode::get(I->getContext(), AccessGroups);
- I->setMetadata("llvm.access.group", UnionMD);
- }
- if (!hasInfo())
- return;
- const LoopInfo &L = getInfo();
- if (!L.getLoopID())
- return;
- if (I->isTerminator()) {
- for (BasicBlock *Succ : successors(I))
- if (Succ == L.getHeader()) {
- I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
- break;
- }
- return;
- }
- }
|