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 29using namespace llvm; 30 31typedef std::map<std::string, std::vector<unsigned> > key_val_pair_t; 32typedef std::map<const GlobalValue *, key_val_pair_t> global_val_annot_t; 33typedef std::map<const Module *, global_val_annot_t> per_module_annot_t; 34 35ManagedStatic<per_module_annot_t> annotationCache; 36 37 38static 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 63static 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 94bool 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 107bool 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 120bool 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 133bool 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 146bool 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 169bool 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 183bool 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 197bool llvm::isImage(const llvm::Value &val) { 198 return llvm::isImageReadOnly(val) || llvm::isImageWriteOnly(val); 199} 200 201std::string llvm::getTextureName(const llvm::Value &val) { 202 assert(val.hasName() && "Found texture variable with no name"); 203 return val.getName(); 204} 205 206std::string llvm::getSurfaceName(const llvm::Value &val) { 207 assert(val.hasName() && "Found surface variable with no name"); 208 return val.getName(); 209} 210 211std::string llvm::getSamplerName(const llvm::Value &val) { 212 assert(val.hasName() && "Found sampler variable with no name"); 213 return val.getName(); 214} 215 216bool llvm::getMaxNTIDx(const Function &F, unsigned &x) { 217 return (llvm::findOneNVVMAnnotation(&F, 218 llvm::PropertyAnnotationNames[llvm::PROPERTY_MAXNTID_X], 219 x)); 220} 221 222bool llvm::getMaxNTIDy(const Function &F, unsigned &y) { 223 return (llvm::findOneNVVMAnnotation(&F, 224 llvm::PropertyAnnotationNames[llvm::PROPERTY_MAXNTID_Y], 225 y)); 226} 227 228bool llvm::getMaxNTIDz(const Function &F, unsigned &z) { 229 return (llvm::findOneNVVMAnnotation(&F, 230 llvm::PropertyAnnotationNames[llvm::PROPERTY_MAXNTID_Z], 231 z)); 232} 233 234bool llvm::getReqNTIDx(const Function &F, unsigned &x) { 235 return (llvm::findOneNVVMAnnotation(&F, 236 llvm::PropertyAnnotationNames[llvm::PROPERTY_REQNTID_X], 237 x)); 238} 239 240bool llvm::getReqNTIDy(const Function &F, unsigned &y) { 241 return (llvm::findOneNVVMAnnotation(&F, 242 llvm::PropertyAnnotationNames[llvm::PROPERTY_REQNTID_Y], 243 y)); 244} 245 246bool llvm::getReqNTIDz(const Function &F, unsigned &z) { 247 return (llvm::findOneNVVMAnnotation(&F, 248 llvm::PropertyAnnotationNames[llvm::PROPERTY_REQNTID_Z], 249 z)); 250} 251 252bool llvm::getMinCTASm(const Function &F, unsigned &x) { 253 return (llvm::findOneNVVMAnnotation(&F, 254 llvm::PropertyAnnotationNames[llvm::PROPERTY_MINNCTAPERSM], 255 x)); 256} 257 258bool 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 273bool 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 290bool 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 310bool 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 321bool 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. 340const 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. 363const 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 412BasicBlock *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 422Function *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 436void 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 451Instruction *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 467void 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 474void 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 490void 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 499void 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