Path: blob/main/contrib/llvm-project/clang/lib/CodeGen/CGLoopInfo.cpp
35234 views
//===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "CGLoopInfo.h"9#include "clang/AST/ASTContext.h"10#include "clang/AST/Attr.h"11#include "clang/AST/Expr.h"12#include "clang/Basic/CodeGenOptions.h"13#include "llvm/IR/BasicBlock.h"14#include "llvm/IR/CFG.h"15#include "llvm/IR/Constants.h"16#include "llvm/IR/InstrTypes.h"17#include "llvm/IR/Instructions.h"18#include "llvm/IR/Metadata.h"19#include <optional>20using namespace clang::CodeGen;21using namespace llvm;2223MDNode *24LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) {25LLVMContext &Ctx = Header->getContext();26SmallVector<Metadata *, 4> NewLoopProperties;27NewLoopProperties.push_back(nullptr);28NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());2930MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties);31LoopID->replaceOperandWith(0, LoopID);32return LoopID;33}3435MDNode *LoopInfo::createPipeliningMetadata(const LoopAttributes &Attrs,36ArrayRef<Metadata *> LoopProperties,37bool &HasUserTransforms) {38LLVMContext &Ctx = Header->getContext();3940std::optional<bool> Enabled;41if (Attrs.PipelineDisabled)42Enabled = false;43else if (Attrs.PipelineInitiationInterval != 0)44Enabled = true;4546if (Enabled != true) {47SmallVector<Metadata *, 4> NewLoopProperties;48if (Enabled == false) {49NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());50NewLoopProperties.push_back(51MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"),52ConstantAsMetadata::get(ConstantInt::get(53llvm::Type::getInt1Ty(Ctx), 1))}));54LoopProperties = NewLoopProperties;55}56return createLoopPropertiesMetadata(LoopProperties);57}5859SmallVector<Metadata *, 4> Args;60Args.push_back(nullptr);61Args.append(LoopProperties.begin(), LoopProperties.end());6263if (Attrs.PipelineInitiationInterval > 0) {64Metadata *Vals[] = {65MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),66ConstantAsMetadata::get(ConstantInt::get(67llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};68Args.push_back(MDNode::get(Ctx, Vals));69}7071// No follow-up: This is the last transformation.7273MDNode *LoopID = MDNode::getDistinct(Ctx, Args);74LoopID->replaceOperandWith(0, LoopID);75HasUserTransforms = true;76return LoopID;77}7879MDNode *80LoopInfo::createPartialUnrollMetadata(const LoopAttributes &Attrs,81ArrayRef<Metadata *> LoopProperties,82bool &HasUserTransforms) {83LLVMContext &Ctx = Header->getContext();8485std::optional<bool> Enabled;86if (Attrs.UnrollEnable == LoopAttributes::Disable)87Enabled = false;88else if (Attrs.UnrollEnable == LoopAttributes::Full)89Enabled = std::nullopt;90else if (Attrs.UnrollEnable != LoopAttributes::Unspecified ||91Attrs.UnrollCount != 0)92Enabled = true;9394if (Enabled != true) {95// createFullUnrollMetadata will already have added llvm.loop.unroll.disable96// if unrolling is disabled.97return createPipeliningMetadata(Attrs, LoopProperties, HasUserTransforms);98}99100SmallVector<Metadata *, 4> FollowupLoopProperties;101102// Apply all loop properties to the unrolled loop.103FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());104105// Don't unroll an already unrolled loop.106FollowupLoopProperties.push_back(107MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));108109bool FollowupHasTransforms = false;110MDNode *Followup = createPipeliningMetadata(Attrs, FollowupLoopProperties,111FollowupHasTransforms);112113SmallVector<Metadata *, 4> Args;114Args.push_back(nullptr);115Args.append(LoopProperties.begin(), LoopProperties.end());116117// Setting unroll.count118if (Attrs.UnrollCount > 0) {119Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),120ConstantAsMetadata::get(ConstantInt::get(121llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))};122Args.push_back(MDNode::get(Ctx, Vals));123}124125// Setting unroll.full or unroll.disable126if (Attrs.UnrollEnable == LoopAttributes::Enable) {127Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")};128Args.push_back(MDNode::get(Ctx, Vals));129}130131if (FollowupHasTransforms)132Args.push_back(MDNode::get(133Ctx, {MDString::get(Ctx, "llvm.loop.unroll.followup_all"), Followup}));134135MDNode *LoopID = MDNode::getDistinct(Ctx, Args);136LoopID->replaceOperandWith(0, LoopID);137HasUserTransforms = true;138return LoopID;139}140141MDNode *142LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs,143ArrayRef<Metadata *> LoopProperties,144bool &HasUserTransforms) {145LLVMContext &Ctx = Header->getContext();146147std::optional<bool> Enabled;148if (Attrs.UnrollAndJamEnable == LoopAttributes::Disable)149Enabled = false;150else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable ||151Attrs.UnrollAndJamCount != 0)152Enabled = true;153154if (Enabled != true) {155SmallVector<Metadata *, 4> NewLoopProperties;156if (Enabled == false) {157NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());158NewLoopProperties.push_back(MDNode::get(159Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));160LoopProperties = NewLoopProperties;161}162return createPartialUnrollMetadata(Attrs, LoopProperties,163HasUserTransforms);164}165166SmallVector<Metadata *, 4> FollowupLoopProperties;167FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());168FollowupLoopProperties.push_back(169MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));170171bool FollowupHasTransforms = false;172MDNode *Followup = createPartialUnrollMetadata(Attrs, FollowupLoopProperties,173FollowupHasTransforms);174175SmallVector<Metadata *, 4> Args;176Args.push_back(nullptr);177Args.append(LoopProperties.begin(), LoopProperties.end());178179// Setting unroll_and_jam.count180if (Attrs.UnrollAndJamCount > 0) {181Metadata *Vals[] = {182MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),183ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),184Attrs.UnrollAndJamCount))};185Args.push_back(MDNode::get(Ctx, Vals));186}187188if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) {189Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")};190Args.push_back(MDNode::get(Ctx, Vals));191}192193if (FollowupHasTransforms)194Args.push_back(MDNode::get(195Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_outer"),196Followup}));197198if (UnrollAndJamInnerFollowup)199Args.push_back(MDNode::get(200Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_inner"),201UnrollAndJamInnerFollowup}));202203MDNode *LoopID = MDNode::getDistinct(Ctx, Args);204LoopID->replaceOperandWith(0, LoopID);205HasUserTransforms = true;206return LoopID;207}208209MDNode *210LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs,211ArrayRef<Metadata *> LoopProperties,212bool &HasUserTransforms) {213LLVMContext &Ctx = Header->getContext();214215std::optional<bool> Enabled;216if (Attrs.VectorizeEnable == LoopAttributes::Disable)217Enabled = false;218else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||219Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified ||220Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0 ||221Attrs.VectorizeScalable != LoopAttributes::Unspecified)222Enabled = true;223224if (Enabled != true) {225SmallVector<Metadata *, 4> NewLoopProperties;226if (Enabled == false) {227NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());228NewLoopProperties.push_back(229MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),230ConstantAsMetadata::get(ConstantInt::get(231llvm::Type::getInt1Ty(Ctx), 0))}));232LoopProperties = NewLoopProperties;233}234return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms);235}236237// Apply all loop properties to the vectorized loop.238SmallVector<Metadata *, 4> FollowupLoopProperties;239FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());240241// Don't vectorize an already vectorized loop.242FollowupLoopProperties.push_back(243MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));244245bool FollowupHasTransforms = false;246MDNode *Followup = createUnrollAndJamMetadata(Attrs, FollowupLoopProperties,247FollowupHasTransforms);248249SmallVector<Metadata *, 4> Args;250Args.push_back(nullptr);251Args.append(LoopProperties.begin(), LoopProperties.end());252253// Setting vectorize.predicate when it has been specified and vectorization254// has not been disabled.255bool IsVectorPredicateEnabled = false;256if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified) {257IsVectorPredicateEnabled =258(Attrs.VectorizePredicateEnable == LoopAttributes::Enable);259260Metadata *Vals[] = {261MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"),262ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx),263IsVectorPredicateEnabled))};264Args.push_back(MDNode::get(Ctx, Vals));265}266267// Setting vectorize.width268if (Attrs.VectorizeWidth > 0) {269Metadata *Vals[] = {270MDString::get(Ctx, "llvm.loop.vectorize.width"),271ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),272Attrs.VectorizeWidth))};273274Args.push_back(MDNode::get(Ctx, Vals));275}276277if (Attrs.VectorizeScalable != LoopAttributes::Unspecified) {278bool IsScalable = Attrs.VectorizeScalable == LoopAttributes::Enable;279Metadata *Vals[] = {280MDString::get(Ctx, "llvm.loop.vectorize.scalable.enable"),281ConstantAsMetadata::get(282ConstantInt::get(llvm::Type::getInt1Ty(Ctx), IsScalable))};283Args.push_back(MDNode::get(Ctx, Vals));284}285286// Setting interleave.count287if (Attrs.InterleaveCount > 0) {288Metadata *Vals[] = {289MDString::get(Ctx, "llvm.loop.interleave.count"),290ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),291Attrs.InterleaveCount))};292Args.push_back(MDNode::get(Ctx, Vals));293}294295// vectorize.enable is set if:296// 1) loop hint vectorize.enable is set, or297// 2) it is implied when vectorize.predicate is set, or298// 3) it is implied when vectorize.width is set to a value > 1299// 4) it is implied when vectorize.scalable.enable is true300// 5) it is implied when vectorize.width is unset (0) and the user301// explicitly requested fixed-width vectorization, i.e.302// vectorize.scalable.enable is false.303if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||304(IsVectorPredicateEnabled && Attrs.VectorizeWidth != 1) ||305Attrs.VectorizeWidth > 1 ||306Attrs.VectorizeScalable == LoopAttributes::Enable ||307(Attrs.VectorizeScalable == LoopAttributes::Disable &&308Attrs.VectorizeWidth != 1)) {309bool AttrVal = Attrs.VectorizeEnable != LoopAttributes::Disable;310Args.push_back(311MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),312ConstantAsMetadata::get(ConstantInt::get(313llvm::Type::getInt1Ty(Ctx), AttrVal))}));314}315316if (FollowupHasTransforms)317Args.push_back(MDNode::get(318Ctx,319{MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup}));320321MDNode *LoopID = MDNode::getDistinct(Ctx, Args);322LoopID->replaceOperandWith(0, LoopID);323HasUserTransforms = true;324return LoopID;325}326327MDNode *328LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs,329ArrayRef<Metadata *> LoopProperties,330bool &HasUserTransforms) {331LLVMContext &Ctx = Header->getContext();332333std::optional<bool> Enabled;334if (Attrs.DistributeEnable == LoopAttributes::Disable)335Enabled = false;336if (Attrs.DistributeEnable == LoopAttributes::Enable)337Enabled = true;338339if (Enabled != true) {340SmallVector<Metadata *, 4> NewLoopProperties;341if (Enabled == false) {342NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());343NewLoopProperties.push_back(344MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),345ConstantAsMetadata::get(ConstantInt::get(346llvm::Type::getInt1Ty(Ctx), 0))}));347LoopProperties = NewLoopProperties;348}349return createLoopVectorizeMetadata(Attrs, LoopProperties,350HasUserTransforms);351}352353bool FollowupHasTransforms = false;354MDNode *Followup =355createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);356357SmallVector<Metadata *, 4> Args;358Args.push_back(nullptr);359Args.append(LoopProperties.begin(), LoopProperties.end());360361Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),362ConstantAsMetadata::get(ConstantInt::get(363llvm::Type::getInt1Ty(Ctx),364(Attrs.DistributeEnable == LoopAttributes::Enable)))};365Args.push_back(MDNode::get(Ctx, Vals));366367if (FollowupHasTransforms)368Args.push_back(MDNode::get(369Ctx,370{MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup}));371372MDNode *LoopID = MDNode::getDistinct(Ctx, Args);373LoopID->replaceOperandWith(0, LoopID);374HasUserTransforms = true;375return LoopID;376}377378MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,379ArrayRef<Metadata *> LoopProperties,380bool &HasUserTransforms) {381LLVMContext &Ctx = Header->getContext();382383std::optional<bool> Enabled;384if (Attrs.UnrollEnable == LoopAttributes::Disable)385Enabled = false;386else if (Attrs.UnrollEnable == LoopAttributes::Full)387Enabled = true;388389if (Enabled != true) {390SmallVector<Metadata *, 4> NewLoopProperties;391if (Enabled == false) {392NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());393NewLoopProperties.push_back(394MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));395LoopProperties = NewLoopProperties;396}397return createLoopDistributeMetadata(Attrs, LoopProperties,398HasUserTransforms);399}400401SmallVector<Metadata *, 4> Args;402Args.push_back(nullptr);403Args.append(LoopProperties.begin(), LoopProperties.end());404Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));405406// No follow-up: there is no loop after full unrolling.407// TODO: Warn if there are transformations after full unrolling.408409MDNode *LoopID = MDNode::getDistinct(Ctx, Args);410LoopID->replaceOperandWith(0, LoopID);411HasUserTransforms = true;412return LoopID;413}414415MDNode *LoopInfo::createMetadata(416const LoopAttributes &Attrs,417llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,418bool &HasUserTransforms) {419SmallVector<Metadata *, 3> LoopProperties;420421// If we have a valid start debug location for the loop, add it.422if (StartLoc) {423LoopProperties.push_back(StartLoc.getAsMDNode());424425// If we also have a valid end debug location for the loop, add it.426if (EndLoc)427LoopProperties.push_back(EndLoc.getAsMDNode());428}429430LLVMContext &Ctx = Header->getContext();431if (Attrs.MustProgress)432LoopProperties.push_back(433MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.mustprogress")));434435assert(!!AccGroup == Attrs.IsParallel &&436"There must be an access group iff the loop is parallel");437if (Attrs.IsParallel) {438LoopProperties.push_back(MDNode::get(439Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));440}441442// Setting clang::code_align attribute.443if (Attrs.CodeAlign > 0) {444Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.align"),445ConstantAsMetadata::get(ConstantInt::get(446llvm::Type::getInt32Ty(Ctx), Attrs.CodeAlign))};447LoopProperties.push_back(MDNode::get(Ctx, Vals));448}449450LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),451AdditionalLoopProperties.end());452return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);453}454455LoopAttributes::LoopAttributes(bool IsParallel)456: IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),457UnrollEnable(LoopAttributes::Unspecified),458UnrollAndJamEnable(LoopAttributes::Unspecified),459VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),460VectorizeScalable(LoopAttributes::Unspecified), InterleaveCount(0),461UnrollCount(0), UnrollAndJamCount(0),462DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),463PipelineInitiationInterval(0), CodeAlign(0), MustProgress(false) {}464465void LoopAttributes::clear() {466IsParallel = false;467VectorizeWidth = 0;468VectorizeScalable = LoopAttributes::Unspecified;469InterleaveCount = 0;470UnrollCount = 0;471UnrollAndJamCount = 0;472VectorizeEnable = LoopAttributes::Unspecified;473UnrollEnable = LoopAttributes::Unspecified;474UnrollAndJamEnable = LoopAttributes::Unspecified;475VectorizePredicateEnable = LoopAttributes::Unspecified;476DistributeEnable = LoopAttributes::Unspecified;477PipelineDisabled = false;478PipelineInitiationInterval = 0;479CodeAlign = 0;480MustProgress = false;481}482483LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,484const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,485LoopInfo *Parent)486: Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),487Parent(Parent) {488489if (Attrs.IsParallel) {490// Create an access group for this loop.491LLVMContext &Ctx = Header->getContext();492AccGroup = MDNode::getDistinct(Ctx, {});493}494495if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&496Attrs.VectorizeScalable == LoopAttributes::Unspecified &&497Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&498Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&499Attrs.PipelineInitiationInterval == 0 &&500Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified &&501Attrs.VectorizeEnable == LoopAttributes::Unspecified &&502Attrs.UnrollEnable == LoopAttributes::Unspecified &&503Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&504Attrs.DistributeEnable == LoopAttributes::Unspecified &&505Attrs.CodeAlign == 0 && !StartLoc && !EndLoc && !Attrs.MustProgress)506return;507508TempLoopID = MDNode::getTemporary(Header->getContext(), std::nullopt);509}510511void LoopInfo::finish() {512// We did not annotate the loop body instructions because there are no513// attributes for this loop.514if (!TempLoopID)515return;516517MDNode *LoopID;518LoopAttributes CurLoopAttr = Attrs;519LLVMContext &Ctx = Header->getContext();520521if (Parent && (Parent->Attrs.UnrollAndJamEnable ||522Parent->Attrs.UnrollAndJamCount != 0)) {523// Parent unroll-and-jams this loop.524// Split the transformations in those that happens before the unroll-and-jam525// and those after.526527LoopAttributes BeforeJam, AfterJam;528529BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;530531BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;532BeforeJam.VectorizeScalable = Attrs.VectorizeScalable;533BeforeJam.InterleaveCount = Attrs.InterleaveCount;534BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;535BeforeJam.DistributeEnable = Attrs.DistributeEnable;536BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;537538switch (Attrs.UnrollEnable) {539case LoopAttributes::Unspecified:540case LoopAttributes::Disable:541BeforeJam.UnrollEnable = Attrs.UnrollEnable;542AfterJam.UnrollEnable = Attrs.UnrollEnable;543break;544case LoopAttributes::Full:545BeforeJam.UnrollEnable = LoopAttributes::Full;546break;547case LoopAttributes::Enable:548AfterJam.UnrollEnable = LoopAttributes::Enable;549break;550}551552AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;553AfterJam.UnrollCount = Attrs.UnrollCount;554AfterJam.PipelineDisabled = Attrs.PipelineDisabled;555AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;556557// If this loop is subject of an unroll-and-jam by the parent loop, and has558// an unroll-and-jam annotation itself, we have to decide whether to first559// apply the parent's unroll-and-jam or this loop's unroll-and-jam. The560// UnrollAndJam pass processes loops from inner to outer, so we apply the561// inner first.562BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;563BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;564565// Set the inner followup metadata to process by the outer loop. Only566// consider the first inner loop.567if (!Parent->UnrollAndJamInnerFollowup) {568// Splitting the attributes into a BeforeJam and an AfterJam part will569// stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)570// to be forwarded to the AfterJam part. We detect the situation here and571// add it manually.572SmallVector<Metadata *, 1> BeforeLoopProperties;573if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||574BeforeJam.VectorizePredicateEnable != LoopAttributes::Unspecified ||575BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0 ||576BeforeJam.VectorizeScalable == LoopAttributes::Enable)577BeforeLoopProperties.push_back(578MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));579580bool InnerFollowupHasTransform = false;581MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,582InnerFollowupHasTransform);583if (InnerFollowupHasTransform)584Parent->UnrollAndJamInnerFollowup = InnerFollowup;585}586587CurLoopAttr = BeforeJam;588}589590bool HasUserTransforms = false;591LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);592TempLoopID->replaceAllUsesWith(LoopID);593}594595void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,596const llvm::DebugLoc &EndLoc) {597Active.emplace_back(598new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,599Active.empty() ? nullptr : Active.back().get()));600// Clear the attributes so nested loops do not inherit them.601StagedAttrs.clear();602}603604void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,605const clang::CodeGenOptions &CGOpts,606ArrayRef<const clang::Attr *> Attrs,607const llvm::DebugLoc &StartLoc,608const llvm::DebugLoc &EndLoc, bool MustProgress) {609// Identify loop hint attributes from Attrs.610for (const auto *Attr : Attrs) {611const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);612const OpenCLUnrollHintAttr *OpenCLHint =613dyn_cast<OpenCLUnrollHintAttr>(Attr);614const HLSLLoopHintAttr *HLSLLoopHint = dyn_cast<HLSLLoopHintAttr>(Attr);615// Skip non loop hint attributes616if (!LH && !OpenCLHint && !HLSLLoopHint) {617continue;618}619620LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;621LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;622unsigned ValueInt = 1;623// Translate opencl_unroll_hint attribute argument to624// equivalent LoopHintAttr enums.625// OpenCL v2.0 s6.11.5:626// 0 - enable unroll (no argument).627// 1 - disable unroll.628// other positive integer n - unroll by n.629if (OpenCLHint) {630ValueInt = OpenCLHint->getUnrollHint();631if (ValueInt == 0) {632State = LoopHintAttr::Enable;633} else if (ValueInt != 1) {634Option = LoopHintAttr::UnrollCount;635State = LoopHintAttr::Numeric;636}637} else if (HLSLLoopHint) {638ValueInt = HLSLLoopHint->getDirective();639if (HLSLLoopHint->getSemanticSpelling() ==640HLSLLoopHintAttr::Spelling::Microsoft_unroll) {641if (ValueInt == 0)642State = LoopHintAttr::Enable;643if (ValueInt > 0) {644Option = LoopHintAttr::UnrollCount;645State = LoopHintAttr::Numeric;646}647}648} else if (LH) {649auto *ValueExpr = LH->getValue();650if (ValueExpr) {651llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);652ValueInt = ValueAPS.getSExtValue();653}654655Option = LH->getOption();656State = LH->getState();657}658switch (State) {659case LoopHintAttr::Disable:660switch (Option) {661case LoopHintAttr::Vectorize:662// Disable vectorization by specifying a width of 1.663setVectorizeWidth(1);664setVectorizeScalable(LoopAttributes::Unspecified);665break;666case LoopHintAttr::Interleave:667// Disable interleaving by speciyfing a count of 1.668setInterleaveCount(1);669break;670case LoopHintAttr::Unroll:671setUnrollState(LoopAttributes::Disable);672break;673case LoopHintAttr::UnrollAndJam:674setUnrollAndJamState(LoopAttributes::Disable);675break;676case LoopHintAttr::VectorizePredicate:677setVectorizePredicateState(LoopAttributes::Disable);678break;679case LoopHintAttr::Distribute:680setDistributeState(false);681break;682case LoopHintAttr::PipelineDisabled:683setPipelineDisabled(true);684break;685case LoopHintAttr::UnrollCount:686case LoopHintAttr::UnrollAndJamCount:687case LoopHintAttr::VectorizeWidth:688case LoopHintAttr::InterleaveCount:689case LoopHintAttr::PipelineInitiationInterval:690llvm_unreachable("Options cannot be disabled.");691break;692}693break;694case LoopHintAttr::Enable:695switch (Option) {696case LoopHintAttr::Vectorize:697case LoopHintAttr::Interleave:698setVectorizeEnable(true);699break;700case LoopHintAttr::Unroll:701setUnrollState(LoopAttributes::Enable);702break;703case LoopHintAttr::UnrollAndJam:704setUnrollAndJamState(LoopAttributes::Enable);705break;706case LoopHintAttr::VectorizePredicate:707setVectorizePredicateState(LoopAttributes::Enable);708break;709case LoopHintAttr::Distribute:710setDistributeState(true);711break;712case LoopHintAttr::UnrollCount:713case LoopHintAttr::UnrollAndJamCount:714case LoopHintAttr::VectorizeWidth:715case LoopHintAttr::InterleaveCount:716case LoopHintAttr::PipelineDisabled:717case LoopHintAttr::PipelineInitiationInterval:718llvm_unreachable("Options cannot enabled.");719break;720}721break;722case LoopHintAttr::AssumeSafety:723switch (Option) {724case LoopHintAttr::Vectorize:725case LoopHintAttr::Interleave:726// Apply "llvm.mem.parallel_loop_access" metadata to load/stores.727setParallel(true);728setVectorizeEnable(true);729break;730case LoopHintAttr::Unroll:731case LoopHintAttr::UnrollAndJam:732case LoopHintAttr::VectorizePredicate:733case LoopHintAttr::UnrollCount:734case LoopHintAttr::UnrollAndJamCount:735case LoopHintAttr::VectorizeWidth:736case LoopHintAttr::InterleaveCount:737case LoopHintAttr::Distribute:738case LoopHintAttr::PipelineDisabled:739case LoopHintAttr::PipelineInitiationInterval:740llvm_unreachable("Options cannot be used to assume mem safety.");741break;742}743break;744case LoopHintAttr::Full:745switch (Option) {746case LoopHintAttr::Unroll:747setUnrollState(LoopAttributes::Full);748break;749case LoopHintAttr::UnrollAndJam:750setUnrollAndJamState(LoopAttributes::Full);751break;752case LoopHintAttr::Vectorize:753case LoopHintAttr::Interleave:754case LoopHintAttr::UnrollCount:755case LoopHintAttr::UnrollAndJamCount:756case LoopHintAttr::VectorizeWidth:757case LoopHintAttr::InterleaveCount:758case LoopHintAttr::Distribute:759case LoopHintAttr::PipelineDisabled:760case LoopHintAttr::PipelineInitiationInterval:761case LoopHintAttr::VectorizePredicate:762llvm_unreachable("Options cannot be used with 'full' hint.");763break;764}765break;766case LoopHintAttr::FixedWidth:767case LoopHintAttr::ScalableWidth:768switch (Option) {769case LoopHintAttr::VectorizeWidth:770setVectorizeScalable(State == LoopHintAttr::ScalableWidth771? LoopAttributes::Enable772: LoopAttributes::Disable);773if (LH->getValue())774setVectorizeWidth(ValueInt);775break;776default:777llvm_unreachable("Options cannot be used with 'scalable' hint.");778break;779}780break;781case LoopHintAttr::Numeric:782switch (Option) {783case LoopHintAttr::InterleaveCount:784setInterleaveCount(ValueInt);785break;786case LoopHintAttr::UnrollCount:787setUnrollCount(ValueInt);788break;789case LoopHintAttr::UnrollAndJamCount:790setUnrollAndJamCount(ValueInt);791break;792case LoopHintAttr::PipelineInitiationInterval:793setPipelineInitiationInterval(ValueInt);794break;795case LoopHintAttr::Unroll:796case LoopHintAttr::UnrollAndJam:797case LoopHintAttr::VectorizePredicate:798case LoopHintAttr::Vectorize:799case LoopHintAttr::VectorizeWidth:800case LoopHintAttr::Interleave:801case LoopHintAttr::Distribute:802case LoopHintAttr::PipelineDisabled:803llvm_unreachable("Options cannot be assigned a value.");804break;805}806break;807}808}809810// Identify loop attribute 'code_align' from Attrs.811// For attribute code_align:812// n - 'llvm.loop.align i32 n' metadata will be emitted.813if (const auto *CodeAlign = getSpecificAttr<const CodeAlignAttr>(Attrs)) {814const auto *CE = cast<ConstantExpr>(CodeAlign->getAlignment());815llvm::APSInt ArgVal = CE->getResultAsAPSInt();816setCodeAlign(ArgVal.getSExtValue());817}818819setMustProgress(MustProgress);820821if (CGOpts.OptimizationLevel > 0)822// Disable unrolling for the loop, if unrolling is disabled (via823// -fno-unroll-loops) and no pragmas override the decision.824if (!CGOpts.UnrollLoops &&825(StagedAttrs.UnrollEnable == LoopAttributes::Unspecified &&826StagedAttrs.UnrollCount == 0))827setUnrollState(LoopAttributes::Disable);828829/// Stage the attributes.830push(Header, StartLoc, EndLoc);831}832833void LoopInfoStack::pop() {834assert(!Active.empty() && "No active loops to pop");835Active.back()->finish();836Active.pop_back();837}838839void LoopInfoStack::InsertHelper(Instruction *I) const {840if (I->mayReadOrWriteMemory()) {841SmallVector<Metadata *, 4> AccessGroups;842for (const auto &AL : Active) {843// Here we assume that every loop that has an access group is parallel.844if (MDNode *Group = AL->getAccessGroup())845AccessGroups.push_back(Group);846}847MDNode *UnionMD = nullptr;848if (AccessGroups.size() == 1)849UnionMD = cast<MDNode>(AccessGroups[0]);850else if (AccessGroups.size() >= 2)851UnionMD = MDNode::get(I->getContext(), AccessGroups);852I->setMetadata("llvm.access.group", UnionMD);853}854855if (!hasInfo())856return;857858const LoopInfo &L = getInfo();859if (!L.getLoopID())860return;861862if (I->isTerminator()) {863for (BasicBlock *Succ : successors(I))864if (Succ == L.getHeader()) {865I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());866break;867}868return;869}870}871872873