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