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