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