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 Metadata *Vals[] = { 71 MDString::get(Ctx, (Attrs.UnrollEnable == LoopAttributes::Enable 72 ? "llvm.loop.unroll.full" 73 : "llvm.loop.unroll.disable"))}; 74 Args.push_back(MDNode::get(Ctx, Vals)); 75 } 76 77 // Set the first operand to itself. 78 MDNode *LoopID = MDNode::get(Ctx, Args); 79 LoopID->replaceOperandWith(0, LoopID); 80 return LoopID; 81 } 82 83 LoopAttributes::LoopAttributes(bool IsParallel) 84 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified), 85 UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0), 86 InterleaveCount(0), UnrollCount(0) {} 87 88 void LoopAttributes::clear() { 89 IsParallel = false; 90 VectorizeWidth = 0; 91 InterleaveCount = 0; 92 UnrollCount = 0; 93 VectorizeEnable = LoopAttributes::Unspecified; 94 UnrollEnable = LoopAttributes::Unspecified; 95 } 96 97 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs) 98 : LoopID(nullptr), Header(Header), Attrs(Attrs) { 99 LoopID = createMetadata(Header->getContext(), Attrs); 100 } 101 102 void LoopInfoStack::push(BasicBlock *Header) { 103 Active.push_back(LoopInfo(Header, StagedAttrs)); 104 // Clear the attributes so nested loops do not inherit them. 105 StagedAttrs.clear(); 106 } 107 108 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, 109 ArrayRef<const clang::Attr *> Attrs) { 110 111 // Identify loop hint attributes from Attrs. 112 for (const auto *Attr : Attrs) { 113 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr); 114 115 // Skip non loop hint attributes 116 if (!LH) 117 continue; 118 119 auto *ValueExpr = LH->getValue(); 120 unsigned ValueInt = 1; 121 if (ValueExpr) { 122 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx); 123 ValueInt = ValueAPS.getSExtValue(); 124 } 125 126 LoopHintAttr::OptionType Option = LH->getOption(); 127 LoopHintAttr::LoopHintState State = LH->getState(); 128 switch (State) { 129 case LoopHintAttr::Disable: 130 switch (Option) { 131 case LoopHintAttr::Vectorize: 132 // Disable vectorization by specifying a width of 1. 133 setVectorizeWidth(1); 134 break; 135 case LoopHintAttr::Interleave: 136 // Disable interleaving by speciyfing a count of 1. 137 setInterleaveCount(1); 138 break; 139 case LoopHintAttr::Unroll: 140 setUnrollEnable(false); 141 break; 142 case LoopHintAttr::UnrollCount: 143 case LoopHintAttr::VectorizeWidth: 144 case LoopHintAttr::InterleaveCount: 145 llvm_unreachable("Options cannot be disabled."); 146 break; 147 } 148 break; 149 case LoopHintAttr::Enable: 150 switch (Option) { 151 case LoopHintAttr::Vectorize: 152 case LoopHintAttr::Interleave: 153 setVectorizeEnable(true); 154 break; 155 case LoopHintAttr::Unroll: 156 setUnrollEnable(true); 157 break; 158 case LoopHintAttr::UnrollCount: 159 case LoopHintAttr::VectorizeWidth: 160 case LoopHintAttr::InterleaveCount: 161 llvm_unreachable("Options cannot enabled."); 162 break; 163 } 164 break; 165 case LoopHintAttr::AssumeSafety: 166 switch (Option) { 167 case LoopHintAttr::Vectorize: 168 case LoopHintAttr::Interleave: 169 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores. 170 setParallel(true); 171 setVectorizeEnable(true); 172 break; 173 case LoopHintAttr::Unroll: 174 case LoopHintAttr::UnrollCount: 175 case LoopHintAttr::VectorizeWidth: 176 case LoopHintAttr::InterleaveCount: 177 llvm_unreachable("Options cannot be used to assume mem safety."); 178 break; 179 } 180 break; 181 case LoopHintAttr::Default: 182 switch (Option) { 183 case LoopHintAttr::VectorizeWidth: 184 setVectorizeWidth(ValueInt); 185 break; 186 case LoopHintAttr::InterleaveCount: 187 setInterleaveCount(ValueInt); 188 break; 189 case LoopHintAttr::UnrollCount: 190 setUnrollCount(ValueInt); 191 break; 192 case LoopHintAttr::Unroll: 193 // The default option is used when '#pragma unroll' is specified. 194 setUnrollEnable(true); 195 break; 196 case LoopHintAttr::Vectorize: 197 case LoopHintAttr::Interleave: 198 llvm_unreachable("Options cannot be assigned a value and do not have a " 199 "default value."); 200 break; 201 } 202 break; 203 } 204 } 205 206 /// Stage the attributes. 207 push(Header); 208 } 209 210 void LoopInfoStack::pop() { 211 assert(!Active.empty() && "No active loops to pop"); 212 Active.pop_back(); 213 } 214 215 void LoopInfoStack::InsertHelper(Instruction *I) const { 216 if (!hasInfo()) 217 return; 218 219 const LoopInfo &L = getInfo(); 220 if (!L.getLoopID()) 221 return; 222 223 if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) { 224 for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i) 225 if (TI->getSuccessor(i) == L.getHeader()) { 226 TI->setMetadata("llvm.loop", L.getLoopID()); 227 break; 228 } 229 return; 230 } 231 232 if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory()) 233 I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID()); 234 } 235