1 //===- NVPTXUtilities.cpp - Utility Functions -----------------------------===// 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 // This file contains miscellaneous utility functions 11 //===----------------------------------------------------------------------===// 12 13 #include "NVPTXUtilities.h" 14 #include "NVPTX.h" 15 #include "llvm/IR/Constants.h" 16 #include "llvm/IR/Function.h" 17 #include "llvm/IR/GlobalVariable.h" 18 #include "llvm/IR/InstIterator.h" 19 #include "llvm/IR/Module.h" 20 #include "llvm/IR/Operator.h" 21 #include "llvm/Support/ManagedStatic.h" 22 #include "llvm/Support/MutexGuard.h" 23 #include <algorithm> 24 #include <cstring> 25 #include <map> 26 #include <string> 27 #include <vector> 28 29 using namespace llvm; 30 31 typedef std::map<std::string, std::vector<unsigned> > key_val_pair_t; 32 typedef std::map<const GlobalValue *, key_val_pair_t> global_val_annot_t; 33 typedef std::map<const Module *, global_val_annot_t> per_module_annot_t; 34 35 ManagedStatic<per_module_annot_t> annotationCache; 36 static sys::Mutex Lock; 37 38 void llvm::clearAnnotationCache(const llvm::Module *Mod) { 39 MutexGuard Guard(Lock); 40 annotationCache->erase(Mod); 41 } 42 43 static void cacheAnnotationFromMD(const MDNode *md, key_val_pair_t &retval) { 44 MutexGuard Guard(Lock); 45 assert(md && "Invalid mdnode for annotation"); 46 assert((md->getNumOperands() % 2) == 1 && "Invalid number of operands"); 47 // start index = 1, to skip the global variable key 48 // increment = 2, to skip the value for each property-value pairs 49 for (unsigned i = 1, e = md->getNumOperands(); i != e; i += 2) { 50 // property 51 const MDString *prop = dyn_cast<MDString>(md->getOperand(i)); 52 assert(prop && "Annotation property not a string"); 53 54 // value 55 ConstantInt *Val = mdconst::dyn_extract<ConstantInt>(md->getOperand(i + 1)); 56 assert(Val && "Value operand not a constant int"); 57 58 std::string keyname = prop->getString().str(); 59 if (retval.find(keyname) != retval.end()) 60 retval[keyname].push_back(Val->getZExtValue()); 61 else { 62 std::vector<unsigned> tmp; 63 tmp.push_back(Val->getZExtValue()); 64 retval[keyname] = tmp; 65 } 66 } 67 } 68 69 static void cacheAnnotationFromMD(const Module *m, const GlobalValue *gv) { 70 MutexGuard Guard(Lock); 71 NamedMDNode *NMD = m->getNamedMetadata(llvm::NamedMDForAnnotations); 72 if (!NMD) 73 return; 74 key_val_pair_t tmp; 75 for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { 76 const MDNode *elem = NMD->getOperand(i); 77 78 GlobalValue *entity = 79 mdconst::dyn_extract_or_null<GlobalValue>(elem->getOperand(0)); 80 // entity may be null due to DCE 81 if (!entity) 82 continue; 83 if (entity != gv) 84 continue; 85 86 // accumulate annotations for entity in tmp 87 cacheAnnotationFromMD(elem, tmp); 88 } 89 90 if (tmp.empty()) // no annotations for this gv 91 return; 92 93 if ((*annotationCache).find(m) != (*annotationCache).end()) 94 (*annotationCache)[m][gv] = std::move(tmp); 95 else { 96 global_val_annot_t tmp1; 97 tmp1[gv] = std::move(tmp); 98 (*annotationCache)[m] = std::move(tmp1); 99 } 100 } 101 102 bool llvm::findOneNVVMAnnotation(const GlobalValue *gv, const std::string &prop, 103 unsigned &retval) { 104 MutexGuard Guard(Lock); 105 const Module *m = gv->getParent(); 106 if ((*annotationCache).find(m) == (*annotationCache).end()) 107 cacheAnnotationFromMD(m, gv); 108 else if ((*annotationCache)[m].find(gv) == (*annotationCache)[m].end()) 109 cacheAnnotationFromMD(m, gv); 110 if ((*annotationCache)[m][gv].find(prop) == (*annotationCache)[m][gv].end()) 111 return false; 112 retval = (*annotationCache)[m][gv][prop][0]; 113 return true; 114 } 115 116 bool llvm::findAllNVVMAnnotation(const GlobalValue *gv, const std::string &prop, 117 std::vector<unsigned> &retval) { 118 MutexGuard Guard(Lock); 119 const Module *m = gv->getParent(); 120 if ((*annotationCache).find(m) == (*annotationCache).end()) 121 cacheAnnotationFromMD(m, gv); 122 else if ((*annotationCache)[m].find(gv) == (*annotationCache)[m].end()) 123 cacheAnnotationFromMD(m, gv); 124 if ((*annotationCache)[m][gv].find(prop) == (*annotationCache)[m][gv].end()) 125 return false; 126 retval = (*annotationCache)[m][gv][prop]; 127 return true; 128 } 129 130 bool llvm::isTexture(const llvm::Value &val) { 131 if (const GlobalValue *gv = dyn_cast<GlobalValue>(&val)) { 132 unsigned annot; 133 if (llvm::findOneNVVMAnnotation( 134 gv, llvm::PropertyAnnotationNames[llvm::PROPERTY_ISTEXTURE], 135 annot)) { 136 assert((annot == 1) && "Unexpected annotation on a texture symbol"); 137 return true; 138 } 139 } 140 return false; 141 } 142 143 bool llvm::isSurface(const llvm::Value &val) { 144 if (const GlobalValue *gv = dyn_cast<GlobalValue>(&val)) { 145 unsigned annot; 146 if (llvm::findOneNVVMAnnotation( 147 gv, llvm::PropertyAnnotationNames[llvm::PROPERTY_ISSURFACE], 148 annot)) { 149 assert((annot == 1) && "Unexpected annotation on a surface symbol"); 150 return true; 151 } 152 } 153 return false; 154 } 155 156 bool llvm::isSampler(const llvm::Value &val) { 157 if (const GlobalValue *gv = dyn_cast<GlobalValue>(&val)) { 158 unsigned annot; 159 if (llvm::findOneNVVMAnnotation( 160 gv, llvm::PropertyAnnotationNames[llvm::PROPERTY_ISSAMPLER], 161 annot)) { 162 assert((annot == 1) && "Unexpected annotation on a sampler symbol"); 163 return true; 164 } 165 } 166 if (const Argument *arg = dyn_cast<Argument>(&val)) { 167 const Function *func = arg->getParent(); 168 std::vector<unsigned> annot; 169 if (llvm::findAllNVVMAnnotation( 170 func, llvm::PropertyAnnotationNames[llvm::PROPERTY_ISSAMPLER], 171 annot)) { 172 if (std::find(annot.begin(), annot.end(), arg->getArgNo()) != annot.end()) 173 return true; 174 } 175 } 176 return false; 177 } 178 179 bool llvm::isImageReadOnly(const llvm::Value &val) { 180 if (const Argument *arg = dyn_cast<Argument>(&val)) { 181 const Function *func = arg->getParent(); 182 std::vector<unsigned> annot; 183 if (llvm::findAllNVVMAnnotation(func, 184 llvm::PropertyAnnotationNames[ 185 llvm::PROPERTY_ISREADONLY_IMAGE_PARAM], 186 annot)) { 187 if (std::find(annot.begin(), annot.end(), arg->getArgNo()) != annot.end()) 188 return true; 189 } 190 } 191 return false; 192 } 193 194 bool llvm::isImageWriteOnly(const llvm::Value &val) { 195 if (const Argument *arg = dyn_cast<Argument>(&val)) { 196 const Function *func = arg->getParent(); 197 std::vector<unsigned> annot; 198 if (llvm::findAllNVVMAnnotation(func, 199 llvm::PropertyAnnotationNames[ 200 llvm::PROPERTY_ISWRITEONLY_IMAGE_PARAM], 201 annot)) { 202 if (std::find(annot.begin(), annot.end(), arg->getArgNo()) != annot.end()) 203 return true; 204 } 205 } 206 return false; 207 } 208 209 bool llvm::isImageReadWrite(const llvm::Value &val) { 210 if (const Argument *arg = dyn_cast<Argument>(&val)) { 211 const Function *func = arg->getParent(); 212 std::vector<unsigned> annot; 213 if (llvm::findAllNVVMAnnotation(func, 214 llvm::PropertyAnnotationNames[ 215 llvm::PROPERTY_ISREADWRITE_IMAGE_PARAM], 216 annot)) { 217 if (std::find(annot.begin(), annot.end(), arg->getArgNo()) != annot.end()) 218 return true; 219 } 220 } 221 return false; 222 } 223 224 bool llvm::isImage(const llvm::Value &val) { 225 return llvm::isImageReadOnly(val) || llvm::isImageWriteOnly(val) || 226 llvm::isImageReadWrite(val); 227 } 228 229 bool llvm::isManaged(const llvm::Value &val) { 230 if(const GlobalValue *gv = dyn_cast<GlobalValue>(&val)) { 231 unsigned annot; 232 if(llvm::findOneNVVMAnnotation(gv, 233 llvm::PropertyAnnotationNames[llvm::PROPERTY_MANAGED], 234 annot)) { 235 assert((annot == 1) && "Unexpected annotation on a managed symbol"); 236 return true; 237 } 238 } 239 return false; 240 } 241 242 std::string llvm::getTextureName(const llvm::Value &val) { 243 assert(val.hasName() && "Found texture variable with no name"); 244 return val.getName(); 245 } 246 247 std::string llvm::getSurfaceName(const llvm::Value &val) { 248 assert(val.hasName() && "Found surface variable with no name"); 249 return val.getName(); 250 } 251 252 std::string llvm::getSamplerName(const llvm::Value &val) { 253 assert(val.hasName() && "Found sampler variable with no name"); 254 return val.getName(); 255 } 256 257 bool llvm::getMaxNTIDx(const Function &F, unsigned &x) { 258 return (llvm::findOneNVVMAnnotation( 259 &F, llvm::PropertyAnnotationNames[llvm::PROPERTY_MAXNTID_X], x)); 260 } 261 262 bool llvm::getMaxNTIDy(const Function &F, unsigned &y) { 263 return (llvm::findOneNVVMAnnotation( 264 &F, llvm::PropertyAnnotationNames[llvm::PROPERTY_MAXNTID_Y], y)); 265 } 266 267 bool llvm::getMaxNTIDz(const Function &F, unsigned &z) { 268 return (llvm::findOneNVVMAnnotation( 269 &F, llvm::PropertyAnnotationNames[llvm::PROPERTY_MAXNTID_Z], z)); 270 } 271 272 bool llvm::getReqNTIDx(const Function &F, unsigned &x) { 273 return (llvm::findOneNVVMAnnotation( 274 &F, llvm::PropertyAnnotationNames[llvm::PROPERTY_REQNTID_X], x)); 275 } 276 277 bool llvm::getReqNTIDy(const Function &F, unsigned &y) { 278 return (llvm::findOneNVVMAnnotation( 279 &F, llvm::PropertyAnnotationNames[llvm::PROPERTY_REQNTID_Y], y)); 280 } 281 282 bool llvm::getReqNTIDz(const Function &F, unsigned &z) { 283 return (llvm::findOneNVVMAnnotation( 284 &F, llvm::PropertyAnnotationNames[llvm::PROPERTY_REQNTID_Z], z)); 285 } 286 287 bool llvm::getMinCTASm(const Function &F, unsigned &x) { 288 return (llvm::findOneNVVMAnnotation( 289 &F, llvm::PropertyAnnotationNames[llvm::PROPERTY_MINNCTAPERSM], x)); 290 } 291 292 bool llvm::isKernelFunction(const Function &F) { 293 unsigned x = 0; 294 bool retval = llvm::findOneNVVMAnnotation( 295 &F, llvm::PropertyAnnotationNames[llvm::PROPERTY_ISKERNEL_FUNCTION], x); 296 if (!retval) { 297 // There is no NVVM metadata, check the calling convention 298 return F.getCallingConv() == llvm::CallingConv::PTX_Kernel; 299 } 300 return (x == 1); 301 } 302 303 bool llvm::getAlign(const Function &F, unsigned index, unsigned &align) { 304 std::vector<unsigned> Vs; 305 bool retval = llvm::findAllNVVMAnnotation( 306 &F, llvm::PropertyAnnotationNames[llvm::PROPERTY_ALIGN], Vs); 307 if (!retval) 308 return false; 309 for (int i = 0, e = Vs.size(); i < e; i++) { 310 unsigned v = Vs[i]; 311 if ((v >> 16) == index) { 312 align = v & 0xFFFF; 313 return true; 314 } 315 } 316 return false; 317 } 318 319 bool llvm::getAlign(const CallInst &I, unsigned index, unsigned &align) { 320 if (MDNode *alignNode = I.getMetadata("callalign")) { 321 for (int i = 0, n = alignNode->getNumOperands(); i < n; i++) { 322 if (const ConstantInt *CI = 323 mdconst::dyn_extract<ConstantInt>(alignNode->getOperand(i))) { 324 unsigned v = CI->getZExtValue(); 325 if ((v >> 16) == index) { 326 align = v & 0xFFFF; 327 return true; 328 } 329 if ((v >> 16) > index) { 330 return false; 331 } 332 } 333 } 334 } 335 return false; 336 } 337 338 // The following are some useful utilities for debugging 339 340 BasicBlock *llvm::getParentBlock(Value *v) { 341 if (BasicBlock *B = dyn_cast<BasicBlock>(v)) 342 return B; 343 344 if (Instruction *I = dyn_cast<Instruction>(v)) 345 return I->getParent(); 346 347 return nullptr; 348 } 349 350 Function *llvm::getParentFunction(Value *v) { 351 if (Function *F = dyn_cast<Function>(v)) 352 return F; 353 354 if (Instruction *I = dyn_cast<Instruction>(v)) 355 return I->getParent()->getParent(); 356 357 if (BasicBlock *B = dyn_cast<BasicBlock>(v)) 358 return B->getParent(); 359 360 return nullptr; 361 } 362 363 // Dump a block by name 364 void llvm::dumpBlock(Value *v, char *blockName) { 365 Function *F = getParentFunction(v); 366 if (!F) 367 return; 368 369 for (Function::iterator it = F->begin(), ie = F->end(); it != ie; ++it) { 370 BasicBlock *B = &*it; 371 if (strcmp(B->getName().data(), blockName) == 0) { 372 B->dump(); 373 return; 374 } 375 } 376 } 377 378 // Find an instruction by name 379 Instruction *llvm::getInst(Value *base, char *instName) { 380 Function *F = getParentFunction(base); 381 if (!F) 382 return nullptr; 383 384 for (inst_iterator it = inst_begin(F), ie = inst_end(F); it != ie; ++it) { 385 Instruction *I = &*it; 386 if (strcmp(I->getName().data(), instName) == 0) { 387 return I; 388 } 389 } 390 391 return nullptr; 392 } 393 394 // Dump an instruction by name 395 void llvm::dumpInst(Value *base, char *instName) { 396 Instruction *I = getInst(base, instName); 397 if (I) 398 I->dump(); 399 } 400 401 // Dump an instruction and all dependent instructions 402 void llvm::dumpInstRec(Value *v, std::set<Instruction *> *visited) { 403 if (Instruction *I = dyn_cast<Instruction>(v)) { 404 405 if (visited->find(I) != visited->end()) 406 return; 407 408 visited->insert(I); 409 410 for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) 411 dumpInstRec(I->getOperand(i), visited); 412 413 I->dump(); 414 } 415 } 416 417 // Dump an instruction and all dependent instructions 418 void llvm::dumpInstRec(Value *v) { 419 std::set<Instruction *> visited; 420 421 //BasicBlock *B = getParentBlock(v); 422 423 dumpInstRec(v, &visited); 424 } 425 426 // Dump the parent for Instruction, block or function 427 void llvm::dumpParent(Value *v) { 428 if (Instruction *I = dyn_cast<Instruction>(v)) { 429 I->getParent()->dump(); 430 return; 431 } 432 433 if (BasicBlock *B = dyn_cast<BasicBlock>(v)) { 434 B->getParent()->dump(); 435 return; 436 } 437 438 if (Function *F = dyn_cast<Function>(v)) { 439 F->getParent()->dump(); 440 return; 441 } 442 } 443