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