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/GlobalVariable.h" 16 #include "llvm/Function.h" 17 #include "llvm/Module.h" 18 #include "llvm/Constants.h" 19 #include "llvm/Operator.h" 20 #include <algorithm> 21 #include <cstring> 22 #include <map> 23 #include <string> 24 #include <vector> 25 //#include <iostream> 26 #include "llvm/Support/ManagedStatic.h" 27 #include "llvm/Support/InstIterator.h" 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 37 38 static void cacheAnnotationFromMD(const MDNode *md, key_val_pair_t &retval) { 39 assert(md && "Invalid mdnode for annotation"); 40 assert((md->getNumOperands() % 2) == 1 && "Invalid number of operands"); 41 // start index = 1, to skip the global variable key 42 // increment = 2, to skip the value for each property-value pairs 43 for (unsigned i = 1, e = md->getNumOperands(); i != e; i += 2) { 44 // property 45 const MDString *prop = dyn_cast<MDString>(md->getOperand(i)); 46 assert(prop && "Annotation property not a string"); 47 48 // value 49 ConstantInt *Val = dyn_cast<ConstantInt>(md->getOperand(i+1)); 50 assert(Val && "Value operand not a constant int"); 51 52 std::string keyname = prop->getString().str(); 53 if (retval.find(keyname) != retval.end()) 54 retval[keyname].push_back(Val->getZExtValue()); 55 else { 56 std::vector<unsigned> tmp; 57 tmp.push_back(Val->getZExtValue()); 58 retval[keyname] = tmp; 59 } 60 } 61 } 62 63 static void cacheAnnotationFromMD(const Module *m, const GlobalValue *gv) { 64 NamedMDNode *NMD = m->getNamedMetadata(llvm::NamedMDForAnnotations); 65 if (!NMD) 66 return; 67 key_val_pair_t tmp; 68 for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { 69 const MDNode *elem = NMD->getOperand(i); 70 71 Value *entity = elem->getOperand(0); 72 // entity may be null due to DCE 73 if (!entity) 74 continue; 75 if (entity != gv) 76 continue; 77 78 // accumulate annotations for entity in tmp 79 cacheAnnotationFromMD(elem, tmp); 80 } 81 82 if (tmp.empty()) // no annotations for this gv 83 return; 84 85 if ((*annotationCache).find(m) != (*annotationCache).end()) 86 (*annotationCache)[m][gv] = tmp; 87 else { 88 global_val_annot_t tmp1; 89 tmp1[gv] = tmp; 90 (*annotationCache)[m] = tmp1; 91 } 92 } 93 94 bool llvm::findOneNVVMAnnotation(const GlobalValue *gv, std::string prop, 95 unsigned &retval) { 96 const Module *m = gv->getParent(); 97 if ((*annotationCache).find(m) == (*annotationCache).end()) 98 cacheAnnotationFromMD(m, gv); 99 else if ((*annotationCache)[m].find(gv) == (*annotationCache)[m].end()) 100 cacheAnnotationFromMD(m, gv); 101 if ((*annotationCache)[m][gv].find(prop) == (*annotationCache)[m][gv].end()) 102 return false; 103 retval = (*annotationCache)[m][gv][prop][0]; 104 return true; 105 } 106 107 bool llvm::findAllNVVMAnnotation(const GlobalValue *gv, std::string prop, 108 std::vector<unsigned> &retval) { 109 const Module *m = gv->getParent(); 110 if ((*annotationCache).find(m) == (*annotationCache).end()) 111 cacheAnnotationFromMD(m, gv); 112 else if ((*annotationCache)[m].find(gv) == (*annotationCache)[m].end()) 113 cacheAnnotationFromMD(m, gv); 114 if ((*annotationCache)[m][gv].find(prop) == (*annotationCache)[m][gv].end()) 115 return false; 116 retval = (*annotationCache)[m][gv][prop]; 117 return true; 118 } 119 120 bool llvm::isTexture(const llvm::Value &val) { 121 if (const GlobalValue *gv = dyn_cast<GlobalValue>(&val)) { 122 unsigned annot; 123 if (llvm::findOneNVVMAnnotation(gv, 124 llvm::PropertyAnnotationNames[llvm::PROPERTY_ISTEXTURE], 125 annot)) { 126 assert((annot == 1) && "Unexpected annotation on a texture symbol"); 127 return true; 128 } 129 } 130 return false; 131 } 132 133 bool llvm::isSurface(const llvm::Value &val) { 134 if (const GlobalValue *gv = dyn_cast<GlobalValue>(&val)) { 135 unsigned annot; 136 if (llvm::findOneNVVMAnnotation(gv, 137 llvm::PropertyAnnotationNames[llvm::PROPERTY_ISSURFACE], 138 annot)) { 139 assert((annot == 1) && "Unexpected annotation on a surface symbol"); 140 return true; 141 } 142 } 143 return false; 144 } 145 146 bool llvm::isSampler(const llvm::Value &val) { 147 if (const GlobalValue *gv = dyn_cast<GlobalValue>(&val)) { 148 unsigned annot; 149 if (llvm::findOneNVVMAnnotation(gv, 150 llvm::PropertyAnnotationNames[llvm::PROPERTY_ISSAMPLER], 151 annot)) { 152 assert((annot == 1) && "Unexpected annotation on a sampler symbol"); 153 return true; 154 } 155 } 156 if (const Argument *arg = dyn_cast<Argument>(&val)) { 157 const Function *func = arg->getParent(); 158 std::vector<unsigned> annot; 159 if (llvm::findAllNVVMAnnotation(func, 160 llvm::PropertyAnnotationNames[llvm::PROPERTY_ISSAMPLER], 161 annot)) { 162 if (std::find(annot.begin(), annot.end(), arg->getArgNo()) != annot.end()) 163 return true; 164 } 165 } 166 return false; 167 } 168 169 bool llvm::isImageReadOnly(const llvm::Value &val) { 170 if (const Argument *arg = dyn_cast<Argument>(&val)) { 171 const Function *func = arg->getParent(); 172 std::vector<unsigned> annot; 173 if (llvm::findAllNVVMAnnotation(func, 174 llvm::PropertyAnnotationNames[llvm::PROPERTY_ISREADONLY_IMAGE_PARAM], 175 annot)) { 176 if (std::find(annot.begin(), annot.end(), arg->getArgNo()) != annot.end()) 177 return true; 178 } 179 } 180 return false; 181 } 182 183 bool llvm::isImageWriteOnly(const llvm::Value &val) { 184 if (const Argument *arg = dyn_cast<Argument>(&val)) { 185 const Function *func = arg->getParent(); 186 std::vector<unsigned> annot; 187 if (llvm::findAllNVVMAnnotation(func, 188 llvm::PropertyAnnotationNames[llvm::PROPERTY_ISWRITEONLY_IMAGE_PARAM], 189 annot)) { 190 if (std::find(annot.begin(), annot.end(), arg->getArgNo()) != annot.end()) 191 return true; 192 } 193 } 194 return false; 195 } 196 197 bool llvm::isImage(const llvm::Value &val) { 198 return llvm::isImageReadOnly(val) || llvm::isImageWriteOnly(val); 199 } 200 201 std::string llvm::getTextureName(const llvm::Value &val) { 202 assert(val.hasName() && "Found texture variable with no name"); 203 return val.getName(); 204 } 205 206 std::string llvm::getSurfaceName(const llvm::Value &val) { 207 assert(val.hasName() && "Found surface variable with no name"); 208 return val.getName(); 209 } 210 211 std::string llvm::getSamplerName(const llvm::Value &val) { 212 assert(val.hasName() && "Found sampler variable with no name"); 213 return val.getName(); 214 } 215 216 bool llvm::getMaxNTIDx(const Function &F, unsigned &x) { 217 return (llvm::findOneNVVMAnnotation(&F, 218 llvm::PropertyAnnotationNames[llvm::PROPERTY_MAXNTID_X], 219 x)); 220 } 221 222 bool llvm::getMaxNTIDy(const Function &F, unsigned &y) { 223 return (llvm::findOneNVVMAnnotation(&F, 224 llvm::PropertyAnnotationNames[llvm::PROPERTY_MAXNTID_Y], 225 y)); 226 } 227 228 bool llvm::getMaxNTIDz(const Function &F, unsigned &z) { 229 return (llvm::findOneNVVMAnnotation(&F, 230 llvm::PropertyAnnotationNames[llvm::PROPERTY_MAXNTID_Z], 231 z)); 232 } 233 234 bool llvm::getReqNTIDx(const Function &F, unsigned &x) { 235 return (llvm::findOneNVVMAnnotation(&F, 236 llvm::PropertyAnnotationNames[llvm::PROPERTY_REQNTID_X], 237 x)); 238 } 239 240 bool llvm::getReqNTIDy(const Function &F, unsigned &y) { 241 return (llvm::findOneNVVMAnnotation(&F, 242 llvm::PropertyAnnotationNames[llvm::PROPERTY_REQNTID_Y], 243 y)); 244 } 245 246 bool llvm::getReqNTIDz(const Function &F, unsigned &z) { 247 return (llvm::findOneNVVMAnnotation(&F, 248 llvm::PropertyAnnotationNames[llvm::PROPERTY_REQNTID_Z], 249 z)); 250 } 251 252 bool llvm::getMinCTASm(const Function &F, unsigned &x) { 253 return (llvm::findOneNVVMAnnotation(&F, 254 llvm::PropertyAnnotationNames[llvm::PROPERTY_MINNCTAPERSM], 255 x)); 256 } 257 258 bool llvm::isKernelFunction(const Function &F) { 259 unsigned x = 0; 260 bool retval = llvm::findOneNVVMAnnotation(&F, 261 llvm::PropertyAnnotationNames[llvm::PROPERTY_ISKERNEL_FUNCTION], 262 x); 263 if (retval == false) { 264 // There is no NVVM metadata, check the calling convention 265 if (F.getCallingConv() == llvm::CallingConv::PTX_Kernel) 266 return true; 267 else 268 return false; 269 } 270 return (x==1); 271 } 272 273 bool llvm::getAlign(const Function &F, unsigned index, unsigned &align) { 274 std::vector<unsigned> Vs; 275 bool retval = llvm::findAllNVVMAnnotation(&F, 276 llvm::PropertyAnnotationNames[llvm::PROPERTY_ALIGN], 277 Vs); 278 if (retval == false) 279 return false; 280 for (int i=0, e=Vs.size(); i<e; i++) { 281 unsigned v = Vs[i]; 282 if ( (v >> 16) == index ) { 283 align = v & 0xFFFF; 284 return true; 285 } 286 } 287 return false; 288 } 289 290 bool llvm::getAlign(const CallInst &I, unsigned index, unsigned &align) { 291 if (MDNode *alignNode = I.getMetadata("callalign")) { 292 for (int i=0, n = alignNode->getNumOperands(); 293 i<n; i++) { 294 if (const ConstantInt *CI = 295 dyn_cast<ConstantInt>(alignNode->getOperand(i))) { 296 unsigned v = CI->getZExtValue(); 297 if ( (v>>16) == index ) { 298 align = v & 0xFFFF; 299 return true; 300 } 301 if ( (v>>16) > index ) { 302 return false; 303 } 304 } 305 } 306 } 307 return false; 308 } 309 310 bool llvm::isBarrierIntrinsic(Intrinsic::ID id) { 311 if ((id == Intrinsic::nvvm_barrier0) || 312 (id == Intrinsic::nvvm_barrier0_popc) || 313 (id == Intrinsic::nvvm_barrier0_and) || 314 (id == Intrinsic::nvvm_barrier0_or) || 315 (id == Intrinsic::cuda_syncthreads)) 316 return true; 317 return false; 318 } 319 320 // Interface for checking all memory space transfer related intrinsics 321 bool llvm::isMemorySpaceTransferIntrinsic(Intrinsic::ID id) { 322 if (id == Intrinsic::nvvm_ptr_local_to_gen || 323 id == Intrinsic::nvvm_ptr_shared_to_gen || 324 id == Intrinsic::nvvm_ptr_global_to_gen || 325 id == Intrinsic::nvvm_ptr_constant_to_gen || 326 id == Intrinsic::nvvm_ptr_gen_to_global || 327 id == Intrinsic::nvvm_ptr_gen_to_shared || 328 id == Intrinsic::nvvm_ptr_gen_to_local || 329 id == Intrinsic::nvvm_ptr_gen_to_constant || 330 id == Intrinsic::nvvm_ptr_gen_to_param) { 331 return true; 332 } 333 334 return false; 335 } 336 337 // consider several special intrinsics in striping pointer casts, and 338 // provide an option to ignore GEP indicies for find out the base address only 339 // which could be used in simple alias disambigurate. 340 const Value *llvm::skipPointerTransfer(const Value *V, 341 bool ignore_GEP_indices) { 342 V = V->stripPointerCasts(); 343 while (true) { 344 if (const IntrinsicInst *IS = dyn_cast<IntrinsicInst>(V)) { 345 if (isMemorySpaceTransferIntrinsic(IS->getIntrinsicID())) { 346 V = IS->getArgOperand(0)->stripPointerCasts(); 347 continue; 348 } 349 } else if (ignore_GEP_indices) 350 if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { 351 V = GEP->getPointerOperand()->stripPointerCasts(); 352 continue; 353 } 354 break; 355 } 356 return V; 357 } 358 359 // consider several special intrinsics in striping pointer casts, and 360 // - ignore GEP indicies for find out the base address only, and 361 // - tracking PHINode 362 // which could be used in simple alias disambigurate. 363 const Value *llvm::skipPointerTransfer(const Value *V, 364 std::set<const Value *> &processed) { 365 if (processed.find(V) != processed.end()) 366 return NULL; 367 processed.insert(V); 368 369 const Value *V2 = V->stripPointerCasts(); 370 if (V2 != V && processed.find(V2) != processed.end()) 371 return NULL; 372 processed.insert(V2); 373 374 V = V2; 375 376 while (true) { 377 if (const IntrinsicInst *IS = dyn_cast<IntrinsicInst>(V)) { 378 if (isMemorySpaceTransferIntrinsic(IS->getIntrinsicID())) { 379 V = IS->getArgOperand(0)->stripPointerCasts(); 380 continue; 381 } 382 } else if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { 383 V = GEP->getPointerOperand()->stripPointerCasts(); 384 continue; 385 } else if (const PHINode *PN = dyn_cast<PHINode>(V)) { 386 if (V != V2 && processed.find(V) != processed.end()) 387 return NULL; 388 processed.insert(PN); 389 const Value *common = 0; 390 for (unsigned i = 0; i != PN->getNumIncomingValues(); ++i) { 391 const Value *pv = PN->getIncomingValue(i); 392 const Value *base = skipPointerTransfer(pv, processed); 393 if (base) { 394 if (common == 0) 395 common = base; 396 else if (common != base) 397 return PN; 398 } 399 } 400 if (common == 0) 401 return PN; 402 V = common; 403 } 404 break; 405 } 406 return V; 407 } 408 409 410 // The following are some useful utilities for debuggung 411 412 BasicBlock *llvm::getParentBlock(Value *v) { 413 if (BasicBlock *B = dyn_cast<BasicBlock>(v)) 414 return B; 415 416 if (Instruction *I = dyn_cast<Instruction>(v)) 417 return I->getParent(); 418 419 return 0; 420 } 421 422 Function *llvm::getParentFunction(Value *v) { 423 if (Function *F = dyn_cast<Function>(v)) 424 return F; 425 426 if (Instruction *I = dyn_cast<Instruction>(v)) 427 return I->getParent()->getParent(); 428 429 if (BasicBlock *B = dyn_cast<BasicBlock>(v)) 430 return B->getParent(); 431 432 return 0; 433 } 434 435 // Dump a block by name 436 void llvm::dumpBlock(Value *v, char *blockName) { 437 Function *F = getParentFunction(v); 438 if (F == 0) 439 return; 440 441 for (Function::iterator it = F->begin(), ie = F->end(); it != ie; ++it) { 442 BasicBlock *B = it; 443 if (strcmp(B->getName().data(), blockName) == 0) { 444 B->dump(); 445 return; 446 } 447 } 448 } 449 450 // Find an instruction by name 451 Instruction *llvm::getInst(Value *base, char *instName) { 452 Function *F = getParentFunction(base); 453 if (F == 0) 454 return 0; 455 456 for (inst_iterator it = inst_begin(F), ie = inst_end(F); it != ie; ++it) { 457 Instruction *I = &*it; 458 if (strcmp(I->getName().data(), instName) == 0) { 459 return I; 460 } 461 } 462 463 return 0; 464 } 465 466 // Dump an instruction by nane 467 void llvm::dumpInst(Value *base, char *instName) { 468 Instruction *I = getInst(base, instName); 469 if (I) 470 I->dump(); 471 } 472 473 // Dump an instruction and all dependent instructions 474 void llvm::dumpInstRec(Value *v, std::set<Instruction *> *visited) { 475 if (Instruction *I = dyn_cast<Instruction>(v)) { 476 477 if (visited->find(I) != visited->end()) 478 return; 479 480 visited->insert(I); 481 482 for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) 483 dumpInstRec(I->getOperand(i), visited); 484 485 I->dump(); 486 } 487 } 488 489 // Dump an instruction and all dependent instructions 490 void llvm::dumpInstRec(Value *v) { 491 std::set<Instruction *> visited; 492 493 //BasicBlock *B = getParentBlock(v); 494 495 dumpInstRec(v, &visited); 496 } 497 498 // Dump the parent for Instruction, block or function 499 void llvm::dumpParent(Value *v) { 500 if (Instruction *I = dyn_cast<Instruction>(v)) { 501 I->getParent()->dump(); 502 return; 503 } 504 505 if (BasicBlock *B = dyn_cast<BasicBlock>(v)) { 506 B->getParent()->dump(); 507 return; 508 } 509 510 if (Function *F = dyn_cast<Function>(v)) { 511 F->getParent()->dump(); 512 return; 513 } 514 } 515