Coverage Report

Created: 2019-07-24 05:18

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