LLVM  4.0.0
AMDGPURuntimeMD.cpp
Go to the documentation of this file.
1 //===-- AMDGPURuntimeMD.cpp - Generates runtime metadata ------------------===//
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 ///
12 /// Generates AMDGPU runtime metadata for YAML mapping.
13 //
14 //===----------------------------------------------------------------------===//
15 //
16 
17 #include "AMDGPU.h"
18 #include "AMDGPURuntimeMetadata.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/ADT/StringSwitch.h"
21 #include "llvm/IR/Constants.h"
22 #include "llvm/IR/DataLayout.h"
23 #include "llvm/IR/Module.h"
27 #include <vector>
28 #include "AMDGPURuntimeMD.h"
29 
30 using namespace llvm;
31 using namespace ::AMDGPU::RuntimeMD;
32 
33 static cl::opt<bool>
34 DumpRuntimeMD("amdgpu-dump-rtmd",
35  cl::desc("Dump AMDGPU runtime metadata"));
36 
37 static cl::opt<bool>
38 CheckRuntimeMDParser("amdgpu-check-rtmd-parser", cl::Hidden,
39  cl::desc("Check AMDGPU runtime metadata YAML parser"));
40 
46 
47 namespace llvm {
48 namespace yaml {
49 
50 template <> struct MappingTraits<KernelArg::Metadata> {
51  static void mapping(IO &YamlIO, KernelArg::Metadata &A) {
52  YamlIO.mapRequired(KeyName::ArgSize, A.Size);
53  YamlIO.mapRequired(KeyName::ArgAlign, A.Align);
54  YamlIO.mapOptional(KeyName::ArgPointeeAlign, A.PointeeAlign, 0U);
55  YamlIO.mapRequired(KeyName::ArgKind, A.Kind);
56  YamlIO.mapRequired(KeyName::ArgValueType, A.ValueType);
57  YamlIO.mapOptional(KeyName::ArgTypeName, A.TypeName, std::string());
58  YamlIO.mapOptional(KeyName::ArgName, A.Name, std::string());
61  YamlIO.mapOptional(KeyName::ArgIsVolatile, A.IsVolatile, uint8_t(0));
62  YamlIO.mapOptional(KeyName::ArgIsConst, A.IsConst, uint8_t(0));
63  YamlIO.mapOptional(KeyName::ArgIsRestrict, A.IsRestrict, uint8_t(0));
64  YamlIO.mapOptional(KeyName::ArgIsPipe, A.IsPipe, uint8_t(0));
65  }
66  static const bool flow = true;
67 };
68 
69 template <> struct MappingTraits<Kernel::Metadata> {
70  static void mapping(IO &YamlIO, Kernel::Metadata &K) {
71  YamlIO.mapRequired(KeyName::KernelName, K.Name);
72  YamlIO.mapOptional(KeyName::Language, K.Language, std::string());
73  YamlIO.mapOptional(KeyName::LanguageVersion, K.LanguageVersion);
74  YamlIO.mapOptional(KeyName::ReqdWorkGroupSize, K.ReqdWorkGroupSize);
75  YamlIO.mapOptional(KeyName::WorkGroupSizeHint, K.WorkGroupSizeHint);
76  YamlIO.mapOptional(KeyName::VecTypeHint, K.VecTypeHint, std::string());
77  YamlIO.mapOptional(KeyName::KernelIndex, K.KernelIndex,
79  YamlIO.mapOptional(KeyName::NoPartialWorkGroups, K.NoPartialWorkGroups,
80  uint8_t(0));
81  YamlIO.mapRequired(KeyName::Args, K.Args);
82  }
83  static const bool flow = true;
84 };
85 
86 template <> struct MappingTraits<Program::Metadata> {
87  static void mapping(IO &YamlIO, Program::Metadata &Prog) {
88  YamlIO.mapRequired(KeyName::MDVersion, Prog.MDVersionSeq);
89  YamlIO.mapOptional(KeyName::PrintfInfo, Prog.PrintfInfo);
90  YamlIO.mapOptional(KeyName::Kernels, Prog.Kernels);
91  }
92  static const bool flow = true;
93 };
94 
95 } // end namespace yaml
96 } // end namespace llvm
97 
98 // Get a vector of three integer values from MDNode \p Node;
99 static std::vector<uint32_t> getThreeInt32(MDNode *Node) {
100  assert(Node->getNumOperands() == 3);
101  std::vector<uint32_t> V;
102  for (const MDOperand &Op : Node->operands()) {
103  const ConstantInt *CI = mdconst::extract<ConstantInt>(Op);
104  V.push_back(CI->getZExtValue());
105  }
106  return V;
107 }
108 
109 static std::string getOCLTypeName(Type *Ty, bool Signed) {
110  switch (Ty->getTypeID()) {
111  case Type::HalfTyID:
112  return "half";
113  case Type::FloatTyID:
114  return "float";
115  case Type::DoubleTyID:
116  return "double";
117  case Type::IntegerTyID: {
118  if (!Signed)
119  return (Twine('u') + getOCLTypeName(Ty, true)).str();
120  unsigned BW = Ty->getIntegerBitWidth();
121  switch (BW) {
122  case 8:
123  return "char";
124  case 16:
125  return "short";
126  case 32:
127  return "int";
128  case 64:
129  return "long";
130  default:
131  return (Twine('i') + Twine(BW)).str();
132  }
133  }
134  case Type::VectorTyID: {
135  VectorType *VecTy = cast<VectorType>(Ty);
136  Type *EleTy = VecTy->getElementType();
137  unsigned Size = VecTy->getVectorNumElements();
138  return (Twine(getOCLTypeName(EleTy, Signed)) + Twine(Size)).str();
139  }
140  default:
141  return "unknown";
142  }
143 }
144 
146  Type *Ty, StringRef TypeName) {
147  switch (Ty->getTypeID()) {
148  case Type::HalfTyID:
149  return KernelArg::F16;
150  case Type::FloatTyID:
151  return KernelArg::F32;
152  case Type::DoubleTyID:
153  return KernelArg::F64;
154  case Type::IntegerTyID: {
155  bool Signed = !TypeName.startswith("u");
156  switch (Ty->getIntegerBitWidth()) {
157  case 8:
158  return Signed ? KernelArg::I8 : KernelArg::U8;
159  case 16:
160  return Signed ? KernelArg::I16 : KernelArg::U16;
161  case 32:
162  return Signed ? KernelArg::I32 : KernelArg::U32;
163  case 64:
164  return Signed ? KernelArg::I64 : KernelArg::U64;
165  default:
166  // Runtime does not recognize other integer types. Report as struct type.
167  return KernelArg::Struct;
168  }
169  }
170  case Type::VectorTyID:
171  return getRuntimeMDValueType(Ty->getVectorElementType(), TypeName);
172  case Type::PointerTyID:
173  return getRuntimeMDValueType(Ty->getPointerElementType(), TypeName);
174  default:
175  return KernelArg::Struct;
176  }
177 }
178 
181  switch (A) {
183  return KernelArg::Global;
185  return KernelArg::Constant;
187  return KernelArg::Local;
189  return KernelArg::Generic;
191  return KernelArg::Region;
192  default:
193  return KernelArg::Private;
194  }
195 }
196 
197 static KernelArg::Metadata getRuntimeMDForKernelArg(const DataLayout &DL,
198  Type *T, KernelArg::Kind Kind, StringRef BaseTypeName = "",
199  StringRef TypeName = "", StringRef ArgName = "", StringRef TypeQual = "",
200  StringRef AccQual = "") {
201 
202  KernelArg::Metadata Arg;
203 
204  // Set ArgSize and ArgAlign.
205  Arg.Size = DL.getTypeAllocSize(T);
206  Arg.Align = DL.getABITypeAlignment(T);
207  if (auto PT = dyn_cast<PointerType>(T)) {
208  auto ET = PT->getElementType();
209  if (PT->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS && ET->isSized())
210  Arg.PointeeAlign = DL.getABITypeAlignment(ET);
211  }
212 
213  // Set ArgTypeName.
214  Arg.TypeName = TypeName;
215 
216  // Set ArgName.
217  Arg.Name = ArgName;
218 
219  // Set ArgIsVolatile, ArgIsRestrict, ArgIsConst and ArgIsPipe.
221  TypeQual.split(SplitQ, " ", -1, false /* Drop empty entry */);
222 
223  for (StringRef KeyName : SplitQ) {
224  auto *P = StringSwitch<uint8_t *>(KeyName)
225  .Case("volatile", &Arg.IsVolatile)
226  .Case("restrict", &Arg.IsRestrict)
227  .Case("const", &Arg.IsConst)
228  .Case("pipe", &Arg.IsPipe)
229  .Default(nullptr);
230  if (P)
231  *P = 1;
232  }
233 
234  // Set ArgKind.
235  Arg.Kind = Kind;
236 
237  // Set ArgValueType.
238  Arg.ValueType = getRuntimeMDValueType(T, BaseTypeName);
239 
240  // Set ArgAccQual.
241  if (!AccQual.empty()) {
242  Arg.AccQual = StringSwitch<KernelArg::AccessQualifer>(AccQual)
243  .Case("read_only", KernelArg::ReadOnly)
244  .Case("write_only", KernelArg::WriteOnly)
245  .Case("read_write", KernelArg::ReadWrite)
247  }
248 
249  // Set ArgAddrQual.
250  if (auto *PT = dyn_cast<PointerType>(T)) {
251  Arg.AddrQual = getRuntimeAddrSpace(static_cast<AMDGPUAS::AddressSpaces>(
252  PT->getAddressSpace()));
253  }
254 
255  return Arg;
256 }
257 
258 static Kernel::Metadata getRuntimeMDForKernel(const Function &F) {
259  Kernel::Metadata Kernel;
260  Kernel.Name = F.getName();
261  auto &M = *F.getParent();
262 
263  // Set Language and LanguageVersion.
264  if (auto MD = M.getNamedMetadata("opencl.ocl.version")) {
265  if (MD->getNumOperands() != 0) {
266  auto Node = MD->getOperand(0);
267  if (Node->getNumOperands() > 1) {
268  Kernel.Language = "OpenCL C";
269  uint16_t Major = mdconst::extract<ConstantInt>(Node->getOperand(0))
270  ->getZExtValue();
271  uint16_t Minor = mdconst::extract<ConstantInt>(Node->getOperand(1))
272  ->getZExtValue();
273  Kernel.LanguageVersion.push_back(Major);
274  Kernel.LanguageVersion.push_back(Minor);
275  }
276  }
277  }
278 
279  const DataLayout &DL = F.getParent()->getDataLayout();
280  for (auto &Arg : F.args()) {
281  unsigned I = Arg.getArgNo();
282  Type *T = Arg.getType();
283  auto TypeName = dyn_cast<MDString>(F.getMetadata(
284  "kernel_arg_type")->getOperand(I))->getString();
285  auto BaseTypeName = cast<MDString>(F.getMetadata(
286  "kernel_arg_base_type")->getOperand(I))->getString();
288  if (auto ArgNameMD = F.getMetadata("kernel_arg_name"))
289  ArgName = cast<MDString>(ArgNameMD->getOperand(I))->getString();
290  auto TypeQual = cast<MDString>(F.getMetadata(
291  "kernel_arg_type_qual")->getOperand(I))->getString();
292  auto AccQual = cast<MDString>(F.getMetadata(
293  "kernel_arg_access_qual")->getOperand(I))->getString();
295  if (TypeQual.find("pipe") != StringRef::npos)
296  Kind = KernelArg::Pipe;
297  else Kind = StringSwitch<KernelArg::Kind>(BaseTypeName)
298  .Case("sampler_t", KernelArg::Sampler)
299  .Case("queue_t", KernelArg::Queue)
300  .Cases("image1d_t", "image1d_array_t", "image1d_buffer_t",
301  "image2d_t" , "image2d_array_t", KernelArg::Image)
302  .Cases("image2d_depth_t", "image2d_array_depth_t",
303  "image2d_msaa_t", "image2d_array_msaa_t",
304  "image2d_msaa_depth_t", KernelArg::Image)
305  .Cases("image2d_array_msaa_depth_t", "image3d_t",
307  .Default(isa<PointerType>(T) ?
312  Kernel.Args.emplace_back(getRuntimeMDForKernelArg(DL, T, Kind,
313  BaseTypeName, TypeName, ArgName, TypeQual, AccQual));
314  }
315 
316  // Emit hidden kernel arguments for OpenCL kernels.
317  if (F.getParent()->getNamedMetadata("opencl.ocl.version")) {
318  auto Int64T = Type::getInt64Ty(F.getContext());
319  Kernel.Args.emplace_back(getRuntimeMDForKernelArg(DL, Int64T,
321  Kernel.Args.emplace_back(getRuntimeMDForKernelArg(DL, Int64T,
323  Kernel.Args.emplace_back(getRuntimeMDForKernelArg(DL, Int64T,
325  if (F.getParent()->getNamedMetadata("llvm.printf.fmts")) {
326  auto Int8PtrT = Type::getInt8PtrTy(F.getContext(),
328  Kernel.Args.emplace_back(getRuntimeMDForKernelArg(DL, Int8PtrT,
330  }
331  }
332 
333  // Set ReqdWorkGroupSize, WorkGroupSizeHint, and VecTypeHint.
334  if (auto RWGS = F.getMetadata("reqd_work_group_size"))
335  Kernel.ReqdWorkGroupSize = getThreeInt32(RWGS);
336 
337  if (auto WGSH = F.getMetadata("work_group_size_hint"))
338  Kernel.WorkGroupSizeHint = getThreeInt32(WGSH);
339 
340  if (auto VTH = F.getMetadata("vec_type_hint"))
341  Kernel.VecTypeHint = getOCLTypeName(cast<ValueAsMetadata>(
342  VTH->getOperand(0))->getType(), mdconst::extract<ConstantInt>(
343  VTH->getOperand(1))->getZExtValue());
344 
345  return Kernel;
346 }
347 
348 Program::Metadata::Metadata(const std::string &YAML) {
349  yaml::Input Input(YAML);
350  Input >> *this;
351 }
352 
353 std::string Program::Metadata::toYAML(void) {
354  std::string Text;
355  raw_string_ostream Stream(Text);
356  yaml::Output Output(Stream, nullptr, INT_MAX /* do not wrap line */);
357  Output << *this;
358  return Stream.str();
359 }
360 
361 Program::Metadata Program::Metadata::fromYAML(const std::string &S) {
362  return Program::Metadata(S);
363 }
364 
365 // Check if the YAML string can be parsed.
366 static void checkRuntimeMDYAMLString(const std::string &YAML) {
367  auto P = Program::Metadata::fromYAML(YAML);
368  auto S = P.toYAML();
369  llvm::errs() << "AMDGPU runtime metadata parser test "
370  << (YAML == S ? "passes" : "fails") << ".\n";
371  if (YAML != S) {
372  llvm::errs() << "First output: " << YAML << '\n'
373  << "Second output: " << S << '\n';
374  }
375 }
376 
378  Program::Metadata Prog;
379  Prog.MDVersionSeq.push_back(MDVersion);
380  Prog.MDVersionSeq.push_back(MDRevision);
381 
382  // Set PrintfInfo.
383  if (auto MD = M.getNamedMetadata("llvm.printf.fmts")) {
384  for (unsigned I = 0; I < MD->getNumOperands(); ++I) {
385  auto Node = MD->getOperand(I);
386  if (Node->getNumOperands() > 0)
387  Prog.PrintfInfo.push_back(cast<MDString>(Node->getOperand(0))
388  ->getString());
389  }
390  }
391 
392  // Set Kernels.
393  for (auto &F: M.functions()) {
394  if (!F.getMetadata("kernel_arg_type"))
395  continue;
396  Prog.Kernels.emplace_back(getRuntimeMDForKernel(F));
397  }
398 
399  auto YAML = Prog.toYAML();
400 
401  if (DumpRuntimeMD)
402  llvm::errs() << "AMDGPU runtime metadata:\n" << YAML << '\n';
403 
406 
407  return YAML;
408 }
static KernelArg::ValueType getRuntimeMDValueType(Type *Ty, StringRef TypeName)
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:102
Tracking metadata reference owned by Metadata.
Definition: Metadata.h:679
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void mapOptional(const char *Key, T &Val)
Definition: YAMLTraits.h:646
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:226
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:52
2: 32-bit floating point type
Definition: Type.h:58
unsigned getNumOperands() const
Return number of MDNode operands.
Definition: Metadata.h:1040
Metadata node.
Definition: Metadata.h:830
#define LLVM_YAML_IS_SEQUENCE_VECTOR(_type)
Utility for declaring that a std::vector of a particular type should be considered a YAML sequence...
Definition: YAMLTraits.h:1565
1: 16-bit floating point type
Definition: Type.h:57
static IntegerType * getInt64Ty(LLVMContext &C)
Definition: Type.cpp:170
Address space for local memory.
Definition: AMDGPU.h:141
FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > Tys=None)
Return the function type for an intrinsic.
Definition: Function.cpp:905
15: Pointers
Definition: Type.h:74
AddressSpaces
Definition: AMDGPU.h:137
Type * getPointerElementType() const
Definition: Type.h:358
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:191
const uint8_t INVALID_ADDR_QUAL
static void mapping(IO &YamlIO, KernelArg::Metadata &A)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
LLVM_ATTRIBUTE_ALWAYS_INLINE R Default(const T &Value) const
Definition: StringSwitch.h:244
Type * getVectorElementType() const
Definition: Type.h:353
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:154
The Input class is used to parse a yaml document into in-memory structs and vectors.
Definition: YAMLTraits.h:1099
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Case(const char(&S)[N], const T &Value)
Definition: StringSwitch.h:74
#define F(x, y, z)
Definition: MD5.cpp:51
This class should be specialized by any type that needs to be converted to/from a YAML mapping...
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:264
TypeID getTypeID() const
Return the type id for the type.
Definition: Type.h:136
static void mapping(IO &YamlIO, Kernel::Metadata &K)
Type * getElementType() const
Definition: DerivedTypes.h:336
const uint8_t INVALID_ACC_QUAL
Address space for region memory.
Definition: AMDGPU.h:143
11: Arbitrary bit width integers
Definition: Type.h:70
#define P(N)
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
static void mapping(IO &YamlIO, Program::Metadata &Prog)
iterator_range< iterator > functions()
Definition: Module.h:546
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
Address space for constant memory (VTX2)
Definition: AMDGPU.h:140
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const unsigned char MDRevision
const uint32_t INVALID_KERNEL_INDEX
unsigned getIntegerBitWidth() const
Definition: DerivedTypes.h:96
Address space for flat memory.
Definition: AMDGPU.h:142
The Output class is used to generate a yaml document from in-memory structs and vectors.
Definition: YAMLTraits.h:1249
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:213
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
Definition: raw_ostream.h:479
static Kernel::Metadata getRuntimeMDForKernel(const Function &F)
unsigned getABITypeAlignment(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
Definition: DataLayout.cpp:689
const MDOperand & getOperand(unsigned I) const
Definition: Metadata.h:1034
static void checkRuntimeMDYAMLString(const std::string &YAML)
Enums and structure types used by runtime metadata.
This is the shared class of boolean and integer constants.
Definition: Constants.h:88
16: SIMD 'packed' format, or other vector type
Definition: Type.h:75
uint64_t getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Definition: DataLayout.h:408
Module.h This file contains the declarations for the Module class.
static KernelArg::AddressSpaceQualifer getRuntimeAddrSpace(AMDGPUAS::AddressSpaces A)
Class to represent vector types.
Definition: DerivedTypes.h:369
const unsigned char MDVersion
static KernelArg::Metadata getRuntimeMDForKernelArg(const DataLayout &DL, Type *T, KernelArg::Kind Kind, StringRef BaseTypeName="", StringRef TypeName="", StringRef ArgName="", StringRef TypeQual="", StringRef AccQual="")
unsigned getVectorNumElements() const
Definition: DerivedTypes.h:438
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
Definition: Metadata.cpp:1391
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Cases(const char(&S0)[N0], const char(&S1)[N1], const T &Value)
Definition: StringSwitch.h:107
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition: Module.cpp:384
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
Definition: Module.cpp:265
static const size_t npos
Definition: StringRef.h:51
std::string getRuntimeMDYAMLString(Module &M)
static std::string getOCLTypeName(Type *Ty, bool Signed)
#define I(x, y, z)
Definition: MD5.cpp:54
static cl::opt< bool > CheckRuntimeMDParser("amdgpu-check-rtmd-parser", cl::Hidden, cl::desc("Check AMDGPU runtime metadata YAML parser"))
static std::vector< uint32_t > getThreeInt32(MDNode *Node)
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:287
op_range operands() const
Definition: Metadata.h:1032
const unsigned Kind
3: 64-bit floating point type
Definition: Type.h:59
#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type)
Utility for declaring that a std::vector of a particular type should be considered a YAML flow sequen...
Definition: YAMLTraits.h:1584
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:463
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:537
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
A single uniqued string.
Definition: Metadata.h:586
void mapRequired(const char *Key, T &Val)
Definition: YAMLTraits.h:637
static cl::opt< bool > DumpRuntimeMD("amdgpu-dump-rtmd", cl::desc("Dump AMDGPU runtime metadata"))
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Definition: DerivedTypes.h:479
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
Root of the metadata hierarchy.
Definition: Metadata.h:55
iterator_range< arg_iterator > args()
Definition: Function.h:568
Address space for global memory (RAT0, VTX0).
Definition: AMDGPU.h:139