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 llvm::DebugLoc StartLoc, llvm::DebugLoc EndLoc) { 24 25 if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 && 26 Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 && 27 Attrs.VectorizeEnable == LoopAttributes::Unspecified && 28 Attrs.UnrollEnable == LoopAttributes::Unspecified && 29 Attrs.DistributeEnable == LoopAttributes::Unspecified && 30 !StartLoc && !EndLoc) 31 return nullptr; 32 33 SmallVector<Metadata *, 4> Args; 34 // Reserve operand 0 for loop id self reference. 35 auto TempNode = MDNode::getTemporary(Ctx, None); 36 Args.push_back(TempNode.get()); 37 38 // If we have a valid start debug location for the loop, add it. 39 if (StartLoc) { 40 Args.push_back(StartLoc.getAsMDNode()); 41 42 // If we also have a valid end debug location for the loop, add it. 43 if (EndLoc) 44 Args.push_back(EndLoc.getAsMDNode()); 45 } 46 47 // Setting vectorize.width 48 if (Attrs.VectorizeWidth > 0) { 49 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"), 50 ConstantAsMetadata::get(ConstantInt::get( 51 Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))}; 52 Args.push_back(MDNode::get(Ctx, Vals)); 53 } 54 55 // Setting interleave.count 56 if (Attrs.InterleaveCount > 0) { 57 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"), 58 ConstantAsMetadata::get(ConstantInt::get( 59 Type::getInt32Ty(Ctx), Attrs.InterleaveCount))}; 60 Args.push_back(MDNode::get(Ctx, Vals)); 61 } 62 63 // Setting interleave.count 64 if (Attrs.UnrollCount > 0) { 65 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"), 66 ConstantAsMetadata::get(ConstantInt::get( 67 Type::getInt32Ty(Ctx), Attrs.UnrollCount))}; 68 Args.push_back(MDNode::get(Ctx, Vals)); 69 } 70 71 // Setting vectorize.enable 72 if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) { 73 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"), 74 ConstantAsMetadata::get(ConstantInt::get( 75 Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable == 76 LoopAttributes::Enable)))}; 77 Args.push_back(MDNode::get(Ctx, Vals)); 78 } 79 80 // Setting unroll.full or unroll.disable 81 if (Attrs.UnrollEnable != LoopAttributes::Unspecified) { 82 std::string Name; 83 if (Attrs.UnrollEnable == LoopAttributes::Enable) 84 Name = "llvm.loop.unroll.enable"; 85 else if (Attrs.UnrollEnable == LoopAttributes::Full) 86 Name = "llvm.loop.unroll.full"; 87 else 88 Name = "llvm.loop.unroll.disable"; 89 Metadata *Vals[] = {MDString::get(Ctx, Name)}; 90 Args.push_back(MDNode::get(Ctx, Vals)); 91 } 92 93 if (Attrs.DistributeEnable != LoopAttributes::Unspecified) { 94 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"), 95 ConstantAsMetadata::get(ConstantInt::get( 96 Type::getInt1Ty(Ctx), (Attrs.DistributeEnable == 97 LoopAttributes::Enable)))}; 98 Args.push_back(MDNode::get(Ctx, Vals)); 99 } 100 101 // Set the first operand to itself. 102 MDNode *LoopID = MDNode::get(Ctx, Args); 103 LoopID->replaceOperandWith(0, LoopID); 104 return LoopID; 105 } 106 107 LoopAttributes::LoopAttributes(bool IsParallel) 108 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified), 109 UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0), 110 InterleaveCount(0), UnrollCount(0), 111 DistributeEnable(LoopAttributes::Unspecified) {} 112 113 void LoopAttributes::clear() { 114 IsParallel = false; 115 VectorizeWidth = 0; 116 InterleaveCount = 0; 117 UnrollCount = 0; 118 VectorizeEnable = LoopAttributes::Unspecified; 119 UnrollEnable = LoopAttributes::Unspecified; 120 DistributeEnable = LoopAttributes::Unspecified; 121 } 122 123 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs, 124 llvm::DebugLoc StartLoc, llvm::DebugLoc EndLoc) 125 : LoopID(nullptr), Header(Header), Attrs(Attrs) { 126 LoopID = createMetadata(Header->getContext(), Attrs, StartLoc, EndLoc); 127 } 128 129 void LoopInfoStack::push(BasicBlock *Header, llvm::DebugLoc StartLoc, 130 llvm::DebugLoc EndLoc) { 131 Active.push_back(LoopInfo(Header, StagedAttrs, StartLoc, EndLoc)); 132 // Clear the attributes so nested loops do not inherit them. 133 StagedAttrs.clear(); 134 } 135 136 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, 137 ArrayRef<const clang::Attr *> Attrs, 138 llvm::DebugLoc StartLoc, llvm::DebugLoc EndLoc) { 139 140 // Identify loop hint attributes from Attrs. 141 for (const auto *Attr : Attrs) { 142 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr); 143 const OpenCLUnrollHintAttr *OpenCLHint = 144 dyn_cast<OpenCLUnrollHintAttr>(Attr); 145 146 // Skip non loop hint attributes 147 if (!LH && !OpenCLHint) { 148 continue; 149 } 150 151 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll; 152 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable; 153 unsigned ValueInt = 1; 154 // Translate opencl_unroll_hint attribute argument to 155 // equivalent LoopHintAttr enums. 156 // OpenCL v2.0 s6.11.5: 157 // 0 - full unroll (no argument). 158 // 1 - disable unroll. 159 // other positive integer n - unroll by n. 160 if (OpenCLHint) { 161 ValueInt = OpenCLHint->getUnrollHint(); 162 if (ValueInt == 0) { 163 State = LoopHintAttr::Full; 164 } else if (ValueInt != 1) { 165 Option = LoopHintAttr::UnrollCount; 166 State = LoopHintAttr::Numeric; 167 } 168 } else if (LH) { 169 auto *ValueExpr = LH->getValue(); 170 if (ValueExpr) { 171 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx); 172 ValueInt = ValueAPS.getSExtValue(); 173 } 174 175 Option = LH->getOption(); 176 State = LH->getState(); 177 } 178 switch (State) { 179 case LoopHintAttr::Disable: 180 switch (Option) { 181 case LoopHintAttr::Vectorize: 182 // Disable vectorization by specifying a width of 1. 183 setVectorizeWidth(1); 184 break; 185 case LoopHintAttr::Interleave: 186 // Disable interleaving by speciyfing a count of 1. 187 setInterleaveCount(1); 188 break; 189 case LoopHintAttr::Unroll: 190 setUnrollState(LoopAttributes::Disable); 191 break; 192 case LoopHintAttr::Distribute: 193 setDistributeState(false); 194 break; 195 case LoopHintAttr::UnrollCount: 196 case LoopHintAttr::VectorizeWidth: 197 case LoopHintAttr::InterleaveCount: 198 llvm_unreachable("Options cannot be disabled."); 199 break; 200 } 201 break; 202 case LoopHintAttr::Enable: 203 switch (Option) { 204 case LoopHintAttr::Vectorize: 205 case LoopHintAttr::Interleave: 206 setVectorizeEnable(true); 207 break; 208 case LoopHintAttr::Unroll: 209 setUnrollState(LoopAttributes::Enable); 210 break; 211 case LoopHintAttr::Distribute: 212 setDistributeState(true); 213 break; 214 case LoopHintAttr::UnrollCount: 215 case LoopHintAttr::VectorizeWidth: 216 case LoopHintAttr::InterleaveCount: 217 llvm_unreachable("Options cannot enabled."); 218 break; 219 } 220 break; 221 case LoopHintAttr::AssumeSafety: 222 switch (Option) { 223 case LoopHintAttr::Vectorize: 224 case LoopHintAttr::Interleave: 225 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores. 226 setParallel(true); 227 setVectorizeEnable(true); 228 break; 229 case LoopHintAttr::Unroll: 230 case LoopHintAttr::UnrollCount: 231 case LoopHintAttr::VectorizeWidth: 232 case LoopHintAttr::InterleaveCount: 233 case LoopHintAttr::Distribute: 234 llvm_unreachable("Options cannot be used to assume mem safety."); 235 break; 236 } 237 break; 238 case LoopHintAttr::Full: 239 switch (Option) { 240 case LoopHintAttr::Unroll: 241 setUnrollState(LoopAttributes::Full); 242 break; 243 case LoopHintAttr::Vectorize: 244 case LoopHintAttr::Interleave: 245 case LoopHintAttr::UnrollCount: 246 case LoopHintAttr::VectorizeWidth: 247 case LoopHintAttr::InterleaveCount: 248 case LoopHintAttr::Distribute: 249 llvm_unreachable("Options cannot be used with 'full' hint."); 250 break; 251 } 252 break; 253 case LoopHintAttr::Numeric: 254 switch (Option) { 255 case LoopHintAttr::VectorizeWidth: 256 setVectorizeWidth(ValueInt); 257 break; 258 case LoopHintAttr::InterleaveCount: 259 setInterleaveCount(ValueInt); 260 break; 261 case LoopHintAttr::UnrollCount: 262 setUnrollCount(ValueInt); 263 break; 264 case LoopHintAttr::Unroll: 265 case LoopHintAttr::Vectorize: 266 case LoopHintAttr::Interleave: 267 case LoopHintAttr::Distribute: 268 llvm_unreachable("Options cannot be assigned a value."); 269 break; 270 } 271 break; 272 } 273 } 274 275 /// Stage the attributes. 276 push(Header, StartLoc, EndLoc); 277 } 278 279 void LoopInfoStack::pop() { 280 assert(!Active.empty() && "No active loops to pop"); 281 Active.pop_back(); 282 } 283 284 void LoopInfoStack::InsertHelper(Instruction *I) const { 285 if (!hasInfo()) 286 return; 287 288 const LoopInfo &L = getInfo(); 289 if (!L.getLoopID()) 290 return; 291 292 if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) { 293 for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i) 294 if (TI->getSuccessor(i) == L.getHeader()) { 295 TI->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID()); 296 break; 297 } 298 return; 299 } 300 301 if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory()) 302 I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID()); 303 } 304