LLVM  10.0.0svn
NVPTXUtilities.cpp
Go to the documentation of this file.
1 //===- NVPTXUtilities.cpp - Utility Functions -----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains miscellaneous utility functions
10 //
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"
22 #include "llvm/Support/Mutex.h"
23 #include <algorithm>
24 #include <cstring>
25 #include <map>
26 #include <mutex>
27 #include <string>
28 #include <vector>
29 
30 namespace llvm {
31 
32 namespace {
33 typedef std::map<std::string, std::vector<unsigned> > key_val_pair_t;
34 typedef std::map<const GlobalValue *, key_val_pair_t> global_val_annot_t;
35 typedef std::map<const Module *, global_val_annot_t> per_module_annot_t;
36 } // anonymous namespace
37 
40 
41 void clearAnnotationCache(const Module *Mod) {
42  std::lock_guard<sys::Mutex> Guard(Lock);
43  annotationCache->erase(Mod);
44 }
45 
46 static void cacheAnnotationFromMD(const MDNode *md, key_val_pair_t &retval) {
47  std::lock_guard<sys::Mutex> Guard(Lock);
48  assert(md && "Invalid mdnode for annotation");
49  assert((md->getNumOperands() % 2) == 1 && "Invalid number of operands");
50  // start index = 1, to skip the global variable key
51  // increment = 2, to skip the value for each property-value pairs
52  for (unsigned i = 1, e = md->getNumOperands(); i != e; i += 2) {
53  // property
54  const MDString *prop = dyn_cast<MDString>(md->getOperand(i));
55  assert(prop && "Annotation property not a string");
56 
57  // value
58  ConstantInt *Val = mdconst::dyn_extract<ConstantInt>(md->getOperand(i + 1));
59  assert(Val && "Value operand not a constant int");
60 
61  std::string keyname = prop->getString().str();
62  if (retval.find(keyname) != retval.end())
63  retval[keyname].push_back(Val->getZExtValue());
64  else {
65  std::vector<unsigned> tmp;
66  tmp.push_back(Val->getZExtValue());
67  retval[keyname] = tmp;
68  }
69  }
70 }
71 
72 static void cacheAnnotationFromMD(const Module *m, const GlobalValue *gv) {
73  std::lock_guard<sys::Mutex> Guard(Lock);
74  NamedMDNode *NMD = m->getNamedMetadata("nvvm.annotations");
75  if (!NMD)
76  return;
77  key_val_pair_t tmp;
78  for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
79  const MDNode *elem = NMD->getOperand(i);
80 
81  GlobalValue *entity =
82  mdconst::dyn_extract_or_null<GlobalValue>(elem->getOperand(0));
83  // entity may be null due to DCE
84  if (!entity)
85  continue;
86  if (entity != gv)
87  continue;
88 
89  // accumulate annotations for entity in tmp
90  cacheAnnotationFromMD(elem, tmp);
91  }
92 
93  if (tmp.empty()) // no annotations for this gv
94  return;
95 
96  if ((*annotationCache).find(m) != (*annotationCache).end())
97  (*annotationCache)[m][gv] = std::move(tmp);
98  else {
99  global_val_annot_t tmp1;
100  tmp1[gv] = std::move(tmp);
101  (*annotationCache)[m] = std::move(tmp1);
102  }
103 }
104 
105 bool findOneNVVMAnnotation(const GlobalValue *gv, const std::string &prop,
106  unsigned &retval) {
107  std::lock_guard<sys::Mutex> Guard(Lock);
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][0];
116  return true;
117 }
118 
119 bool findAllNVVMAnnotation(const GlobalValue *gv, const std::string &prop,
120  std::vector<unsigned> &retval) {
121  std::lock_guard<sys::Mutex> Guard(Lock);
122  const Module *m = gv->getParent();
123  if ((*annotationCache).find(m) == (*annotationCache).end())
124  cacheAnnotationFromMD(m, gv);
125  else if ((*annotationCache)[m].find(gv) == (*annotationCache)[m].end())
126  cacheAnnotationFromMD(m, gv);
127  if ((*annotationCache)[m][gv].find(prop) == (*annotationCache)[m][gv].end())
128  return false;
129  retval = (*annotationCache)[m][gv][prop];
130  return true;
131 }
132 
133 bool isTexture(const Value &val) {
134  if (const GlobalValue *gv = dyn_cast<GlobalValue>(&val)) {
135  unsigned annot;
136  if (findOneNVVMAnnotation(gv, "texture", annot)) {
137  assert((annot == 1) && "Unexpected annotation on a texture symbol");
138  return true;
139  }
140  }
141  return false;
142 }
143 
144 bool isSurface(const Value &val) {
145  if (const GlobalValue *gv = dyn_cast<GlobalValue>(&val)) {
146  unsigned annot;
147  if (findOneNVVMAnnotation(gv, "surface", annot)) {
148  assert((annot == 1) && "Unexpected annotation on a surface symbol");
149  return true;
150  }
151  }
152  return false;
153 }
154 
155 bool isSampler(const Value &val) {
156  const char *AnnotationName = "sampler";
157 
158  if (const GlobalValue *gv = dyn_cast<GlobalValue>(&val)) {
159  unsigned annot;
160  if (findOneNVVMAnnotation(gv, AnnotationName, annot)) {
161  assert((annot == 1) && "Unexpected annotation on a sampler symbol");
162  return true;
163  }
164  }
165  if (const Argument *arg = dyn_cast<Argument>(&val)) {
166  const Function *func = arg->getParent();
167  std::vector<unsigned> annot;
168  if (findAllNVVMAnnotation(func, AnnotationName, annot)) {
169  if (is_contained(annot, arg->getArgNo()))
170  return true;
171  }
172  }
173  return false;
174 }
175 
176 bool isImageReadOnly(const Value &val) {
177  if (const Argument *arg = dyn_cast<Argument>(&val)) {
178  const Function *func = arg->getParent();
179  std::vector<unsigned> annot;
180  if (findAllNVVMAnnotation(func, "rdoimage", annot)) {
181  if (is_contained(annot, arg->getArgNo()))
182  return true;
183  }
184  }
185  return false;
186 }
187 
188 bool isImageWriteOnly(const Value &val) {
189  if (const Argument *arg = dyn_cast<Argument>(&val)) {
190  const Function *func = arg->getParent();
191  std::vector<unsigned> annot;
192  if (findAllNVVMAnnotation(func, "wroimage", annot)) {
193  if (is_contained(annot, arg->getArgNo()))
194  return true;
195  }
196  }
197  return false;
198 }
199 
200 bool isImageReadWrite(const Value &val) {
201  if (const Argument *arg = dyn_cast<Argument>(&val)) {
202  const Function *func = arg->getParent();
203  std::vector<unsigned> annot;
204  if (findAllNVVMAnnotation(func, "rdwrimage", annot)) {
205  if (is_contained(annot, arg->getArgNo()))
206  return true;
207  }
208  }
209  return false;
210 }
211 
212 bool isImage(const Value &val) {
213  return isImageReadOnly(val) || isImageWriteOnly(val) || isImageReadWrite(val);
214 }
215 
216 bool isManaged(const Value &val) {
217  if(const GlobalValue *gv = dyn_cast<GlobalValue>(&val)) {
218  unsigned annot;
219  if (findOneNVVMAnnotation(gv, "managed", annot)) {
220  assert((annot == 1) && "Unexpected annotation on a managed symbol");
221  return true;
222  }
223  }
224  return false;
225 }
226 
227 std::string getTextureName(const Value &val) {
228  assert(val.hasName() && "Found texture variable with no name");
229  return val.getName();
230 }
231 
232 std::string getSurfaceName(const Value &val) {
233  assert(val.hasName() && "Found surface variable with no name");
234  return val.getName();
235 }
236 
237 std::string getSamplerName(const Value &val) {
238  assert(val.hasName() && "Found sampler variable with no name");
239  return val.getName();
240 }
241 
242 bool getMaxNTIDx(const Function &F, unsigned &x) {
243  return findOneNVVMAnnotation(&F, "maxntidx", x);
244 }
245 
246 bool getMaxNTIDy(const Function &F, unsigned &y) {
247  return findOneNVVMAnnotation(&F, "maxntidy", y);
248 }
249 
250 bool getMaxNTIDz(const Function &F, unsigned &z) {
251  return findOneNVVMAnnotation(&F, "maxntidz", z);
252 }
253 
254 bool getReqNTIDx(const Function &F, unsigned &x) {
255  return findOneNVVMAnnotation(&F, "reqntidx", x);
256 }
257 
258 bool getReqNTIDy(const Function &F, unsigned &y) {
259  return findOneNVVMAnnotation(&F, "reqntidy", y);
260 }
261 
262 bool getReqNTIDz(const Function &F, unsigned &z) {
263  return findOneNVVMAnnotation(&F, "reqntidz", z);
264 }
265 
266 bool getMinCTASm(const Function &F, unsigned &x) {
267  return findOneNVVMAnnotation(&F, "minctasm", x);
268 }
269 
270 bool getMaxNReg(const Function &F, unsigned &x) {
271  return findOneNVVMAnnotation(&F, "maxnreg", x);
272 }
273 
275  unsigned x = 0;
276  bool retval = findOneNVVMAnnotation(&F, "kernel", x);
277  if (!retval) {
278  // There is no NVVM metadata, check the calling convention
280  }
281  return (x == 1);
282 }
283 
284 bool getAlign(const Function &F, unsigned index, unsigned &align) {
285  std::vector<unsigned> Vs;
286  bool retval = findAllNVVMAnnotation(&F, "align", Vs);
287  if (!retval)
288  return false;
289  for (int i = 0, e = Vs.size(); i < e; i++) {
290  unsigned v = Vs[i];
291  if ((v >> 16) == index) {
292  align = v & 0xFFFF;
293  return true;
294  }
295  }
296  return false;
297 }
298 
299 bool getAlign(const CallInst &I, unsigned index, unsigned &align) {
300  if (MDNode *alignNode = I.getMetadata("callalign")) {
301  for (int i = 0, n = alignNode->getNumOperands(); i < n; i++) {
302  if (const ConstantInt *CI =
303  mdconst::dyn_extract<ConstantInt>(alignNode->getOperand(i))) {
304  unsigned v = CI->getZExtValue();
305  if ((v >> 16) == index) {
306  align = v & 0xFFFF;
307  return true;
308  }
309  if ((v >> 16) > index) {
310  return false;
311  }
312  }
313  }
314  }
315  return false;
316 }
317 
318 } // namespace llvm
PTX_Kernel - Call to a PTX kernel.
Definition: CallingConv.h:119
This class represents an incoming formal argument to a Function.
Definition: Argument.h:29
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:232
bool getAlign(const Function &F, unsigned index, unsigned &align)
MDNode * getOperand(unsigned i) const
Definition: Metadata.cpp:1080
This class represents lattice values for constants.
Definition: AllocatorList.h:23
bool getMaxNReg(const Function &F, unsigned &x)
bool findOneNVVMAnnotation(const GlobalValue *gv, const std::string &prop, unsigned &retval)
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
bool findAllNVVMAnnotation(const GlobalValue *gv, const std::string &prop, std::vector< unsigned > &retval)
bool isTexture(const Value &val)
This class represents a function call, abstracting a target machine&#39;s calling convention.
static sys::Mutex Lock
Metadata node.
Definition: Metadata.h:863
F(f)
const MDOperand & getOperand(unsigned I) const
Definition: Metadata.h:1068
A tuple of MDNodes.
Definition: Metadata.h:1325
void clearAnnotationCache(const Module *Mod)
unsigned getNumOperands() const
Definition: Metadata.cpp:1076
bool getMaxNTIDz(const Function &F, unsigned &z)
bool isKernelFunction(const Function &F)
bool isSurface(const Value &val)
bool getMaxNTIDx(const Function &F, unsigned &x)
std::string getTextureName(const Value &val)
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
Definition: Module.cpp:250
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
Definition: Instruction.h:244
bool isSampler(const Value &val)
StringRef getString() const
Definition: Metadata.cpp:463
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition: Constants.h:148
bool hasName() const
Definition: Value.h:251
This file contains the declarations for the subclasses of Constant, which represent the different fla...
constexpr double e
Definition: MathExtras.h:57
bool getMaxNTIDy(const Function &F, unsigned &y)
bool getReqNTIDx(const Function &F, unsigned &x)
bool isImage(const Value &val)
bool getReqNTIDz(const Function &F, unsigned &z)
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition: Function.h:212
Module.h This file contains the declarations for the Module class.
bool isImageReadWrite(const Value &val)
std::string getSurfaceName(const Value &val)
std::string getSamplerName(const Value &val)
bool isManaged(const Value &val)
bool getReqNTIDy(const Function &F, unsigned &y)
bool isImageReadOnly(const Value &val)
static void cacheAnnotationFromMD(const MDNode *md, key_val_pair_t &retval)
static ManagedStatic< per_module_annot_t > annotationCache
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:214
#define I(x, y, z)
Definition: MD5.cpp:58
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:332
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:575
LLVM Value Representation.
Definition: Value.h:73
A single uniqued string.
Definition: Metadata.h:603
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:83
bool getMinCTASm(const Function &F, unsigned &x)
unsigned getNumOperands() const
Return number of MDNode operands.
Definition: Metadata.h:1074
bool isImageWriteOnly(const Value &val)
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1224