Home | History | Annotate | Line # | Download | only in CodeGen
CGLoopInfo.cpp revision 1.1.1.1
      1 //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #include "CGLoopInfo.h"
     10 #include "clang/AST/ASTContext.h"
     11 #include "clang/AST/Attr.h"
     12 #include "llvm/IR/BasicBlock.h"
     13 #include "llvm/IR/CFG.h"
     14 #include "llvm/IR/Constants.h"
     15 #include "llvm/IR/InstrTypes.h"
     16 #include "llvm/IR/Instructions.h"
     17 #include "llvm/IR/Metadata.h"
     18 using namespace clang::CodeGen;
     19 using namespace llvm;
     20 
     21 MDNode *
     22 LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) {
     23   LLVMContext &Ctx = Header->getContext();
     24   SmallVector<Metadata *, 4> NewLoopProperties;
     25   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
     26   NewLoopProperties.push_back(TempNode.get());
     27   NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
     28 
     29   MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties);
     30   LoopID->replaceOperandWith(0, LoopID);
     31   return LoopID;
     32 }
     33 
     34 MDNode *LoopInfo::createPipeliningMetadata(const LoopAttributes &Attrs,
     35                                            ArrayRef<Metadata *> LoopProperties,
     36                                            bool &HasUserTransforms) {
     37   LLVMContext &Ctx = Header->getContext();
     38 
     39   Optional<bool> Enabled;
     40   if (Attrs.PipelineDisabled)
     41     Enabled = false;
     42   else if (Attrs.PipelineInitiationInterval != 0)
     43     Enabled = true;
     44 
     45   if (Enabled != true) {
     46     SmallVector<Metadata *, 4> NewLoopProperties;
     47     if (Enabled == false) {
     48       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
     49       NewLoopProperties.push_back(
     50           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"),
     51                             ConstantAsMetadata::get(ConstantInt::get(
     52                                 llvm::Type::getInt1Ty(Ctx), 1))}));
     53       LoopProperties = NewLoopProperties;
     54     }
     55     return createLoopPropertiesMetadata(LoopProperties);
     56   }
     57 
     58   SmallVector<Metadata *, 4> Args;
     59   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
     60   Args.push_back(TempNode.get());
     61   Args.append(LoopProperties.begin(), LoopProperties.end());
     62 
     63   if (Attrs.PipelineInitiationInterval > 0) {
     64     Metadata *Vals[] = {
     65         MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
     66         ConstantAsMetadata::get(ConstantInt::get(
     67             llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
     68     Args.push_back(MDNode::get(Ctx, Vals));
     69   }
     70 
     71   // No follow-up: This is the last transformation.
     72 
     73   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
     74   LoopID->replaceOperandWith(0, LoopID);
     75   HasUserTransforms = true;
     76   return LoopID;
     77 }
     78 
     79 MDNode *
     80 LoopInfo::createPartialUnrollMetadata(const LoopAttributes &Attrs,
     81                                       ArrayRef<Metadata *> LoopProperties,
     82                                       bool &HasUserTransforms) {
     83   LLVMContext &Ctx = Header->getContext();
     84 
     85   Optional<bool> Enabled;
     86   if (Attrs.UnrollEnable == LoopAttributes::Disable)
     87     Enabled = false;
     88   else if (Attrs.UnrollEnable == LoopAttributes::Full)
     89     Enabled = None;
     90   else if (Attrs.UnrollEnable != LoopAttributes::Unspecified ||
     91            Attrs.UnrollCount != 0)
     92     Enabled = true;
     93 
     94   if (Enabled != true) {
     95     // createFullUnrollMetadata will already have added llvm.loop.unroll.disable
     96     // if unrolling is disabled.
     97     return createPipeliningMetadata(Attrs, LoopProperties, HasUserTransforms);
     98   }
     99 
    100   SmallVector<Metadata *, 4> FollowupLoopProperties;
    101 
    102   // Apply all loop properties to the unrolled loop.
    103   FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
    104 
    105   // Don't unroll an already unrolled loop.
    106   FollowupLoopProperties.push_back(
    107       MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
    108 
    109   bool FollowupHasTransforms = false;
    110   MDNode *Followup = createPipeliningMetadata(Attrs, FollowupLoopProperties,
    111                                               FollowupHasTransforms);
    112 
    113   SmallVector<Metadata *, 4> Args;
    114   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
    115   Args.push_back(TempNode.get());
    116   Args.append(LoopProperties.begin(), LoopProperties.end());
    117 
    118   // Setting unroll.count
    119   if (Attrs.UnrollCount > 0) {
    120     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
    121                         ConstantAsMetadata::get(ConstantInt::get(
    122                             llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
    123     Args.push_back(MDNode::get(Ctx, Vals));
    124   }
    125 
    126   // Setting unroll.full or unroll.disable
    127   if (Attrs.UnrollEnable == LoopAttributes::Enable) {
    128     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")};
    129     Args.push_back(MDNode::get(Ctx, Vals));
    130   }
    131 
    132   if (FollowupHasTransforms)
    133     Args.push_back(MDNode::get(
    134         Ctx, {MDString::get(Ctx, "llvm.loop.unroll.followup_all"), Followup}));
    135 
    136   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
    137   LoopID->replaceOperandWith(0, LoopID);
    138   HasUserTransforms = true;
    139   return LoopID;
    140 }
    141 
    142 MDNode *
    143 LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs,
    144                                      ArrayRef<Metadata *> LoopProperties,
    145                                      bool &HasUserTransforms) {
    146   LLVMContext &Ctx = Header->getContext();
    147 
    148   Optional<bool> Enabled;
    149   if (Attrs.UnrollAndJamEnable == LoopAttributes::Disable)
    150     Enabled = false;
    151   else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable ||
    152            Attrs.UnrollAndJamCount != 0)
    153     Enabled = true;
    154 
    155   if (Enabled != true) {
    156     SmallVector<Metadata *, 4> NewLoopProperties;
    157     if (Enabled == false) {
    158       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
    159       NewLoopProperties.push_back(MDNode::get(
    160           Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
    161       LoopProperties = NewLoopProperties;
    162     }
    163     return createPartialUnrollMetadata(Attrs, LoopProperties,
    164                                        HasUserTransforms);
    165   }
    166 
    167   SmallVector<Metadata *, 4> FollowupLoopProperties;
    168   FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
    169   FollowupLoopProperties.push_back(
    170       MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
    171 
    172   bool FollowupHasTransforms = false;
    173   MDNode *Followup = createPartialUnrollMetadata(Attrs, FollowupLoopProperties,
    174                                                  FollowupHasTransforms);
    175 
    176   SmallVector<Metadata *, 4> Args;
    177   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
    178   Args.push_back(TempNode.get());
    179   Args.append(LoopProperties.begin(), LoopProperties.end());
    180 
    181   // Setting unroll_and_jam.count
    182   if (Attrs.UnrollAndJamCount > 0) {
    183     Metadata *Vals[] = {
    184         MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
    185         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
    186                                                  Attrs.UnrollAndJamCount))};
    187     Args.push_back(MDNode::get(Ctx, Vals));
    188   }
    189 
    190   if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) {
    191     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")};
    192     Args.push_back(MDNode::get(Ctx, Vals));
    193   }
    194 
    195   if (FollowupHasTransforms)
    196     Args.push_back(MDNode::get(
    197         Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_outer"),
    198               Followup}));
    199 
    200   if (UnrollAndJamInnerFollowup)
    201     Args.push_back(MDNode::get(
    202         Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_inner"),
    203               UnrollAndJamInnerFollowup}));
    204 
    205   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
    206   LoopID->replaceOperandWith(0, LoopID);
    207   HasUserTransforms = true;
    208   return LoopID;
    209 }
    210 
    211 MDNode *
    212 LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs,
    213                                       ArrayRef<Metadata *> LoopProperties,
    214                                       bool &HasUserTransforms) {
    215   LLVMContext &Ctx = Header->getContext();
    216 
    217   Optional<bool> Enabled;
    218   if (Attrs.VectorizeEnable == LoopAttributes::Disable)
    219     Enabled = false;
    220   else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
    221            Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified ||
    222            Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0)
    223     Enabled = true;
    224 
    225   if (Enabled != true) {
    226     SmallVector<Metadata *, 4> NewLoopProperties;
    227     if (Enabled == false) {
    228       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
    229       NewLoopProperties.push_back(
    230           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
    231                             ConstantAsMetadata::get(ConstantInt::get(
    232                                 llvm::Type::getInt1Ty(Ctx), 0))}));
    233       LoopProperties = NewLoopProperties;
    234     }
    235     return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms);
    236   }
    237 
    238   // Apply all loop properties to the vectorized loop.
    239   SmallVector<Metadata *, 4> FollowupLoopProperties;
    240   FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
    241 
    242   // Don't vectorize an already vectorized loop.
    243   FollowupLoopProperties.push_back(
    244       MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
    245 
    246   bool FollowupHasTransforms = false;
    247   MDNode *Followup = createUnrollAndJamMetadata(Attrs, FollowupLoopProperties,
    248                                                 FollowupHasTransforms);
    249 
    250   SmallVector<Metadata *, 4> Args;
    251   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
    252   Args.push_back(TempNode.get());
    253   Args.append(LoopProperties.begin(), LoopProperties.end());
    254 
    255   // Setting vectorize.predicate
    256   bool IsVectorPredicateEnabled = false;
    257   if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified &&
    258       Attrs.VectorizeEnable != LoopAttributes::Disable &&
    259       Attrs.VectorizeWidth < 1) {
    260 
    261     IsVectorPredicateEnabled =
    262         (Attrs.VectorizePredicateEnable == LoopAttributes::Enable);
    263 
    264     Metadata *Vals[] = {
    265         MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"),
    266         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx),
    267                                                  IsVectorPredicateEnabled))};
    268     Args.push_back(MDNode::get(Ctx, Vals));
    269   }
    270 
    271   // Setting vectorize.width
    272   if (Attrs.VectorizeWidth > 0) {
    273     Metadata *Vals[] = {
    274         MDString::get(Ctx, "llvm.loop.vectorize.width"),
    275         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
    276                                                  Attrs.VectorizeWidth))};
    277     Args.push_back(MDNode::get(Ctx, Vals));
    278   }
    279 
    280   // Setting interleave.count
    281   if (Attrs.InterleaveCount > 0) {
    282     Metadata *Vals[] = {
    283         MDString::get(Ctx, "llvm.loop.interleave.count"),
    284         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
    285                                                  Attrs.InterleaveCount))};
    286     Args.push_back(MDNode::get(Ctx, Vals));
    287   }
    288 
    289   // Setting vectorize.enable
    290   if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
    291       IsVectorPredicateEnabled) {
    292     Metadata *Vals[] = {
    293         MDString::get(Ctx, "llvm.loop.vectorize.enable"),
    294         ConstantAsMetadata::get(ConstantInt::get(
    295             llvm::Type::getInt1Ty(Ctx),
    296             IsVectorPredicateEnabled
    297                 ? true
    298                 : (Attrs.VectorizeEnable == LoopAttributes::Enable)))};
    299     Args.push_back(MDNode::get(Ctx, Vals));
    300   }
    301 
    302   if (FollowupHasTransforms)
    303     Args.push_back(MDNode::get(
    304         Ctx,
    305         {MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup}));
    306 
    307   MDNode *LoopID = MDNode::get(Ctx, Args);
    308   LoopID->replaceOperandWith(0, LoopID);
    309   HasUserTransforms = true;
    310   return LoopID;
    311 }
    312 
    313 MDNode *
    314 LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs,
    315                                        ArrayRef<Metadata *> LoopProperties,
    316                                        bool &HasUserTransforms) {
    317   LLVMContext &Ctx = Header->getContext();
    318 
    319   Optional<bool> Enabled;
    320   if (Attrs.DistributeEnable == LoopAttributes::Disable)
    321     Enabled = false;
    322   if (Attrs.DistributeEnable == LoopAttributes::Enable)
    323     Enabled = true;
    324 
    325   if (Enabled != true) {
    326     SmallVector<Metadata *, 4> NewLoopProperties;
    327     if (Enabled == false) {
    328       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
    329       NewLoopProperties.push_back(
    330           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),
    331                             ConstantAsMetadata::get(ConstantInt::get(
    332                                 llvm::Type::getInt1Ty(Ctx), 0))}));
    333       LoopProperties = NewLoopProperties;
    334     }
    335     return createLoopVectorizeMetadata(Attrs, LoopProperties,
    336                                        HasUserTransforms);
    337   }
    338 
    339   bool FollowupHasTransforms = false;
    340   MDNode *Followup =
    341       createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);
    342 
    343   SmallVector<Metadata *, 4> Args;
    344   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
    345   Args.push_back(TempNode.get());
    346   Args.append(LoopProperties.begin(), LoopProperties.end());
    347 
    348   Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
    349                       ConstantAsMetadata::get(ConstantInt::get(
    350                           llvm::Type::getInt1Ty(Ctx),
    351                           (Attrs.DistributeEnable == LoopAttributes::Enable)))};
    352   Args.push_back(MDNode::get(Ctx, Vals));
    353 
    354   if (FollowupHasTransforms)
    355     Args.push_back(MDNode::get(
    356         Ctx,
    357         {MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup}));
    358 
    359   MDNode *LoopID = MDNode::get(Ctx, Args);
    360   LoopID->replaceOperandWith(0, LoopID);
    361   HasUserTransforms = true;
    362   return LoopID;
    363 }
    364 
    365 MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,
    366                                            ArrayRef<Metadata *> LoopProperties,
    367                                            bool &HasUserTransforms) {
    368   LLVMContext &Ctx = Header->getContext();
    369 
    370   Optional<bool> Enabled;
    371   if (Attrs.UnrollEnable == LoopAttributes::Disable)
    372     Enabled = false;
    373   else if (Attrs.UnrollEnable == LoopAttributes::Full)
    374     Enabled = true;
    375 
    376   if (Enabled != true) {
    377     SmallVector<Metadata *, 4> NewLoopProperties;
    378     if (Enabled == false) {
    379       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
    380       NewLoopProperties.push_back(
    381           MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
    382       LoopProperties = NewLoopProperties;
    383     }
    384     return createLoopDistributeMetadata(Attrs, LoopProperties,
    385                                         HasUserTransforms);
    386   }
    387 
    388   SmallVector<Metadata *, 4> Args;
    389   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
    390   Args.push_back(TempNode.get());
    391   Args.append(LoopProperties.begin(), LoopProperties.end());
    392   Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));
    393 
    394   // No follow-up: there is no loop after full unrolling.
    395   // TODO: Warn if there are transformations after full unrolling.
    396 
    397   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
    398   LoopID->replaceOperandWith(0, LoopID);
    399   HasUserTransforms = true;
    400   return LoopID;
    401 }
    402 
    403 MDNode *LoopInfo::createMetadata(
    404     const LoopAttributes &Attrs,
    405     llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,
    406     bool &HasUserTransforms) {
    407   SmallVector<Metadata *, 3> LoopProperties;
    408 
    409   // If we have a valid start debug location for the loop, add it.
    410   if (StartLoc) {
    411     LoopProperties.push_back(StartLoc.getAsMDNode());
    412 
    413     // If we also have a valid end debug location for the loop, add it.
    414     if (EndLoc)
    415       LoopProperties.push_back(EndLoc.getAsMDNode());
    416   }
    417 
    418   assert(!!AccGroup == Attrs.IsParallel &&
    419          "There must be an access group iff the loop is parallel");
    420   if (Attrs.IsParallel) {
    421     LLVMContext &Ctx = Header->getContext();
    422     LoopProperties.push_back(MDNode::get(
    423         Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
    424   }
    425 
    426   LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
    427                         AdditionalLoopProperties.end());
    428   return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
    429 }
    430 
    431 LoopAttributes::LoopAttributes(bool IsParallel)
    432     : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
    433       UnrollEnable(LoopAttributes::Unspecified),
    434       UnrollAndJamEnable(LoopAttributes::Unspecified),
    435       VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
    436       InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0),
    437       DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
    438       PipelineInitiationInterval(0) {}
    439 
    440 void LoopAttributes::clear() {
    441   IsParallel = false;
    442   VectorizeWidth = 0;
    443   InterleaveCount = 0;
    444   UnrollCount = 0;
    445   UnrollAndJamCount = 0;
    446   VectorizeEnable = LoopAttributes::Unspecified;
    447   UnrollEnable = LoopAttributes::Unspecified;
    448   UnrollAndJamEnable = LoopAttributes::Unspecified;
    449   VectorizePredicateEnable = LoopAttributes::Unspecified;
    450   DistributeEnable = LoopAttributes::Unspecified;
    451   PipelineDisabled = false;
    452   PipelineInitiationInterval = 0;
    453 }
    454 
    455 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
    456                    const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
    457                    LoopInfo *Parent)
    458     : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
    459       Parent(Parent) {
    460 
    461   if (Attrs.IsParallel) {
    462     // Create an access group for this loop.
    463     LLVMContext &Ctx = Header->getContext();
    464     AccGroup = MDNode::getDistinct(Ctx, {});
    465   }
    466 
    467   if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
    468       Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
    469       Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
    470       Attrs.PipelineInitiationInterval == 0 &&
    471       Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified &&
    472       Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
    473       Attrs.UnrollEnable == LoopAttributes::Unspecified &&
    474       Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
    475       Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
    476       !EndLoc)
    477     return;
    478 
    479   TempLoopID = MDNode::getTemporary(Header->getContext(), None);
    480 }
    481 
    482 void LoopInfo::finish() {
    483   // We did not annotate the loop body instructions because there are no
    484   // attributes for this loop.
    485   if (!TempLoopID)
    486     return;
    487 
    488   MDNode *LoopID;
    489   LoopAttributes CurLoopAttr = Attrs;
    490   LLVMContext &Ctx = Header->getContext();
    491 
    492   if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
    493                  Parent->Attrs.UnrollAndJamCount != 0)) {
    494     // Parent unroll-and-jams this loop.
    495     // Split the transformations in those that happens before the unroll-and-jam
    496     // and those after.
    497 
    498     LoopAttributes BeforeJam, AfterJam;
    499 
    500     BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
    501 
    502     BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
    503     BeforeJam.InterleaveCount = Attrs.InterleaveCount;
    504     BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
    505     BeforeJam.DistributeEnable = Attrs.DistributeEnable;
    506     BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
    507 
    508     switch (Attrs.UnrollEnable) {
    509     case LoopAttributes::Unspecified:
    510     case LoopAttributes::Disable:
    511       BeforeJam.UnrollEnable = Attrs.UnrollEnable;
    512       AfterJam.UnrollEnable = Attrs.UnrollEnable;
    513       break;
    514     case LoopAttributes::Full:
    515       BeforeJam.UnrollEnable = LoopAttributes::Full;
    516       break;
    517     case LoopAttributes::Enable:
    518       AfterJam.UnrollEnable = LoopAttributes::Enable;
    519       break;
    520     }
    521 
    522     AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
    523     AfterJam.UnrollCount = Attrs.UnrollCount;
    524     AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
    525     AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;
    526 
    527     // If this loop is subject of an unroll-and-jam by the parent loop, and has
    528     // an unroll-and-jam annotation itself, we have to decide whether to first
    529     // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
    530     // UnrollAndJam pass processes loops from inner to outer, so we apply the
    531     // inner first.
    532     BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
    533     BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
    534 
    535     // Set the inner followup metadata to process by the outer loop. Only
    536     // consider the first inner loop.
    537     if (!Parent->UnrollAndJamInnerFollowup) {
    538       // Splitting the attributes into a BeforeJam and an AfterJam part will
    539       // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
    540       // to be forwarded to the AfterJam part. We detect the situation here and
    541       // add it manually.
    542       SmallVector<Metadata *, 1> BeforeLoopProperties;
    543       if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||
    544           BeforeJam.VectorizePredicateEnable != LoopAttributes::Unspecified ||
    545           BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0)
    546         BeforeLoopProperties.push_back(
    547             MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
    548 
    549       bool InnerFollowupHasTransform = false;
    550       MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,
    551                                              InnerFollowupHasTransform);
    552       if (InnerFollowupHasTransform)
    553         Parent->UnrollAndJamInnerFollowup = InnerFollowup;
    554     }
    555 
    556     CurLoopAttr = BeforeJam;
    557   }
    558 
    559   bool HasUserTransforms = false;
    560   LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);
    561   TempLoopID->replaceAllUsesWith(LoopID);
    562 }
    563 
    564 void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
    565                          const llvm::DebugLoc &EndLoc) {
    566   Active.emplace_back(
    567       new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
    568                    Active.empty() ? nullptr : Active.back().get()));
    569   // Clear the attributes so nested loops do not inherit them.
    570   StagedAttrs.clear();
    571 }
    572 
    573 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
    574                          ArrayRef<const clang::Attr *> Attrs,
    575                          const llvm::DebugLoc &StartLoc,
    576                          const llvm::DebugLoc &EndLoc) {
    577 
    578   // Identify loop hint attributes from Attrs.
    579   for (const auto *Attr : Attrs) {
    580     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
    581     const OpenCLUnrollHintAttr *OpenCLHint =
    582         dyn_cast<OpenCLUnrollHintAttr>(Attr);
    583 
    584     // Skip non loop hint attributes
    585     if (!LH && !OpenCLHint) {
    586       continue;
    587     }
    588 
    589     LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
    590     LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
    591     unsigned ValueInt = 1;
    592     // Translate opencl_unroll_hint attribute argument to
    593     // equivalent LoopHintAttr enums.
    594     // OpenCL v2.0 s6.11.5:
    595     // 0 - enable unroll (no argument).
    596     // 1 - disable unroll.
    597     // other positive integer n - unroll by n.
    598     if (OpenCLHint) {
    599       ValueInt = OpenCLHint->getUnrollHint();
    600       if (ValueInt == 0) {
    601         State = LoopHintAttr::Enable;
    602       } else if (ValueInt != 1) {
    603         Option = LoopHintAttr::UnrollCount;
    604         State = LoopHintAttr::Numeric;
    605       }
    606     } else if (LH) {
    607       auto *ValueExpr = LH->getValue();
    608       if (ValueExpr) {
    609         llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
    610         ValueInt = ValueAPS.getSExtValue();
    611       }
    612 
    613       Option = LH->getOption();
    614       State = LH->getState();
    615     }
    616     switch (State) {
    617     case LoopHintAttr::Disable:
    618       switch (Option) {
    619       case LoopHintAttr::Vectorize:
    620         // Disable vectorization by specifying a width of 1.
    621         setVectorizeWidth(1);
    622         break;
    623       case LoopHintAttr::Interleave:
    624         // Disable interleaving by speciyfing a count of 1.
    625         setInterleaveCount(1);
    626         break;
    627       case LoopHintAttr::Unroll:
    628         setUnrollState(LoopAttributes::Disable);
    629         break;
    630       case LoopHintAttr::UnrollAndJam:
    631         setUnrollAndJamState(LoopAttributes::Disable);
    632         break;
    633       case LoopHintAttr::VectorizePredicate:
    634         setVectorizePredicateState(LoopAttributes::Disable);
    635         break;
    636       case LoopHintAttr::Distribute:
    637         setDistributeState(false);
    638         break;
    639       case LoopHintAttr::PipelineDisabled:
    640         setPipelineDisabled(true);
    641         break;
    642       case LoopHintAttr::UnrollCount:
    643       case LoopHintAttr::UnrollAndJamCount:
    644       case LoopHintAttr::VectorizeWidth:
    645       case LoopHintAttr::InterleaveCount:
    646       case LoopHintAttr::PipelineInitiationInterval:
    647         llvm_unreachable("Options cannot be disabled.");
    648         break;
    649       }
    650       break;
    651     case LoopHintAttr::Enable:
    652       switch (Option) {
    653       case LoopHintAttr::Vectorize:
    654       case LoopHintAttr::Interleave:
    655         setVectorizeEnable(true);
    656         break;
    657       case LoopHintAttr::Unroll:
    658         setUnrollState(LoopAttributes::Enable);
    659         break;
    660       case LoopHintAttr::UnrollAndJam:
    661         setUnrollAndJamState(LoopAttributes::Enable);
    662         break;
    663       case LoopHintAttr::VectorizePredicate:
    664         setVectorizePredicateState(LoopAttributes::Enable);
    665         break;
    666       case LoopHintAttr::Distribute:
    667         setDistributeState(true);
    668         break;
    669       case LoopHintAttr::UnrollCount:
    670       case LoopHintAttr::UnrollAndJamCount:
    671       case LoopHintAttr::VectorizeWidth:
    672       case LoopHintAttr::InterleaveCount:
    673       case LoopHintAttr::PipelineDisabled:
    674       case LoopHintAttr::PipelineInitiationInterval:
    675         llvm_unreachable("Options cannot enabled.");
    676         break;
    677       }
    678       break;
    679     case LoopHintAttr::AssumeSafety:
    680       switch (Option) {
    681       case LoopHintAttr::Vectorize:
    682       case LoopHintAttr::Interleave:
    683         // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
    684         setParallel(true);
    685         setVectorizeEnable(true);
    686         break;
    687       case LoopHintAttr::Unroll:
    688       case LoopHintAttr::UnrollAndJam:
    689       case LoopHintAttr::VectorizePredicate:
    690       case LoopHintAttr::UnrollCount:
    691       case LoopHintAttr::UnrollAndJamCount:
    692       case LoopHintAttr::VectorizeWidth:
    693       case LoopHintAttr::InterleaveCount:
    694       case LoopHintAttr::Distribute:
    695       case LoopHintAttr::PipelineDisabled:
    696       case LoopHintAttr::PipelineInitiationInterval:
    697         llvm_unreachable("Options cannot be used to assume mem safety.");
    698         break;
    699       }
    700       break;
    701     case LoopHintAttr::Full:
    702       switch (Option) {
    703       case LoopHintAttr::Unroll:
    704         setUnrollState(LoopAttributes::Full);
    705         break;
    706       case LoopHintAttr::UnrollAndJam:
    707         setUnrollAndJamState(LoopAttributes::Full);
    708         break;
    709       case LoopHintAttr::Vectorize:
    710       case LoopHintAttr::Interleave:
    711       case LoopHintAttr::UnrollCount:
    712       case LoopHintAttr::UnrollAndJamCount:
    713       case LoopHintAttr::VectorizeWidth:
    714       case LoopHintAttr::InterleaveCount:
    715       case LoopHintAttr::Distribute:
    716       case LoopHintAttr::PipelineDisabled:
    717       case LoopHintAttr::PipelineInitiationInterval:
    718       case LoopHintAttr::VectorizePredicate:
    719         llvm_unreachable("Options cannot be used with 'full' hint.");
    720         break;
    721       }
    722       break;
    723     case LoopHintAttr::Numeric:
    724       switch (Option) {
    725       case LoopHintAttr::VectorizeWidth:
    726         setVectorizeWidth(ValueInt);
    727         break;
    728       case LoopHintAttr::InterleaveCount:
    729         setInterleaveCount(ValueInt);
    730         break;
    731       case LoopHintAttr::UnrollCount:
    732         setUnrollCount(ValueInt);
    733         break;
    734       case LoopHintAttr::UnrollAndJamCount:
    735         setUnrollAndJamCount(ValueInt);
    736         break;
    737       case LoopHintAttr::PipelineInitiationInterval:
    738         setPipelineInitiationInterval(ValueInt);
    739         break;
    740       case LoopHintAttr::Unroll:
    741       case LoopHintAttr::UnrollAndJam:
    742       case LoopHintAttr::VectorizePredicate:
    743       case LoopHintAttr::Vectorize:
    744       case LoopHintAttr::Interleave:
    745       case LoopHintAttr::Distribute:
    746       case LoopHintAttr::PipelineDisabled:
    747         llvm_unreachable("Options cannot be assigned a value.");
    748         break;
    749       }
    750       break;
    751     }
    752   }
    753 
    754   /// Stage the attributes.
    755   push(Header, StartLoc, EndLoc);
    756 }
    757 
    758 void LoopInfoStack::pop() {
    759   assert(!Active.empty() && "No active loops to pop");
    760   Active.back()->finish();
    761   Active.pop_back();
    762 }
    763 
    764 void LoopInfoStack::InsertHelper(Instruction *I) const {
    765   if (I->mayReadOrWriteMemory()) {
    766     SmallVector<Metadata *, 4> AccessGroups;
    767     for (const auto &AL : Active) {
    768       // Here we assume that every loop that has an access group is parallel.
    769       if (MDNode *Group = AL->getAccessGroup())
    770         AccessGroups.push_back(Group);
    771     }
    772     MDNode *UnionMD = nullptr;
    773     if (AccessGroups.size() == 1)
    774       UnionMD = cast<MDNode>(AccessGroups[0]);
    775     else if (AccessGroups.size() >= 2)
    776       UnionMD = MDNode::get(I->getContext(), AccessGroups);
    777     I->setMetadata("llvm.access.group", UnionMD);
    778   }
    779 
    780   if (!hasInfo())
    781     return;
    782 
    783   const LoopInfo &L = getInfo();
    784   if (!L.getLoopID())
    785     return;
    786 
    787   if (I->isTerminator()) {
    788     for (BasicBlock *Succ : successors(I))
    789       if (Succ == L.getHeader()) {
    790         I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
    791         break;
    792       }
    793     return;
    794   }
    795 }
    796