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/Attr.h" 12 #include "clang/Sema/LoopHint.h" 13 #include "llvm/IR/BasicBlock.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 static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) { 22 23 if (!Attrs.IsParallel && Attrs.VectorizerWidth == 0 && 24 Attrs.VectorizerUnroll == 0 && 25 Attrs.VectorizerEnable == LoopAttributes::VecUnspecified) 26 return nullptr; 27 28 SmallVector<Metadata *, 4> Args; 29 // Reserve operand 0 for loop id self reference. 30 auto TempNode = MDNode::getTemporary(Ctx, None); 31 Args.push_back(TempNode.get()); 32 33 // Setting vectorizer.width 34 if (Attrs.VectorizerWidth > 0) { 35 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"), 36 ConstantAsMetadata::get(ConstantInt::get( 37 Type::getInt32Ty(Ctx), Attrs.VectorizerWidth))}; 38 Args.push_back(MDNode::get(Ctx, Vals)); 39 } 40 41 // Setting vectorizer.unroll 42 if (Attrs.VectorizerUnroll > 0) { 43 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"), 44 ConstantAsMetadata::get(ConstantInt::get( 45 Type::getInt32Ty(Ctx), Attrs.VectorizerUnroll))}; 46 Args.push_back(MDNode::get(Ctx, Vals)); 47 } 48 49 // Setting vectorizer.enable 50 if (Attrs.VectorizerEnable != LoopAttributes::VecUnspecified) { 51 Metadata *Vals[] = { 52 MDString::get(Ctx, "llvm.loop.vectorize.enable"), 53 ConstantAsMetadata::get(ConstantInt::get( 54 Type::getInt1Ty(Ctx), 55 (Attrs.VectorizerEnable == LoopAttributes::VecEnable)))}; 56 Args.push_back(MDNode::get(Ctx, Vals)); 57 } 58 59 // Set the first operand to itself. 60 MDNode *LoopID = MDNode::get(Ctx, Args); 61 LoopID->replaceOperandWith(0, LoopID); 62 return LoopID; 63 } 64 65 LoopAttributes::LoopAttributes(bool IsParallel) 66 : IsParallel(IsParallel), VectorizerEnable(LoopAttributes::VecUnspecified), 67 VectorizerWidth(0), VectorizerUnroll(0) {} 68 69 void LoopAttributes::clear() { 70 IsParallel = false; 71 VectorizerWidth = 0; 72 VectorizerUnroll = 0; 73 VectorizerEnable = LoopAttributes::VecUnspecified; 74 } 75 76 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs) 77 : LoopID(nullptr), Header(Header), Attrs(Attrs) { 78 LoopID = createMetadata(Header->getContext(), Attrs); 79 } 80 81 void LoopInfoStack::push(BasicBlock *Header, 82 ArrayRef<const clang::Attr *> Attrs) { 83 for (const auto *Attr : Attrs) { 84 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr); 85 86 // Skip non loop hint attributes 87 if (!LH) 88 continue; 89 90 LoopHintAttr::OptionType Option = LH->getOption(); 91 LoopHintAttr::LoopHintState State = LH->getState(); 92 switch (Option) { 93 case LoopHintAttr::Vectorize: 94 case LoopHintAttr::Interleave: 95 if (State == LoopHintAttr::AssumeSafety) { 96 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores. 97 setParallel(true); 98 } 99 break; 100 case LoopHintAttr::VectorizeWidth: 101 case LoopHintAttr::InterleaveCount: 102 case LoopHintAttr::Unroll: 103 case LoopHintAttr::UnrollCount: 104 // Nothing to do here for these loop hints. 105 break; 106 } 107 } 108 109 Active.push_back(LoopInfo(Header, StagedAttrs)); 110 // Clear the attributes so nested loops do not inherit them. 111 StagedAttrs.clear(); 112 } 113 114 void LoopInfoStack::pop() { 115 assert(!Active.empty() && "No active loops to pop"); 116 Active.pop_back(); 117 } 118 119 void LoopInfoStack::InsertHelper(Instruction *I) const { 120 if (!hasInfo()) 121 return; 122 123 const LoopInfo &L = getInfo(); 124 if (!L.getLoopID()) 125 return; 126 127 if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) { 128 for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i) 129 if (TI->getSuccessor(i) == L.getHeader()) { 130 TI->setMetadata("llvm.loop", L.getLoopID()); 131 break; 132 } 133 return; 134 } 135 136 if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory()) 137 I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID()); 138 } 139