Home | History | Annotate | Download | only in NVPTX
      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