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