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, 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, 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 bool llvm::isBarrierIntrinsic(Intrinsic::ID id) { 339 if ((id == Intrinsic::nvvm_barrier0) || 340 (id == Intrinsic::nvvm_barrier0_popc) || 341 (id == Intrinsic::nvvm_barrier0_and) || 342 (id == Intrinsic::nvvm_barrier0_or) || 343 (id == Intrinsic::cuda_syncthreads)) 344 return true; 345 return false; 346 } 347 348 // Interface for checking all memory space transfer related intrinsics 349 bool llvm::isMemorySpaceTransferIntrinsic(Intrinsic::ID id) { 350 if (id == Intrinsic::nvvm_ptr_local_to_gen || 351 id == Intrinsic::nvvm_ptr_shared_to_gen || 352 id == Intrinsic::nvvm_ptr_global_to_gen || 353 id == Intrinsic::nvvm_ptr_constant_to_gen || 354 id == Intrinsic::nvvm_ptr_gen_to_global || 355 id == Intrinsic::nvvm_ptr_gen_to_shared || 356 id == Intrinsic::nvvm_ptr_gen_to_local || 357 id == Intrinsic::nvvm_ptr_gen_to_constant || 358 id == Intrinsic::nvvm_ptr_gen_to_param) { 359 return true; 360 } 361 362 return false; 363 } 364 365 // consider several special intrinsics in striping pointer casts, and 366 // provide an option to ignore GEP indicies for find out the base address only 367 // which could be used in simple alias disambigurate. 368 const Value * 369 llvm::skipPointerTransfer(const Value *V, bool ignore_GEP_indices) { 370 V = V->stripPointerCasts(); 371 while (true) { 372 if (const IntrinsicInst *IS = dyn_cast<IntrinsicInst>(V)) { 373 if (isMemorySpaceTransferIntrinsic(IS->getIntrinsicID())) { 374 V = IS->getArgOperand(0)->stripPointerCasts(); 375 continue; 376 } 377 } else if (ignore_GEP_indices) 378 if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { 379 V = GEP->getPointerOperand()->stripPointerCasts(); 380 continue; 381 } 382 break; 383 } 384 return V; 385 } 386 387 // consider several special intrinsics in striping pointer casts, and 388 // - ignore GEP indicies for find out the base address only, and 389 // - tracking PHINode 390 // which could be used in simple alias disambigurate. 391 const Value * 392 llvm::skipPointerTransfer(const Value *V, std::set<const Value *> &processed) { 393 if (processed.find(V) != processed.end()) 394 return nullptr; 395 processed.insert(V); 396 397 const Value *V2 = V->stripPointerCasts(); 398 if (V2 != V && processed.find(V2) != processed.end()) 399 return nullptr; 400 processed.insert(V2); 401 402 V = V2; 403 404 while (true) { 405 if (const IntrinsicInst *IS = dyn_cast<IntrinsicInst>(V)) { 406 if (isMemorySpaceTransferIntrinsic(IS->getIntrinsicID())) { 407 V = IS->getArgOperand(0)->stripPointerCasts(); 408 continue; 409 } 410 } else if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { 411 V = GEP->getPointerOperand()->stripPointerCasts(); 412 continue; 413 } else if (const PHINode *PN = dyn_cast<PHINode>(V)) { 414 if (V != V2 && processed.find(V) != processed.end()) 415 return nullptr; 416 processed.insert(PN); 417 const Value *common = nullptr; 418 for (unsigned i = 0; i != PN->getNumIncomingValues(); ++i) { 419 const Value *pv = PN->getIncomingValue(i); 420 const Value *base = skipPointerTransfer(pv, processed); 421 if (base) { 422 if (!common) 423 common = base; 424 else if (common != base) 425 return PN; 426 } 427 } 428 if (!common) 429 return PN; 430 V = common; 431 } 432 break; 433 } 434 return V; 435 } 436 437 // The following are some useful utilities for debuggung 438 439 BasicBlock *llvm::getParentBlock(Value *v) { 440 if (BasicBlock *B = dyn_cast<BasicBlock>(v)) 441 return B; 442 443 if (Instruction *I = dyn_cast<Instruction>(v)) 444 return I->getParent(); 445 446 return nullptr; 447 } 448 449 Function *llvm::getParentFunction(Value *v) { 450 if (Function *F = dyn_cast<Function>(v)) 451 return F; 452 453 if (Instruction *I = dyn_cast<Instruction>(v)) 454 return I->getParent()->getParent(); 455 456 if (BasicBlock *B = dyn_cast<BasicBlock>(v)) 457 return B->getParent(); 458 459 return nullptr; 460 } 461 462 // Dump a block by name 463 void llvm::dumpBlock(Value *v, char *blockName) { 464 Function *F = getParentFunction(v); 465 if (!F) 466 return; 467 468 for (Function::iterator it = F->begin(), ie = F->end(); it != ie; ++it) { 469 BasicBlock *B = it; 470 if (strcmp(B->getName().data(), blockName) == 0) { 471 B->dump(); 472 return; 473 } 474 } 475 } 476 477 // Find an instruction by name 478 Instruction *llvm::getInst(Value *base, char *instName) { 479 Function *F = getParentFunction(base); 480 if (!F) 481 return nullptr; 482 483 for (inst_iterator it = inst_begin(F), ie = inst_end(F); it != ie; ++it) { 484 Instruction *I = &*it; 485 if (strcmp(I->getName().data(), instName) == 0) { 486 return I; 487 } 488 } 489 490 return nullptr; 491 } 492 493 // Dump an instruction by nane 494 void llvm::dumpInst(Value *base, char *instName) { 495 Instruction *I = getInst(base, instName); 496 if (I) 497 I->dump(); 498 } 499 500 // Dump an instruction and all dependent instructions 501 void llvm::dumpInstRec(Value *v, std::set<Instruction *> *visited) { 502 if (Instruction *I = dyn_cast<Instruction>(v)) { 503 504 if (visited->find(I) != visited->end()) 505 return; 506 507 visited->insert(I); 508 509 for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) 510 dumpInstRec(I->getOperand(i), visited); 511 512 I->dump(); 513 } 514 } 515 516 // Dump an instruction and all dependent instructions 517 void llvm::dumpInstRec(Value *v) { 518 std::set<Instruction *> visited; 519 520 //BasicBlock *B = getParentBlock(v); 521 522 dumpInstRec(v, &visited); 523 } 524 525 // Dump the parent for Instruction, block or function 526 void llvm::dumpParent(Value *v) { 527 if (Instruction *I = dyn_cast<Instruction>(v)) { 528 I->getParent()->dump(); 529 return; 530 } 531 532 if (BasicBlock *B = dyn_cast<BasicBlock>(v)) { 533 B->getParent()->dump(); 534 return; 535 } 536 537 if (Function *F = dyn_cast<Function>(v)) { 538 F->getParent()->dump(); 539 return; 540 } 541 } 542