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