/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/NVPTX/NVPTXUtilities.cpp
Line | Count | Source (jump to first uncovered line) |
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/InstIterator.h" |
19 | | #include "llvm/IR/Module.h" |
20 | | #include "llvm/IR/Operator.h" |
21 | | #include "llvm/Support/ManagedStatic.h" |
22 | | #include "llvm/Support/MutexGuard.h" |
23 | | #include <algorithm> |
24 | | #include <cstring> |
25 | | #include <map> |
26 | | #include <string> |
27 | | #include <vector> |
28 | | |
29 | | namespace llvm { |
30 | | |
31 | | namespace { |
32 | | typedef std::map<std::string, std::vector<unsigned> > key_val_pair_t; |
33 | | typedef std::map<const GlobalValue *, key_val_pair_t> global_val_annot_t; |
34 | | typedef std::map<const Module *, global_val_annot_t> per_module_annot_t; |
35 | | } // anonymous namespace |
36 | | |
37 | | static ManagedStatic<per_module_annot_t> annotationCache; |
38 | | static sys::Mutex Lock; |
39 | | |
40 | 224 | void clearAnnotationCache(const Module *Mod) { |
41 | 224 | MutexGuard Guard(Lock); |
42 | 224 | annotationCache->erase(Mod); |
43 | 224 | } |
44 | | |
45 | 122 | static void cacheAnnotationFromMD(const MDNode *md, key_val_pair_t &retval) { |
46 | 122 | MutexGuard Guard(Lock); |
47 | 122 | assert(md && "Invalid mdnode for annotation"); |
48 | 122 | assert((md->getNumOperands() % 2) == 1 && "Invalid number of operands"); |
49 | 122 | // start index = 1, to skip the global variable key |
50 | 122 | // increment = 2, to skip the value for each property-value pairs |
51 | 254 | for (unsigned i = 1, e = md->getNumOperands(); i != e254 ; i += 2132 ) { |
52 | 132 | // property |
53 | 132 | const MDString *prop = dyn_cast<MDString>(md->getOperand(i)); |
54 | 132 | assert(prop && "Annotation property not a string"); |
55 | 132 | |
56 | 132 | // value |
57 | 132 | ConstantInt *Val = mdconst::dyn_extract<ConstantInt>(md->getOperand(i + 1)); |
58 | 132 | assert(Val && "Value operand not a constant int"); |
59 | 132 | |
60 | 132 | std::string keyname = prop->getString().str(); |
61 | 132 | if (retval.find(keyname) != retval.end()) |
62 | 0 | retval[keyname].push_back(Val->getZExtValue()); |
63 | 132 | else { |
64 | 132 | std::vector<unsigned> tmp; |
65 | 132 | tmp.push_back(Val->getZExtValue()); |
66 | 132 | retval[keyname] = tmp; |
67 | 132 | } |
68 | 132 | } |
69 | 122 | } |
70 | | |
71 | 1.64k | static void cacheAnnotationFromMD(const Module *m, const GlobalValue *gv) { |
72 | 1.64k | MutexGuard Guard(Lock); |
73 | 1.64k | NamedMDNode *NMD = m->getNamedMetadata("nvvm.annotations"); |
74 | 1.64k | if (!NMD) |
75 | 1.48k | return; |
76 | 162 | key_val_pair_t tmp; |
77 | 1.30k | for (unsigned i = 0, e = NMD->getNumOperands(); i != e1.30k ; ++i1.13k ) { |
78 | 1.13k | const MDNode *elem = NMD->getOperand(i); |
79 | 1.13k | |
80 | 1.13k | GlobalValue *entity = |
81 | 1.13k | mdconst::dyn_extract_or_null<GlobalValue>(elem->getOperand(0)); |
82 | 1.13k | // entity may be null due to DCE |
83 | 1.13k | if (!entity) |
84 | 0 | continue; |
85 | 1.13k | if (1.13k entity != gv1.13k ) |
86 | 1.01k | continue; |
87 | 122 | |
88 | 122 | // accumulate annotations for entity in tmp |
89 | 122 | cacheAnnotationFromMD(elem, tmp); |
90 | 122 | } |
91 | 162 | |
92 | 162 | if (tmp.empty()) // no annotations for this gv |
93 | 54 | return; |
94 | 108 | |
95 | 108 | if (108 (*annotationCache).find(m) != (*annotationCache).end()108 ) |
96 | 80 | (*annotationCache)[m][gv] = std::move(tmp); |
97 | 28 | else { |
98 | 28 | global_val_annot_t tmp1; |
99 | 28 | tmp1[gv] = std::move(tmp); |
100 | 28 | (*annotationCache)[m] = std::move(tmp1); |
101 | 28 | } |
102 | 1.64k | } |
103 | | |
104 | | bool findOneNVVMAnnotation(const GlobalValue *gv, const std::string &prop, |
105 | 9.71k | unsigned &retval) { |
106 | 9.71k | MutexGuard Guard(Lock); |
107 | 9.71k | const Module *m = gv->getParent(); |
108 | 9.71k | if ((*annotationCache).find(m) == (*annotationCache).end()) |
109 | 206 | cacheAnnotationFromMD(m, gv); |
110 | 9.51k | else if (9.51k (*annotationCache)[m].find(gv) == (*annotationCache)[m].end()9.51k ) |
111 | 1.42k | cacheAnnotationFromMD(m, gv); |
112 | 9.71k | if ((*annotationCache)[m][gv].find(prop) == (*annotationCache)[m][gv].end()) |
113 | 9.13k | return false; |
114 | 581 | retval = (*annotationCache)[m][gv][prop][0]; |
115 | 581 | return true; |
116 | 581 | } |
117 | | |
118 | | bool findAllNVVMAnnotation(const GlobalValue *gv, const std::string &prop, |
119 | 1.26k | std::vector<unsigned> &retval) { |
120 | 1.26k | MutexGuard Guard(Lock); |
121 | 1.26k | const Module *m = gv->getParent(); |
122 | 1.26k | if ((*annotationCache).find(m) == (*annotationCache).end()) |
123 | 0 | cacheAnnotationFromMD(m, gv); |
124 | 1.26k | else if (1.26k (*annotationCache)[m].find(gv) == (*annotationCache)[m].end()1.26k ) |
125 | 12 | cacheAnnotationFromMD(m, gv); |
126 | 1.26k | if ((*annotationCache)[m][gv].find(prop) == (*annotationCache)[m][gv].end()) |
127 | 1.24k | return false; |
128 | 26 | retval = (*annotationCache)[m][gv][prop]; |
129 | 26 | return true; |
130 | 26 | } |
131 | | |
132 | 103 | bool isTexture(const Value &val) { |
133 | 103 | if (const GlobalValue *gv103 = dyn_cast<GlobalValue>(&val)) { |
134 | 103 | unsigned annot; |
135 | 103 | if (findOneNVVMAnnotation(gv, "texture", annot)103 ) { |
136 | 6 | assert((annot == 1) && "Unexpected annotation on a texture symbol"); |
137 | 6 | return true; |
138 | 6 | } |
139 | 97 | } |
140 | 97 | return false; |
141 | 97 | } |
142 | | |
143 | 97 | bool isSurface(const Value &val) { |
144 | 97 | if (const GlobalValue *gv97 = dyn_cast<GlobalValue>(&val)) { |
145 | 97 | unsigned annot; |
146 | 97 | if (findOneNVVMAnnotation(gv, "surface", annot)97 ) { |
147 | 8 | assert((annot == 1) && "Unexpected annotation on a surface symbol"); |
148 | 8 | return true; |
149 | 8 | } |
150 | 89 | } |
151 | 89 | return false; |
152 | 89 | } |
153 | | |
154 | 266 | bool isSampler(const Value &val) { |
155 | 266 | const char *AnnotationName = "sampler"; |
156 | 266 | |
157 | 266 | if (const GlobalValue *gv266 = dyn_cast<GlobalValue>(&val)) { |
158 | 86 | unsigned annot; |
159 | 86 | if (findOneNVVMAnnotation(gv, AnnotationName, annot)86 ) { |
160 | 0 | assert((annot == 1) && "Unexpected annotation on a sampler symbol"); |
161 | 0 | return true; |
162 | 0 | } |
163 | 266 | } |
164 | 266 | if (const Argument *266 arg266 = dyn_cast<Argument>(&val)) { |
165 | 180 | const Function *func = arg->getParent(); |
166 | 180 | std::vector<unsigned> annot; |
167 | 180 | if (findAllNVVMAnnotation(func, AnnotationName, annot)180 ) { |
168 | 7 | if (is_contained(annot, arg->getArgNo())) |
169 | 2 | return true; |
170 | 264 | } |
171 | 180 | } |
172 | 264 | return false; |
173 | 264 | } |
174 | | |
175 | 184 | bool isImageReadOnly(const Value &val) { |
176 | 184 | if (const Argument *arg184 = dyn_cast<Argument>(&val)) { |
177 | 184 | const Function *func = arg->getParent(); |
178 | 184 | std::vector<unsigned> annot; |
179 | 184 | if (findAllNVVMAnnotation(func, "rdoimage", annot)184 ) { |
180 | 9 | if (is_contained(annot, arg->getArgNo())) |
181 | 4 | return true; |
182 | 180 | } |
183 | 184 | } |
184 | 180 | return false; |
185 | 180 | } |
186 | | |
187 | 184 | bool isImageWriteOnly(const Value &val) { |
188 | 184 | if (const Argument *arg184 = dyn_cast<Argument>(&val)) { |
189 | 184 | const Function *func = arg->getParent(); |
190 | 184 | std::vector<unsigned> annot; |
191 | 184 | if (findAllNVVMAnnotation(func, "wroimage", annot)184 ) { |
192 | 5 | if (is_contained(annot, arg->getArgNo())) |
193 | 3 | return true; |
194 | 181 | } |
195 | 184 | } |
196 | 181 | return false; |
197 | 181 | } |
198 | | |
199 | 181 | bool isImageReadWrite(const Value &val) { |
200 | 181 | if (const Argument *arg181 = dyn_cast<Argument>(&val)) { |
201 | 181 | const Function *func = arg->getParent(); |
202 | 181 | std::vector<unsigned> annot; |
203 | 181 | if (findAllNVVMAnnotation(func, "rdwrimage", annot)181 ) { |
204 | 5 | if (is_contained(annot, arg->getArgNo())) |
205 | 3 | return true; |
206 | 178 | } |
207 | 181 | } |
208 | 178 | return false; |
209 | 178 | } |
210 | | |
211 | 184 | bool isImage(const Value &val) { |
212 | 184 | return isImageReadOnly(val) || isImageWriteOnly(val)180 || isImageReadWrite(val)178 ; |
213 | 184 | } |
214 | | |
215 | 54 | bool isManaged(const Value &val) { |
216 | 54 | if(const GlobalValue *gv54 = dyn_cast<GlobalValue>(&val)) { |
217 | 54 | unsigned annot; |
218 | 54 | if (findOneNVVMAnnotation(gv, "managed", annot)54 ) { |
219 | 1 | assert((annot == 1) && "Unexpected annotation on a managed symbol"); |
220 | 1 | return true; |
221 | 1 | } |
222 | 53 | } |
223 | 53 | return false; |
224 | 53 | } |
225 | | |
226 | 6 | std::string getTextureName(const Value &val) { |
227 | 6 | assert(val.hasName() && "Found texture variable with no name"); |
228 | 6 | return val.getName(); |
229 | 6 | } |
230 | | |
231 | 8 | std::string getSurfaceName(const Value &val) { |
232 | 8 | assert(val.hasName() && "Found surface variable with no name"); |
233 | 8 | return val.getName(); |
234 | 8 | } |
235 | | |
236 | 0 | std::string getSamplerName(const Value &val) { |
237 | 0 | assert(val.hasName() && "Found sampler variable with no name"); |
238 | 0 | return val.getName(); |
239 | 0 | } |
240 | | |
241 | 96 | bool getMaxNTIDx(const Function &F, unsigned &x) { |
242 | 96 | return findOneNVVMAnnotation(&F, "maxntidx", x); |
243 | 96 | } |
244 | | |
245 | 96 | bool getMaxNTIDy(const Function &F, unsigned &y) { |
246 | 96 | return findOneNVVMAnnotation(&F, "maxntidy", y); |
247 | 96 | } |
248 | | |
249 | 96 | bool getMaxNTIDz(const Function &F, unsigned &z) { |
250 | 96 | return findOneNVVMAnnotation(&F, "maxntidz", z); |
251 | 96 | } |
252 | | |
253 | 96 | bool getReqNTIDx(const Function &F, unsigned &x) { |
254 | 96 | return findOneNVVMAnnotation(&F, "reqntidx", x); |
255 | 96 | } |
256 | | |
257 | 96 | bool getReqNTIDy(const Function &F, unsigned &y) { |
258 | 96 | return findOneNVVMAnnotation(&F, "reqntidy", y); |
259 | 96 | } |
260 | | |
261 | 96 | bool getReqNTIDz(const Function &F, unsigned &z) { |
262 | 96 | return findOneNVVMAnnotation(&F, "reqntidz", z); |
263 | 96 | } |
264 | | |
265 | 96 | bool getMinCTASm(const Function &F, unsigned &x) { |
266 | 96 | return findOneNVVMAnnotation(&F, "minctasm", x); |
267 | 96 | } |
268 | | |
269 | 96 | bool getMaxNReg(const Function &F, unsigned &x) { |
270 | 96 | return findOneNVVMAnnotation(&F, "maxnreg", x); |
271 | 96 | } |
272 | | |
273 | 8.60k | bool isKernelFunction(const Function &F) { |
274 | 8.60k | unsigned x = 0; |
275 | 8.60k | bool retval = findOneNVVMAnnotation(&F, "kernel", x); |
276 | 8.60k | if (!retval8.60k ) { |
277 | 8.06k | // There is no NVVM metadata, check the calling convention |
278 | 8.06k | return F.getCallingConv() == CallingConv::PTX_Kernel; |
279 | 8.06k | } |
280 | 547 | return (x == 1); |
281 | 547 | } |
282 | | |
283 | 539 | bool getAlign(const Function &F, unsigned index, unsigned &align) { |
284 | 539 | std::vector<unsigned> Vs; |
285 | 539 | bool retval = findAllNVVMAnnotation(&F, "align", Vs); |
286 | 539 | if (!retval) |
287 | 539 | return false; |
288 | 0 | for (int i = 0, e = Vs.size(); 0 i < e0 ; i++0 ) { |
289 | 0 | unsigned v = Vs[i]; |
290 | 0 | if ((v >> 16) == index0 ) { |
291 | 0 | align = v & 0xFFFF; |
292 | 0 | return true; |
293 | 0 | } |
294 | 0 | } |
295 | 0 | return false; |
296 | 539 | } |
297 | | |
298 | 3 | bool getAlign(const CallInst &I, unsigned index, unsigned &align) { |
299 | 3 | if (MDNode *alignNode3 = I.getMetadata("callalign")) { |
300 | 0 | for (int i = 0, n = alignNode->getNumOperands(); i < n0 ; i++0 ) { |
301 | 0 | if (const ConstantInt *CI = |
302 | 0 | mdconst::dyn_extract<ConstantInt>(alignNode->getOperand(i))) { |
303 | 0 | unsigned v = CI->getZExtValue(); |
304 | 0 | if ((v >> 16) == index0 ) { |
305 | 0 | align = v & 0xFFFF; |
306 | 0 | return true; |
307 | 0 | } |
308 | 0 | if (0 (v >> 16) > index0 ) { |
309 | 0 | return false; |
310 | 0 | } |
311 | 0 | } |
312 | 0 | } |
313 | 0 | } |
314 | 3 | return false; |
315 | 3 | } |
316 | | |
317 | | } // namespace llvm |