Home | History | Annotate | Download | only in CodeGen
      1 //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "CGLoopInfo.h"
     11 #include "clang/AST/ASTContext.h"
     12 #include "clang/AST/Attr.h"
     13 #include "clang/Sema/LoopHint.h"
     14 #include "llvm/IR/BasicBlock.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 using namespace clang::CodeGen;
     20 using namespace llvm;
     21 
     22 static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
     23 
     24   if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
     25       Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
     26       Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
     27       Attrs.UnrollEnable == LoopAttributes::Unspecified)
     28     return nullptr;
     29 
     30   SmallVector<Metadata *, 4> Args;
     31   // Reserve operand 0 for loop id self reference.
     32   auto TempNode = MDNode::getTemporary(Ctx, None);
     33   Args.push_back(TempNode.get());
     34 
     35   // Setting vectorize.width
     36   if (Attrs.VectorizeWidth > 0) {
     37     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
     38                         ConstantAsMetadata::get(ConstantInt::get(
     39                             Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
     40     Args.push_back(MDNode::get(Ctx, Vals));
     41   }
     42 
     43   // Setting interleave.count
     44   if (Attrs.InterleaveCount > 0) {
     45     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
     46                         ConstantAsMetadata::get(ConstantInt::get(
     47                             Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
     48     Args.push_back(MDNode::get(Ctx, Vals));
     49   }
     50 
     51   // Setting interleave.count
     52   if (Attrs.UnrollCount > 0) {
     53     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
     54                         ConstantAsMetadata::get(ConstantInt::get(
     55                             Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
     56     Args.push_back(MDNode::get(Ctx, Vals));
     57   }
     58 
     59   // Setting vectorize.enable
     60   if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
     61     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
     62                         ConstantAsMetadata::get(ConstantInt::get(
     63                             Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable ==
     64                                                    LoopAttributes::Enable)))};
     65     Args.push_back(MDNode::get(Ctx, Vals));
     66   }
     67 
     68   // Setting unroll.full or unroll.disable
     69   if (Attrs.UnrollEnable != LoopAttributes::Unspecified) {
     70     std::string Name;
     71     if (Attrs.UnrollEnable == LoopAttributes::Enable)
     72       Name = "llvm.loop.unroll.enable";
     73     else if (Attrs.UnrollEnable == LoopAttributes::Full)
     74       Name = "llvm.loop.unroll.full";
     75     else
     76       Name = "llvm.loop.unroll.disable";
     77     Metadata *Vals[] = {MDString::get(Ctx, Name)};
     78     Args.push_back(MDNode::get(Ctx, Vals));
     79   }
     80 
     81   // Set the first operand to itself.
     82   MDNode *LoopID = MDNode::get(Ctx, Args);
     83   LoopID->replaceOperandWith(0, LoopID);
     84   return LoopID;
     85 }
     86 
     87 LoopAttributes::LoopAttributes(bool IsParallel)
     88     : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
     89       UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
     90       InterleaveCount(0), UnrollCount(0) {}
     91 
     92 void LoopAttributes::clear() {
     93   IsParallel = false;
     94   VectorizeWidth = 0;
     95   InterleaveCount = 0;
     96   UnrollCount = 0;
     97   VectorizeEnable = LoopAttributes::Unspecified;
     98   UnrollEnable = LoopAttributes::Unspecified;
     99 }
    100 
    101 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
    102     : LoopID(nullptr), Header(Header), Attrs(Attrs) {
    103   LoopID = createMetadata(Header->getContext(), Attrs);
    104 }
    105 
    106 void LoopInfoStack::push(BasicBlock *Header) {
    107   Active.push_back(LoopInfo(Header, StagedAttrs));
    108   // Clear the attributes so nested loops do not inherit them.
    109   StagedAttrs.clear();
    110 }
    111 
    112 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
    113                          ArrayRef<const clang::Attr *> Attrs) {
    114 
    115   // Identify loop hint attributes from Attrs.
    116   for (const auto *Attr : Attrs) {
    117     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
    118 
    119     // Skip non loop hint attributes
    120     if (!LH)
    121       continue;
    122 
    123     auto *ValueExpr = LH->getValue();
    124     unsigned ValueInt = 1;
    125     if (ValueExpr) {
    126       llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
    127       ValueInt = ValueAPS.getSExtValue();
    128     }
    129 
    130     LoopHintAttr::OptionType Option = LH->getOption();
    131     LoopHintAttr::LoopHintState State = LH->getState();
    132     switch (State) {
    133     case LoopHintAttr::Disable:
    134       switch (Option) {
    135       case LoopHintAttr::Vectorize:
    136         // Disable vectorization by specifying a width of 1.
    137         setVectorizeWidth(1);
    138         break;
    139       case LoopHintAttr::Interleave:
    140         // Disable interleaving by speciyfing a count of 1.
    141         setInterleaveCount(1);
    142         break;
    143       case LoopHintAttr::Unroll:
    144         setUnrollState(LoopAttributes::Disable);
    145         break;
    146       case LoopHintAttr::UnrollCount:
    147       case LoopHintAttr::VectorizeWidth:
    148       case LoopHintAttr::InterleaveCount:
    149         llvm_unreachable("Options cannot be disabled.");
    150         break;
    151       }
    152       break;
    153     case LoopHintAttr::Enable:
    154       switch (Option) {
    155       case LoopHintAttr::Vectorize:
    156       case LoopHintAttr::Interleave:
    157         setVectorizeEnable(true);
    158         break;
    159       case LoopHintAttr::Unroll:
    160         setUnrollState(LoopAttributes::Enable);
    161         break;
    162       case LoopHintAttr::UnrollCount:
    163       case LoopHintAttr::VectorizeWidth:
    164       case LoopHintAttr::InterleaveCount:
    165         llvm_unreachable("Options cannot enabled.");
    166         break;
    167       }
    168       break;
    169     case LoopHintAttr::AssumeSafety:
    170       switch (Option) {
    171       case LoopHintAttr::Vectorize:
    172       case LoopHintAttr::Interleave:
    173         // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
    174         setParallel(true);
    175         setVectorizeEnable(true);
    176         break;
    177       case LoopHintAttr::Unroll:
    178       case LoopHintAttr::UnrollCount:
    179       case LoopHintAttr::VectorizeWidth:
    180       case LoopHintAttr::InterleaveCount:
    181         llvm_unreachable("Options cannot be used to assume mem safety.");
    182         break;
    183       }
    184       break;
    185     case LoopHintAttr::Full:
    186       switch (Option) {
    187       case LoopHintAttr::Unroll:
    188         setUnrollState(LoopAttributes::Full);
    189         break;
    190       case LoopHintAttr::Vectorize:
    191       case LoopHintAttr::Interleave:
    192       case LoopHintAttr::UnrollCount:
    193       case LoopHintAttr::VectorizeWidth:
    194       case LoopHintAttr::InterleaveCount:
    195         llvm_unreachable("Options cannot be used with 'full' hint.");
    196         break;
    197       }
    198       break;
    199     case LoopHintAttr::Numeric:
    200       switch (Option) {
    201       case LoopHintAttr::VectorizeWidth:
    202         setVectorizeWidth(ValueInt);
    203         break;
    204       case LoopHintAttr::InterleaveCount:
    205         setInterleaveCount(ValueInt);
    206         break;
    207       case LoopHintAttr::UnrollCount:
    208         setUnrollCount(ValueInt);
    209         break;
    210       case LoopHintAttr::Unroll:
    211       case LoopHintAttr::Vectorize:
    212       case LoopHintAttr::Interleave:
    213         llvm_unreachable("Options cannot be assigned a value.");
    214         break;
    215       }
    216       break;
    217     }
    218   }
    219 
    220   /// Stage the attributes.
    221   push(Header);
    222 }
    223 
    224 void LoopInfoStack::pop() {
    225   assert(!Active.empty() && "No active loops to pop");
    226   Active.pop_back();
    227 }
    228 
    229 void LoopInfoStack::InsertHelper(Instruction *I) const {
    230   if (!hasInfo())
    231     return;
    232 
    233   const LoopInfo &L = getInfo();
    234   if (!L.getLoopID())
    235     return;
    236 
    237   if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
    238     for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
    239       if (TI->getSuccessor(i) == L.getHeader()) {
    240         TI->setMetadata("llvm.loop", L.getLoopID());
    241         break;
    242       }
    243     return;
    244   }
    245 
    246   if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
    247     I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
    248 }
    249