LLVM  6.0.0svn
AMDGPUHSAMetadataStreamer.cpp
Go to the documentation of this file.
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 /// \brief AMDGPU HSA Metadata Streamer.
12 ///
13 //
14 //===----------------------------------------------------------------------===//
15 
17 #include "AMDGPU.h"
18 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/IR/Constants.h"
20 #include "llvm/IR/Module.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 void MetadataStreamer::dump(StringRef HSAMetadataString) const {
36  errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
37 }
38 
39 void MetadataStreamer::verify(StringRef HSAMetadataString) const {
40  errs() << "AMDGPU HSA Metadata Parser Test: ";
41 
42  HSAMD::Metadata FromHSAMetadataString;
43  if (fromString(HSAMetadataString, FromHSAMetadataString)) {
44  errs() << "FAIL\n";
45  return;
46  }
47 
48  std::string ToHSAMetadataString;
49  if (toString(FromHSAMetadataString, ToHSAMetadataString)) {
50  errs() << "FAIL\n";
51  return;
52  }
53 
54  errs() << (HSAMetadataString == ToHSAMetadataString ? "PASS" : "FAIL")
55  << '\n';
56  if (HSAMetadataString != ToHSAMetadataString) {
57  errs() << "Original input: " << HSAMetadataString << '\n'
58  << "Produced output: " << ToHSAMetadataString << '\n';
59  }
60 }
61 
62 AccessQualifier MetadataStreamer::getAccessQualifier(StringRef AccQual) const {
63  if (AccQual.empty())
65 
66  return StringSwitch<AccessQualifier>(AccQual)
67  .Case("read_only", AccessQualifier::ReadOnly)
68  .Case("write_only", AccessQualifier::WriteOnly)
69  .Case("read_write", AccessQualifier::ReadWrite)
70  .Default(AccessQualifier::Default);
71 }
72 
73 AddressSpaceQualifier MetadataStreamer::getAddressSpaceQualifer(
74  unsigned AddressSpace) const {
75  if (AddressSpace == AMDGPUASI.PRIVATE_ADDRESS)
77  if (AddressSpace == AMDGPUASI.GLOBAL_ADDRESS)
79  if (AddressSpace == AMDGPUASI.CONSTANT_ADDRESS)
81  if (AddressSpace == AMDGPUASI.LOCAL_ADDRESS)
83  if (AddressSpace == AMDGPUASI.FLAT_ADDRESS)
85  if (AddressSpace == AMDGPUASI.REGION_ADDRESS)
87 
88  llvm_unreachable("Unknown address space qualifier");
89 }
90 
91 ValueKind MetadataStreamer::getValueKind(Type *Ty, StringRef TypeQual,
92  StringRef BaseTypeName) const {
93  if (TypeQual.find("pipe") != StringRef::npos)
94  return ValueKind::Pipe;
95 
96  return StringSwitch<ValueKind>(BaseTypeName)
97  .Case("image1d_t", ValueKind::Image)
98  .Case("image1d_array_t", ValueKind::Image)
99  .Case("image1d_buffer_t", ValueKind::Image)
100  .Case("image2d_t", ValueKind::Image)
101  .Case("image2d_array_t", ValueKind::Image)
102  .Case("image2d_array_depth_t", ValueKind::Image)
103  .Case("image2d_array_msaa_t", ValueKind::Image)
104  .Case("image2d_array_msaa_depth_t", ValueKind::Image)
105  .Case("image2d_depth_t", ValueKind::Image)
106  .Case("image2d_msaa_t", ValueKind::Image)
107  .Case("image2d_msaa_depth_t", ValueKind::Image)
108  .Case("image3d_t", ValueKind::Image)
109  .Case("sampler_t", ValueKind::Sampler)
110  .Case("queue_t", ValueKind::Queue)
111  .Default(isa<PointerType>(Ty) ?
112  (Ty->getPointerAddressSpace() ==
113  AMDGPUASI.LOCAL_ADDRESS ?
117 }
118 
119 ValueType MetadataStreamer::getValueType(Type *Ty, StringRef TypeName) const {
120  switch (Ty->getTypeID()) {
121  case Type::IntegerTyID: {
122  auto Signed = !TypeName.startswith("u");
123  switch (Ty->getIntegerBitWidth()) {
124  case 8:
126  case 16:
128  case 32:
130  case 64:
132  default:
133  return ValueType::Struct;
134  }
135  }
136  case Type::HalfTyID:
137  return ValueType::F16;
138  case Type::FloatTyID:
139  return ValueType::F32;
140  case Type::DoubleTyID:
141  return ValueType::F64;
142  case Type::PointerTyID:
143  return getValueType(Ty->getPointerElementType(), TypeName);
144  case Type::VectorTyID:
145  return getValueType(Ty->getVectorElementType(), TypeName);
146  default:
147  return ValueType::Struct;
148  }
149 }
150 
151 std::string MetadataStreamer::getTypeName(Type *Ty, bool Signed) const {
152  switch (Ty->getTypeID()) {
153  case Type::IntegerTyID: {
154  if (!Signed)
155  return (Twine('u') + getTypeName(Ty, true)).str();
156 
157  auto BitWidth = Ty->getIntegerBitWidth();
158  switch (BitWidth) {
159  case 8:
160  return "char";
161  case 16:
162  return "short";
163  case 32:
164  return "int";
165  case 64:
166  return "long";
167  default:
168  return (Twine('i') + Twine(BitWidth)).str();
169  }
170  }
171  case Type::HalfTyID:
172  return "half";
173  case Type::FloatTyID:
174  return "float";
175  case Type::DoubleTyID:
176  return "double";
177  case Type::VectorTyID: {
178  auto VecTy = cast<VectorType>(Ty);
179  auto ElTy = VecTy->getElementType();
180  auto NumElements = VecTy->getVectorNumElements();
181  return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
182  }
183  default:
184  return "unknown";
185  }
186 }
187 
188 std::vector<uint32_t> MetadataStreamer::getWorkGroupDimensions(
189  MDNode *Node) const {
190  std::vector<uint32_t> Dims;
191  if (Node->getNumOperands() != 3)
192  return Dims;
193 
194  for (auto &Op : Node->operands())
195  Dims.push_back(mdconst::extract<ConstantInt>(Op)->getZExtValue());
196  return Dims;
197 }
198 
199 void MetadataStreamer::emitVersion() {
200  auto &Version = HSAMetadata.mVersion;
201 
202  Version.push_back(VersionMajor);
203  Version.push_back(VersionMinor);
204 }
205 
206 void MetadataStreamer::emitPrintf(const Module &Mod) {
207  auto &Printf = HSAMetadata.mPrintf;
208 
209  auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
210  if (!Node)
211  return;
212 
213  for (auto Op : Node->operands())
214  if (Op->getNumOperands())
215  Printf.push_back(cast<MDString>(Op->getOperand(0))->getString());
216 }
217 
218 void MetadataStreamer::emitKernelLanguage(const Function &Func) {
219  auto &Kernel = HSAMetadata.mKernels.back();
220 
221  // TODO: What about other languages?
222  auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
223  if (!Node || !Node->getNumOperands())
224  return;
225  auto Op0 = Node->getOperand(0);
226  if (Op0->getNumOperands() <= 1)
227  return;
228 
229  Kernel.mLanguage = "OpenCL C";
230  Kernel.mLanguageVersion.push_back(
231  mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue());
232  Kernel.mLanguageVersion.push_back(
233  mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue());
234 }
235 
236 void MetadataStreamer::emitKernelAttrs(const Function &Func) {
237  auto &Attrs = HSAMetadata.mKernels.back().mAttrs;
238 
239  if (auto Node = Func.getMetadata("reqd_work_group_size"))
240  Attrs.mReqdWorkGroupSize = getWorkGroupDimensions(Node);
241  if (auto Node = Func.getMetadata("work_group_size_hint"))
242  Attrs.mWorkGroupSizeHint = getWorkGroupDimensions(Node);
243  if (auto Node = Func.getMetadata("vec_type_hint")) {
244  Attrs.mVecTypeHint = getTypeName(
245  cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
246  mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue());
247  }
248  if (Func.hasFnAttribute("runtime-handle")) {
249  Attrs.mRuntimeHandle =
250  Func.getFnAttribute("runtime-handle").getValueAsString().str();
251  }
252 }
253 
254 void MetadataStreamer::emitKernelArgs(const Function &Func) {
255  for (auto &Arg : Func.args())
256  emitKernelArg(Arg);
257 
258  // TODO: What about other languages?
259  if (!Func.getParent()->getNamedMetadata("opencl.ocl.version"))
260  return;
261 
262  auto &DL = Func.getParent()->getDataLayout();
263  auto Int64Ty = Type::getInt64Ty(Func.getContext());
264 
265  emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetX);
266  emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetY);
267  emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetZ);
268 
269  auto Int8PtrTy = Type::getInt8PtrTy(Func.getContext(),
270  AMDGPUASI.GLOBAL_ADDRESS);
271  auto CallsPrintf = Func.getParent()->getNamedMetadata("llvm.printf.fmts");
272  if (CallsPrintf)
273  emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenPrintfBuffer);
274  if (Func.hasFnAttribute("calls-enqueue-kernel")) {
275  if (!CallsPrintf) {
276  // Emit a dummy argument so that the remaining hidden arguments
277  // have a fixed position relative to the first hidden argument.
278  // This is to facilitate library code to access hidden arguments.
279  emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
280  }
281  emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenDefaultQueue);
282  emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenCompletionAction);
283  }
284 }
285 
286 void MetadataStreamer::emitKernelArg(const Argument &Arg) {
287  auto Func = Arg.getParent();
288  auto ArgNo = Arg.getArgNo();
289  const MDNode *Node;
290 
291  StringRef Name;
292  Node = Func->getMetadata("kernel_arg_name");
293  if (Node && ArgNo < Node->getNumOperands())
294  Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
295 
296  StringRef TypeName;
297  Node = Func->getMetadata("kernel_arg_type");
298  if (Node && ArgNo < Node->getNumOperands())
299  TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
300 
301  StringRef BaseTypeName;
302  Node = Func->getMetadata("kernel_arg_base_type");
303  if (Node && ArgNo < Node->getNumOperands())
304  BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
305 
306  StringRef AccQual;
307  if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
308  Arg.hasNoAliasAttr()) {
309  AccQual = "read_only";
310  } else {
311  Node = Func->getMetadata("kernel_arg_access_qual");
312  if (Node && ArgNo < Node->getNumOperands())
313  AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
314  }
315 
316  StringRef TypeQual;
317  Node = Func->getMetadata("kernel_arg_type_qual");
318  if (Node && ArgNo < Node->getNumOperands())
319  TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
320 
321  emitKernelArg(Func->getParent()->getDataLayout(), Arg.getType(),
322  getValueKind(Arg.getType(), TypeQual, BaseTypeName), Name,
323  TypeName, BaseTypeName, AccQual, TypeQual);
324 }
325 
326 void MetadataStreamer::emitKernelArg(const DataLayout &DL, Type *Ty,
327  ValueKind ValueKind, StringRef Name,
328  StringRef TypeName, StringRef BaseTypeName,
329  StringRef AccQual, StringRef TypeQual) {
330  HSAMetadata.mKernels.back().mArgs.push_back(Kernel::Arg::Metadata());
331  auto &Arg = HSAMetadata.mKernels.back().mArgs.back();
332 
333  Arg.mName = Name;
334  Arg.mTypeName = TypeName;
335  Arg.mSize = DL.getTypeAllocSize(Ty);
336  Arg.mAlign = DL.getABITypeAlignment(Ty);
337  Arg.mValueKind = ValueKind;
338  Arg.mValueType = getValueType(Ty, BaseTypeName);
339 
340  if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
341  auto ElTy = PtrTy->getElementType();
342  if (PtrTy->getAddressSpace() == AMDGPUASI.LOCAL_ADDRESS && ElTy->isSized())
343  Arg.mPointeeAlign = DL.getABITypeAlignment(ElTy);
344  }
345 
346  if (auto PtrTy = dyn_cast<PointerType>(Ty))
347  Arg.mAddrSpaceQual = getAddressSpaceQualifer(PtrTy->getAddressSpace());
348 
349  Arg.mAccQual = getAccessQualifier(AccQual);
350 
351  // TODO: Emit Arg.mActualAccQual.
352 
353  SmallVector<StringRef, 1> SplitTypeQuals;
354  TypeQual.split(SplitTypeQuals, " ", -1, false);
355  for (StringRef Key : SplitTypeQuals) {
356  auto P = StringSwitch<bool*>(Key)
357  .Case("const", &Arg.mIsConst)
358  .Case("restrict", &Arg.mIsRestrict)
359  .Case("volatile", &Arg.mIsVolatile)
360  .Case("pipe", &Arg.mIsPipe)
361  .Default(nullptr);
362  if (P)
363  *P = true;
364  }
365 }
366 
367 void MetadataStreamer::begin(const Module &Mod) {
368  AMDGPUASI = getAMDGPUAS(Mod);
369  emitVersion();
370  emitPrintf(Mod);
371 }
372 
374  std::string HSAMetadataString;
375  if (toString(HSAMetadata, HSAMetadataString))
376  return;
377 
378  if (DumpHSAMetadata)
379  dump(HSAMetadataString);
380  if (VerifyHSAMetadata)
381  verify(HSAMetadataString);
382 }
383 
385  const Function &Func,
389  return;
390 
391  HSAMetadata.mKernels.push_back(Kernel::Metadata());
392  auto &Kernel = HSAMetadata.mKernels.back();
393 
394  Kernel.mName = Func.getName();
395  Kernel.mSymbolName = (Twine(Func.getName()) + Twine("@kd")).str();
396  emitKernelLanguage(Func);
397  emitKernelAttrs(Func);
398  emitKernelArgs(Func);
399  HSAMetadata.mKernels.back().mCodeProps = CodeProps;
400  HSAMetadata.mKernels.back().mDebugProps = DebugProps;
401 }
402 
403 } // end namespace HSAMD
404 } // end namespace AMDGPU
405 } // end namespace llvm
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:63
2: 32-bit floating point type
Definition: Type.h:59
AMDGPUAS getAMDGPUAS(const Module &M)
1: 16-bit floating point type
Definition: Type.h:58
static IntegerType * getInt64Ty(LLVMContext &C)
Definition: Type.cpp:177
15: Pointers
Definition: Type.h:75
Address space for global memory (RAT0, VTX0).
Definition: AMDGPU.h:224
In-memory representation of kernel debug properties metadata.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
constexpr char Printf[]
Key for HSA::Metadata::mPrintf.
std::error_code fromString(std::string String, Metadata &HSAMetadata)
Converts String to HSAMetadata.
Key
PAL metadata keys.
static cl::opt< bool > VerifyHSAMetadata("amdgpu-verify-hsa-metadata", cl::desc("Verify AMDGPU HSA Metadata"))
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
AMDGPU HSA Metadata Streamer.
11: Arbitrary bit width integers
Definition: Type.h:71
#define P(N)
static cl::opt< bool > DumpHSAMetadata("amdgpu-dump-hsa-metadata", cl::desc("Dump AMDGPU HSA Metadata"))
In-memory representation of kernel metadata.
ValueKind
Value kinds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
std::vector< uint32_t > mVersion
HSA metadata version. Required.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
Calling convention for AMDGPU code object kernels.
Definition: CallingConv.h:201
unsigned REGION_ADDRESS
Address space for region memory.
Definition: AMDGPU.h:218
static wasm::ValType getType(const TargetRegisterClass *RC)
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:220
void emitKernel(const Function &Func, const Kernel::CodeProps::Metadata &CodeProps, const Kernel::DebugProps::Metadata &DebugProps)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
AccessQualifier
Access qualifiers.
std::vector< std::string > mPrintf
Printf metadata. Optional.
16: SIMD &#39;packed&#39; format, or other vector type
Definition: Type.h:76
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition: Function.h:194
Module.h This file contains the declarations for the Module class.
AddressSpace
Definition: NVPTXBaseInfo.h:22
constexpr char CodeProps[]
Key for Kernel::Metadata::mCodeProps.
ValueType
Value types.
constexpr uint32_t VersionMinor
HSA metadata minor version.
Address space for constant memory (VTX2)
Definition: AMDGPU.h:225
amdgpu Simplify well known AMD library false Value Value * Arg
std::error_code toString(Metadata HSAMetadata, std::string &String)
Converts HSAMetadata to String.
static const size_t npos
Definition: StringRef.h:51
constexpr char DebugProps[]
Key for Kernel::Metadata::mDebugProps.
AddressSpaceQualifier
Address space qualifiers.
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:220
unsigned FLAT_ADDRESS
Address space for flat memory.
Definition: AMDGPU.h:217
constexpr char AccQual[]
Key for Kernel::Arg::Metadata::mAccQual.
Address space for local memory.
Definition: AMDGPU.h:226
In-memory representation of kernel code properties metadata.
3: 64-bit floating point type
Definition: Type.h:60
std::vector< Kernel::Metadata > mKernels
Kernels metadata. Required.
const uint64_t Version
Definition: InstrProf.h:867
constexpr uint32_t VersionMajor
HSA metadata major version.
unsigned PRIVATE_ADDRESS
Address space for private memory.
Definition: AMDGPU.h:216
std::vector< uint32_t > Metadata
PAL metadata represented as a vector.