Coverage Report

Created: 2018-07-10 14:28

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUHSAMetadataStreamer.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- AMDGPUHSAMetadataStreamer.cpp --------------------------*- C++ -*-===//
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
/// \file
11
/// AMDGPU HSA Metadata Streamer.
12
///
13
//
14
//===----------------------------------------------------------------------===//
15
16
#include "AMDGPUHSAMetadataStreamer.h"
17
#include "AMDGPU.h"
18
#include "llvm/ADT/StringSwitch.h"
19
#include "llvm/IR/Constants.h"
20
#include "llvm/IR/Module.h"
21
#include "llvm/Support/raw_ostream.h"
22
23
namespace llvm {
24
25
static cl::opt<bool> DumpHSAMetadata(
26
    "amdgpu-dump-hsa-metadata",
27
    cl::desc("Dump AMDGPU HSA Metadata"));
28
static cl::opt<bool> VerifyHSAMetadata(
29
    "amdgpu-verify-hsa-metadata",
30
    cl::desc("Verify AMDGPU HSA Metadata"));
31
32
namespace AMDGPU {
33
namespace HSAMD {
34
35
4
void MetadataStreamer::dump(StringRef HSAMetadataString) const {
36
4
  errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
37
4
}
38
39
4
void MetadataStreamer::verify(StringRef HSAMetadataString) const {
40
4
  errs() << "AMDGPU HSA Metadata Parser Test: ";
41
4
42
4
  HSAMD::Metadata FromHSAMetadataString;
43
4
  if (fromString(HSAMetadataString, FromHSAMetadataString)) {
44
0
    errs() << "FAIL\n";
45
0
    return;
46
0
  }
47
4
48
4
  std::string ToHSAMetadataString;
49
4
  if (toString(FromHSAMetadataString, ToHSAMetadataString)) {
50
0
    errs() << "FAIL\n";
51
0
    return;
52
0
  }
53
4
54
4
  errs() << (HSAMetadataString == ToHSAMetadataString ? "PASS" : 
"FAIL"0
)
55
4
         << '\n';
56
4
  if (HSAMetadataString != ToHSAMetadataString) {
57
0
    errs() << "Original input: " << HSAMetadataString << '\n'
58
0
           << "Produced output: " << ToHSAMetadataString << '\n';
59
0
  }
60
4
}
61
62
5.67k
AccessQualifier MetadataStreamer::getAccessQualifier(StringRef AccQual) const {
63
5.67k
  if (AccQual.empty())
64
5.33k
    return AccessQualifier::Unknown;
65
337
66
337
  return StringSwitch<AccessQualifier>(AccQual)
67
337
             .Case("read_only",  AccessQualifier::ReadOnly)
68
337
             .Case("write_only", AccessQualifier::WriteOnly)
69
337
             .Case("read_write", AccessQualifier::ReadWrite)
70
337
             .Default(AccessQualifier::Default);
71
337
}
72
73
AddressSpaceQualifier MetadataStreamer::getAddressSpaceQualifer(
74
3.46k
    unsigned AddressSpace) const {
75
3.46k
  if (AddressSpace == AMDGPUASI.PRIVATE_ADDRESS)
76
22
    return AddressSpaceQualifier::Private;
77
3.44k
  if (AddressSpace == AMDGPUASI.GLOBAL_ADDRESS)
78
2.78k
    return AddressSpaceQualifier::Global;
79
660
  if (AddressSpace == AMDGPUASI.CONSTANT_ADDRESS)
80
206
    return AddressSpaceQualifier::Constant;
81
454
  if (AddressSpace == AMDGPUASI.LOCAL_ADDRESS)
82
175
    return AddressSpaceQualifier::Local;
83
279
  if (AddressSpace == AMDGPUASI.FLAT_ADDRESS)
84
278
    return AddressSpaceQualifier::Generic;
85
1
  if (AddressSpace == AMDGPUASI.REGION_ADDRESS)
86
1
    return AddressSpaceQualifier::Region;
87
0
88
0
  llvm_unreachable("Unknown address space qualifier");
89
0
}
90
91
ValueKind MetadataStreamer::getValueKind(Type *Ty, StringRef TypeQual,
92
4.34k
                                         StringRef BaseTypeName) const {
93
4.34k
  if (TypeQual.find("pipe") != StringRef::npos)
94
6
    return ValueKind::Pipe;
95
4.33k
96
4.33k
  return StringSwitch<ValueKind>(BaseTypeName)
97
4.33k
             .Case("image1d_t", ValueKind::Image)
98
4.33k
             .Case("image1d_array_t", ValueKind::Image)
99
4.33k
             .Case("image1d_buffer_t", ValueKind::Image)
100
4.33k
             .Case("image2d_t", ValueKind::Image)
101
4.33k
             .Case("image2d_array_t", ValueKind::Image)
102
4.33k
             .Case("image2d_array_depth_t", ValueKind::Image)
103
4.33k
             .Case("image2d_array_msaa_t", ValueKind::Image)
104
4.33k
             .Case("image2d_array_msaa_depth_t", ValueKind::Image)
105
4.33k
             .Case("image2d_depth_t", ValueKind::Image)
106
4.33k
             .Case("image2d_msaa_t", ValueKind::Image)
107
4.33k
             .Case("image2d_msaa_depth_t", ValueKind::Image)
108
4.33k
             .Case("image3d_t", ValueKind::Image)
109
4.33k
             .Case("sampler_t", ValueKind::Sampler)
110
4.33k
             .Case("queue_t", ValueKind::Queue)
111
4.33k
             .Default(isa<PointerType>(Ty) ?
112
2.79k
                          (Ty->getPointerAddressSpace() ==
113
2.79k
                           AMDGPUASI.LOCAL_ADDRESS ?
114
175
                           ValueKind::DynamicSharedPointer :
115
2.79k
                           
ValueKind::GlobalBuffer2.62k
) :
116
4.33k
                      
ValueKind::ByValue1.53k
);
117
4.33k
}
118
119
10.7k
ValueType MetadataStreamer::getValueType(Type *Ty, StringRef TypeName) const {
120
10.7k
  switch (Ty->getTypeID()) {
121
10.7k
  case Type::IntegerTyID: {
122
4.44k
    auto Signed = !TypeName.startswith("u");
123
4.44k
    switch (Ty->getIntegerBitWidth()) {
124
4.44k
    case 8:
125
1.05k
      return Signed ? ValueType::I8 : 
ValueType::U80
;
126
4.44k
    case 16:
127
426
      return Signed ? 
ValueType::I16420
:
ValueType::U166
;
128
4.44k
    case 32:
129
2.01k
      return Signed ? ValueType::I32 : 
ValueType::U320
;
130
4.44k
    case 64:
131
892
      return Signed ? 
ValueType::I64886
:
ValueType::U646
;
132
4.44k
    default:
133
54
      return ValueType::Struct;
134
0
    }
135
0
  }
136
638
  case Type::HalfTyID:
137
638
    return ValueType::F16;
138
221
  case Type::FloatTyID:
139
221
    return ValueType::F32;
140
100
  case Type::DoubleTyID:
141
100
    return ValueType::F64;
142
3.48k
  case Type::PointerTyID:
143
3.48k
    return getValueType(Ty->getPointerElementType(), TypeName);
144
1.55k
  case Type::VectorTyID:
145
1.55k
    return getValueType(Ty->getVectorElementType(), TypeName);
146
272
  default:
147
272
    return ValueType::Struct;
148
10.7k
  }
149
10.7k
}
150
151
66
std::string MetadataStreamer::getTypeName(Type *Ty, bool Signed) const {
152
66
  switch (Ty->getTypeID()) {
153
66
  case Type::IntegerTyID: {
154
36
    if (!Signed)
155
6
      return (Twine('u') + getTypeName(Ty, true)).str();
156
30
157
30
    auto BitWidth = Ty->getIntegerBitWidth();
158
30
    switch (BitWidth) {
159
30
    case 8:
160
6
      return "char";
161
30
    case 16:
162
6
      return "short";
163
30
    case 32:
164
12
      return "int";
165
30
    case 64:
166
6
      return "long";
167
30
    default:
168
0
      return (Twine('i') + Twine(BitWidth)).str();
169
0
    }
170
0
  }
171
6
  case Type::HalfTyID:
172
6
    return "half";
173
6
  case Type::FloatTyID:
174
6
    return "float";
175
6
  case Type::DoubleTyID:
176
6
    return "double";
177
6
  case Type::VectorTyID: {
178
6
    auto VecTy = cast<VectorType>(Ty);
179
6
    auto ElTy = VecTy->getElementType();
180
6
    auto NumElements = VecTy->getVectorNumElements();
181
6
    return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
182
0
  }
183
6
  default:
184
6
    return "unknown";
185
66
  }
186
66
}
187
188
std::vector<uint32_t> MetadataStreamer::getWorkGroupDimensions(
189
12
    MDNode *Node) const {
190
12
  std::vector<uint32_t> Dims;
191
12
  if (Node->getNumOperands() != 3)
192
0
    return Dims;
193
12
194
12
  for (auto &Op : Node->operands())
195
36
    Dims.push_back(mdconst::extract<ConstantInt>(Op)->getZExtValue());
196
12
  return Dims;
197
12
}
198
199
298
void MetadataStreamer::emitVersion() {
200
298
  auto &Version = HSAMetadata.mVersion;
201
298
202
298
  Version.push_back(VersionMajor);
203
298
  Version.push_back(VersionMinor);
204
298
}
205
206
298
void MetadataStreamer::emitPrintf(const Module &Mod) {
207
298
  auto &Printf = HSAMetadata.mPrintf;
208
298
209
298
  auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
210
298
  if (!Node)
211
292
    return;
212
6
213
6
  for (auto Op : Node->operands())
214
12
    if (Op->getNumOperands())
215
12
      Printf.push_back(cast<MDString>(Op->getOperand(0))->getString());
216
6
}
217
218
2.28k
void MetadataStreamer::emitKernelLanguage(const Function &Func) {
219
2.28k
  auto &Kernel = HSAMetadata.mKernels.back();
220
2.28k
221
2.28k
  // TODO: What about other languages?
222
2.28k
  auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
223
2.28k
  if (!Node || 
!Node->getNumOperands()222
)
224
2.06k
    return;
225
222
  auto Op0 = Node->getOperand(0);
226
222
  if (Op0->getNumOperands() <= 1)
227
0
    return;
228
222
229
222
  Kernel.mLanguage = "OpenCL C";
230
222
  Kernel.mLanguageVersion.push_back(
231
222
      mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue());
232
222
  Kernel.mLanguageVersion.push_back(
233
222
      mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue());
234
222
}
235
236
2.28k
void MetadataStreamer::emitKernelAttrs(const Function &Func) {
237
2.28k
  auto &Attrs = HSAMetadata.mKernels.back().mAttrs;
238
2.28k
239
2.28k
  if (auto Node = Func.getMetadata("reqd_work_group_size"))
240
6
    Attrs.mReqdWorkGroupSize = getWorkGroupDimensions(Node);
241
2.28k
  if (auto Node = Func.getMetadata("work_group_size_hint"))
242
6
    Attrs.mWorkGroupSizeHint = getWorkGroupDimensions(Node);
243
2.28k
  if (auto Node = Func.getMetadata("vec_type_hint")) {
244
54
    Attrs.mVecTypeHint = getTypeName(
245
54
        cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
246
54
        mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue());
247
54
  }
248
2.28k
  if (Func.hasFnAttribute("runtime-handle")) {
249
6
    Attrs.mRuntimeHandle =
250
6
        Func.getFnAttribute("runtime-handle").getValueAsString().str();
251
6
  }
252
2.28k
}
253
254
2.28k
void MetadataStreamer::emitKernelArgs(const Function &Func) {
255
2.28k
  for (auto &Arg : Func.args())
256
4.34k
    emitKernelArg(Arg);
257
2.28k
258
2.28k
  // TODO: What about other languages?
259
2.28k
  if (!Func.getParent()->getNamedMetadata("opencl.ocl.version"))
260
2.06k
    return;
261
222
262
222
  auto &DL = Func.getParent()->getDataLayout();
263
222
  auto Int64Ty = Type::getInt64Ty(Func.getContext());
264
222
265
222
  emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetX);
266
222
  emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetY);
267
222
  emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetZ);
268
222
269
222
  auto Int8PtrTy = Type::getInt8PtrTy(Func.getContext(),
270
222
                                      AMDGPUASI.GLOBAL_ADDRESS);
271
222
272
222
  // Emit "printf buffer" argument if printf is used, otherwise emit dummy
273
222
  // "none" argument.
274
222
  if (Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
275
204
    emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenPrintfBuffer);
276
18
  else
277
18
    emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
278
222
279
222
  // Emit "default queue" and "completion action" arguments if enqueue kernel is
280
222
  // used, otherwise emit dummy "none" arguments.
281
222
  if (Func.hasFnAttribute("calls-enqueue-kernel")) {
282
8
    emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenDefaultQueue);
283
8
    emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenCompletionAction);
284
214
  } else {
285
214
    emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
286
214
    emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
287
214
  }
288
222
}
289
290
4.34k
void MetadataStreamer::emitKernelArg(const Argument &Arg) {
291
4.34k
  auto Func = Arg.getParent();
292
4.34k
  auto ArgNo = Arg.getArgNo();
293
4.34k
  const MDNode *Node;
294
4.34k
295
4.34k
  StringRef Name;
296
4.34k
  Node = Func->getMetadata("kernel_arg_name");
297
4.34k
  if (Node && 
ArgNo < Node->getNumOperands()0
)
298
0
    Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
299
4.34k
  else if (Arg.hasName())
300
4.16k
    Name = Arg.getName();
301
4.34k
302
4.34k
  StringRef TypeName;
303
4.34k
  Node = Func->getMetadata("kernel_arg_type");
304
4.34k
  if (Node && 
ArgNo < Node->getNumOperands()382
)
305
370
    TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
306
4.34k
307
4.34k
  StringRef BaseTypeName;
308
4.34k
  Node = Func->getMetadata("kernel_arg_base_type");
309
4.34k
  if (Node && 
ArgNo < Node->getNumOperands()382
)
310
370
    BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
311
4.34k
312
4.34k
  StringRef AccQual;
313
4.34k
  if (Arg.getType()->isPointerTy() && 
Arg.onlyReadsMemory()2.80k
&&
314
4.34k
      
Arg.hasNoAliasAttr()44
) {
315
4
    AccQual = "read_only";
316
4.33k
  } else {
317
4.33k
    Node = Func->getMetadata("kernel_arg_access_qual");
318
4.33k
    if (Node && 
ArgNo < Node->getNumOperands()345
)
319
333
      AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
320
4.33k
  }
321
4.34k
322
4.34k
  StringRef TypeQual;
323
4.34k
  Node = Func->getMetadata("kernel_arg_type_qual");
324
4.34k
  if (Node && 
ArgNo < Node->getNumOperands()346
)
325
334
    TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
326
4.34k
327
4.34k
  Type *Ty = Arg.getType();
328
4.34k
  const DataLayout &DL = Func->getParent()->getDataLayout();
329
4.34k
330
4.34k
  unsigned PointeeAlign = 0;
331
4.34k
  if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
332
2.80k
    if (PtrTy->getAddressSpace() == AMDGPUASI.LOCAL_ADDRESS) {
333
175
      PointeeAlign = Arg.getParamAlignment();
334
175
      if (PointeeAlign == 0)
335
132
        PointeeAlign = DL.getABITypeAlignment(PtrTy->getElementType());
336
175
    }
337
2.80k
  }
338
4.34k
339
4.34k
  emitKernelArg(DL, Ty, getValueKind(Arg.getType(), TypeQual, BaseTypeName),
340
4.34k
                PointeeAlign, Name, TypeName, BaseTypeName, AccQual, TypeQual);
341
4.34k
}
342
343
void MetadataStreamer::emitKernelArg(const DataLayout &DL, Type *Ty,
344
                                     ValueKind ValueKind,
345
                                     unsigned PointeeAlign,
346
                                     StringRef Name,
347
                                     StringRef TypeName, StringRef BaseTypeName,
348
5.67k
                                     StringRef AccQual, StringRef TypeQual) {
349
5.67k
  HSAMetadata.mKernels.back().mArgs.push_back(Kernel::Arg::Metadata());
350
5.67k
  auto &Arg = HSAMetadata.mKernels.back().mArgs.back();
351
5.67k
352
5.67k
  Arg.mName = Name;
353
5.67k
  Arg.mTypeName = TypeName;
354
5.67k
  Arg.mSize = DL.getTypeAllocSize(Ty);
355
5.67k
  Arg.mAlign = DL.getABITypeAlignment(Ty);
356
5.67k
  Arg.mValueKind = ValueKind;
357
5.67k
  Arg.mValueType = getValueType(Ty, BaseTypeName);
358
5.67k
  Arg.mPointeeAlign = PointeeAlign;
359
5.67k
360
5.67k
  if (auto PtrTy = dyn_cast<PointerType>(Ty))
361
3.46k
    Arg.mAddrSpaceQual = getAddressSpaceQualifer(PtrTy->getAddressSpace());
362
5.67k
363
5.67k
  Arg.mAccQual = getAccessQualifier(AccQual);
364
5.67k
365
5.67k
  // TODO: Emit Arg.mActualAccQual.
366
5.67k
367
5.67k
  SmallVector<StringRef, 1> SplitTypeQuals;
368
5.67k
  TypeQual.split(SplitTypeQuals, " ", -1, false);
369
5.67k
  for (StringRef Key : SplitTypeQuals) {
370
26
    auto P = StringSwitch<bool*>(Key)
371
26
                 .Case("const",    &Arg.mIsConst)
372
26
                 .Case("restrict", &Arg.mIsRestrict)
373
26
                 .Case("volatile", &Arg.mIsVolatile)
374
26
                 .Case("pipe",     &Arg.mIsPipe)
375
26
                 .Default(nullptr);
376
26
    if (P)
377
26
      *P = true;
378
26
  }
379
5.67k
}
380
381
298
void MetadataStreamer::begin(const Module &Mod) {
382
298
  AMDGPUASI = getAMDGPUAS(Mod);
383
298
  emitVersion();
384
298
  emitPrintf(Mod);
385
298
}
386
387
298
void MetadataStreamer::end() {
388
298
  std::string HSAMetadataString;
389
298
  if (toString(HSAMetadata, HSAMetadataString))
390
0
    return;
391
298
392
298
  if (DumpHSAMetadata)
393
4
    dump(HSAMetadataString);
394
298
  if (VerifyHSAMetadata)
395
4
    verify(HSAMetadataString);
396
298
}
397
398
void MetadataStreamer::emitKernel(
399
    const Function &Func,
400
    const Kernel::CodeProps::Metadata &CodeProps,
401
2.29k
    const Kernel::DebugProps::Metadata &DebugProps) {
402
2.29k
  if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL)
403
3
    return;
404
2.28k
405
2.28k
  HSAMetadata.mKernels.push_back(Kernel::Metadata());
406
2.28k
  auto &Kernel = HSAMetadata.mKernels.back();
407
2.28k
408
2.28k
  Kernel.mName = Func.getName();
409
2.28k
  Kernel.mSymbolName = (Twine(Func.getName()) + Twine("@kd")).str();
410
2.28k
  emitKernelLanguage(Func);
411
2.28k
  emitKernelAttrs(Func);
412
2.28k
  emitKernelArgs(Func);
413
2.28k
  HSAMetadata.mKernels.back().mCodeProps = CodeProps;
414
2.28k
  HSAMetadata.mKernels.back().mDebugProps = DebugProps;
415
2.28k
}
416
417
} // end namespace HSAMD
418
} // end namespace AMDGPU
419
} // end namespace llvm