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 const llvm::DebugLoc &StartLoc, 24 const llvm::DebugLoc &EndLoc) { 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 // Set the first operand to itself. 126 MDNode *LoopID = MDNode::get(Ctx, Args); 127 LoopID->replaceOperandWith(0, LoopID); 128 return LoopID; 129 } 130 131 LoopAttributes::LoopAttributes(bool IsParallel) 132 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified), 133 UnrollEnable(LoopAttributes::Unspecified), 134 UnrollAndJamEnable(LoopAttributes::Unspecified), VectorizeWidth(0), 135 InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0), 136 DistributeEnable(LoopAttributes::Unspecified) {} 137 138 void LoopAttributes::clear() { 139 IsParallel = false; 140 VectorizeWidth = 0; 141 InterleaveCount = 0; 142 UnrollCount = 0; 143 UnrollAndJamCount = 0; 144 VectorizeEnable = LoopAttributes::Unspecified; 145 UnrollEnable = LoopAttributes::Unspecified; 146 UnrollAndJamEnable = LoopAttributes::Unspecified; 147 DistributeEnable = LoopAttributes::Unspecified; 148 } 149 150 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs, 151 const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc) 152 : LoopID(nullptr), Header(Header), Attrs(Attrs) { 153 LoopID = createMetadata(Header->getContext(), Attrs, StartLoc, EndLoc); 154 } 155 156 void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc, 157 const llvm::DebugLoc &EndLoc) { 158 Active.push_back(LoopInfo(Header, StagedAttrs, StartLoc, EndLoc)); 159 // Clear the attributes so nested loops do not inherit them. 160 StagedAttrs.clear(); 161 } 162 163 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, 164 ArrayRef<const clang::Attr *> Attrs, 165 const llvm::DebugLoc &StartLoc, 166 const llvm::DebugLoc &EndLoc) { 167 168 // Identify loop hint attributes from Attrs. 169 for (const auto *Attr : Attrs) { 170 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr); 171 const OpenCLUnrollHintAttr *OpenCLHint = 172 dyn_cast<OpenCLUnrollHintAttr>(Attr); 173 174 // Skip non loop hint attributes 175 if (!LH && !OpenCLHint) { 176 continue; 177 } 178 179 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll; 180 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable; 181 unsigned ValueInt = 1; 182 // Translate opencl_unroll_hint attribute argument to 183 // equivalent LoopHintAttr enums. 184 // OpenCL v2.0 s6.11.5: 185 // 0 - full unroll (no argument). 186 // 1 - disable unroll. 187 // other positive integer n - unroll by n. 188 if (OpenCLHint) { 189 ValueInt = OpenCLHint->getUnrollHint(); 190 if (ValueInt == 0) { 191 State = LoopHintAttr::Full; 192 } else if (ValueInt != 1) { 193 Option = LoopHintAttr::UnrollCount; 194 State = LoopHintAttr::Numeric; 195 } 196 } else if (LH) { 197 auto *ValueExpr = LH->getValue(); 198 if (ValueExpr) { 199 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx); 200 ValueInt = ValueAPS.getSExtValue(); 201 } 202 203 Option = LH->getOption(); 204 State = LH->getState(); 205 } 206 switch (State) { 207 case LoopHintAttr::Disable: 208 switch (Option) { 209 case LoopHintAttr::Vectorize: 210 // Disable vectorization by specifying a width of 1. 211 setVectorizeWidth(1); 212 break; 213 case LoopHintAttr::Interleave: 214 // Disable interleaving by speciyfing a count of 1. 215 setInterleaveCount(1); 216 break; 217 case LoopHintAttr::Unroll: 218 setUnrollState(LoopAttributes::Disable); 219 break; 220 case LoopHintAttr::UnrollAndJam: 221 setUnrollAndJamState(LoopAttributes::Disable); 222 break; 223 case LoopHintAttr::Distribute: 224 setDistributeState(false); 225 break; 226 case LoopHintAttr::UnrollCount: 227 case LoopHintAttr::UnrollAndJamCount: 228 case LoopHintAttr::VectorizeWidth: 229 case LoopHintAttr::InterleaveCount: 230 llvm_unreachable("Options cannot be disabled."); 231 break; 232 } 233 break; 234 case LoopHintAttr::Enable: 235 switch (Option) { 236 case LoopHintAttr::Vectorize: 237 case LoopHintAttr::Interleave: 238 setVectorizeEnable(true); 239 break; 240 case LoopHintAttr::Unroll: 241 setUnrollState(LoopAttributes::Enable); 242 break; 243 case LoopHintAttr::UnrollAndJam: 244 setUnrollAndJamState(LoopAttributes::Enable); 245 break; 246 case LoopHintAttr::Distribute: 247 setDistributeState(true); 248 break; 249 case LoopHintAttr::UnrollCount: 250 case LoopHintAttr::UnrollAndJamCount: 251 case LoopHintAttr::VectorizeWidth: 252 case LoopHintAttr::InterleaveCount: 253 llvm_unreachable("Options cannot enabled."); 254 break; 255 } 256 break; 257 case LoopHintAttr::AssumeSafety: 258 switch (Option) { 259 case LoopHintAttr::Vectorize: 260 case LoopHintAttr::Interleave: 261 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores. 262 setParallel(true); 263 setVectorizeEnable(true); 264 break; 265 case LoopHintAttr::Unroll: 266 case LoopHintAttr::UnrollAndJam: 267 case LoopHintAttr::UnrollCount: 268 case LoopHintAttr::UnrollAndJamCount: 269 case LoopHintAttr::VectorizeWidth: 270 case LoopHintAttr::InterleaveCount: 271 case LoopHintAttr::Distribute: 272 llvm_unreachable("Options cannot be used to assume mem safety."); 273 break; 274 } 275 break; 276 case LoopHintAttr::Full: 277 switch (Option) { 278 case LoopHintAttr::Unroll: 279 setUnrollState(LoopAttributes::Full); 280 break; 281 case LoopHintAttr::UnrollAndJam: 282 setUnrollAndJamState(LoopAttributes::Full); 283 break; 284 case LoopHintAttr::Vectorize: 285 case LoopHintAttr::Interleave: 286 case LoopHintAttr::UnrollCount: 287 case LoopHintAttr::UnrollAndJamCount: 288 case LoopHintAttr::VectorizeWidth: 289 case LoopHintAttr::InterleaveCount: 290 case LoopHintAttr::Distribute: 291 llvm_unreachable("Options cannot be used with 'full' hint."); 292 break; 293 } 294 break; 295 case LoopHintAttr::Numeric: 296 switch (Option) { 297 case LoopHintAttr::VectorizeWidth: 298 setVectorizeWidth(ValueInt); 299 break; 300 case LoopHintAttr::InterleaveCount: 301 setInterleaveCount(ValueInt); 302 break; 303 case LoopHintAttr::UnrollCount: 304 setUnrollCount(ValueInt); 305 break; 306 case LoopHintAttr::UnrollAndJamCount: 307 setUnrollAndJamCount(ValueInt); 308 break; 309 case LoopHintAttr::Unroll: 310 case LoopHintAttr::UnrollAndJam: 311 case LoopHintAttr::Vectorize: 312 case LoopHintAttr::Interleave: 313 case LoopHintAttr::Distribute: 314 llvm_unreachable("Options cannot be assigned a value."); 315 break; 316 } 317 break; 318 } 319 } 320 321 /// Stage the attributes. 322 push(Header, StartLoc, EndLoc); 323 } 324 325 void LoopInfoStack::pop() { 326 assert(!Active.empty() && "No active loops to pop"); 327 Active.pop_back(); 328 } 329 330 void LoopInfoStack::InsertHelper(Instruction *I) const { 331 if (!hasInfo()) 332 return; 333 334 const LoopInfo &L = getInfo(); 335 if (!L.getLoopID()) 336 return; 337 338 if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) { 339 for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i) 340 if (TI->getSuccessor(i) == L.getHeader()) { 341 TI->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID()); 342 break; 343 } 344 return; 345 } 346 347 if (I->mayReadOrWriteMemory()) { 348 SmallVector<Metadata *, 2> ParallelLoopIDs; 349 for (const LoopInfo &AL : Active) 350 if (AL.getAttributes().IsParallel) 351 ParallelLoopIDs.push_back(AL.getLoopID()); 352 353 MDNode *ParallelMD = nullptr; 354 if (ParallelLoopIDs.size() == 1) 355 ParallelMD = cast<MDNode>(ParallelLoopIDs[0]); 356 else if (ParallelLoopIDs.size() >= 2) 357 ParallelMD = MDNode::get(I->getContext(), ParallelLoopIDs); 358 I->setMetadata("llvm.mem.parallel_loop_access", ParallelMD); 359 } 360 } 361