blob: 9f5bcd8ff5f01947c612c96ea971148af20fea44 [file] [log] [blame]
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +00001//===--- AMDGPUHSAMetadataStreamer.cpp --------------------------*- C++ -*-===//
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +00006//
7//===----------------------------------------------------------------------===//
8//
9/// \file
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000010/// AMDGPU HSA Metadata Streamer.
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000011///
12//
13//===----------------------------------------------------------------------===//
14
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +000015#include "AMDGPUHSAMetadataStreamer.h"
Scott Linder2ad2c182018-07-10 17:31:32 +000016#include "AMDGPU.h"
17#include "AMDGPUSubtarget.h"
Scott Linderf5b36e52018-12-12 19:39:27 +000018#include "MCTargetDesc/AMDGPUTargetStreamer.h"
Scott Linder2ad2c182018-07-10 17:31:32 +000019#include "SIMachineFunctionInfo.h"
20#include "SIProgramInfo.h"
Konstantin Zhuravlyovf0badd52018-07-10 16:12:51 +000021#include "Utils/AMDGPUBaseInfo.h"
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000022#include "llvm/ADT/StringSwitch.h"
23#include "llvm/IR/Constants.h"
24#include "llvm/IR/Module.h"
Konstantin Zhuravlyov1e2b8782017-06-06 18:35:50 +000025#include "llvm/Support/raw_ostream.h"
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000026
27namespace llvm {
28
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +000029static cl::opt<bool> DumpHSAMetadata(
30 "amdgpu-dump-hsa-metadata",
31 cl::desc("Dump AMDGPU HSA Metadata"));
32static cl::opt<bool> VerifyHSAMetadata(
33 "amdgpu-verify-hsa-metadata",
34 cl::desc("Verify AMDGPU HSA Metadata"));
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000035
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000036namespace AMDGPU {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +000037namespace HSAMD {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000038
Scott Linderf5b36e52018-12-12 19:39:27 +000039//===----------------------------------------------------------------------===//
40// HSAMetadataStreamerV2
41//===----------------------------------------------------------------------===//
42void MetadataStreamerV2::dump(StringRef HSAMetadataString) const {
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +000043 errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000044}
45
Scott Linderf5b36e52018-12-12 19:39:27 +000046void MetadataStreamerV2::verify(StringRef HSAMetadataString) const {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +000047 errs() << "AMDGPU HSA Metadata Parser Test: ";
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000048
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +000049 HSAMD::Metadata FromHSAMetadataString;
50 if (fromString(HSAMetadataString, FromHSAMetadataString)) {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000051 errs() << "FAIL\n";
52 return;
53 }
54
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +000055 std::string ToHSAMetadataString;
56 if (toString(FromHSAMetadataString, ToHSAMetadataString)) {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000057 errs() << "FAIL\n";
58 return;
59 }
60
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +000061 errs() << (HSAMetadataString == ToHSAMetadataString ? "PASS" : "FAIL")
62 << '\n';
63 if (HSAMetadataString != ToHSAMetadataString) {
64 errs() << "Original input: " << HSAMetadataString << '\n'
65 << "Produced output: " << ToHSAMetadataString << '\n';
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000066 }
67}
68
Scott Linderf5b36e52018-12-12 19:39:27 +000069AccessQualifier
70MetadataStreamerV2::getAccessQualifier(StringRef AccQual) const {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000071 if (AccQual.empty())
72 return AccessQualifier::Unknown;
73
74 return StringSwitch<AccessQualifier>(AccQual)
75 .Case("read_only", AccessQualifier::ReadOnly)
76 .Case("write_only", AccessQualifier::WriteOnly)
77 .Case("read_write", AccessQualifier::ReadWrite)
78 .Default(AccessQualifier::Default);
79}
80
Scott Linderf5b36e52018-12-12 19:39:27 +000081AddressSpaceQualifier
82MetadataStreamerV2::getAddressSpaceQualifier(
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000083 unsigned AddressSpace) const {
Matt Arsenaultb9986742018-09-10 02:23:30 +000084 switch (AddressSpace) {
85 case AMDGPUAS::PRIVATE_ADDRESS:
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000086 return AddressSpaceQualifier::Private;
Matt Arsenaultb9986742018-09-10 02:23:30 +000087 case AMDGPUAS::GLOBAL_ADDRESS:
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000088 return AddressSpaceQualifier::Global;
Matt Arsenaultb9986742018-09-10 02:23:30 +000089 case AMDGPUAS::CONSTANT_ADDRESS:
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000090 return AddressSpaceQualifier::Constant;
Matt Arsenaultb9986742018-09-10 02:23:30 +000091 case AMDGPUAS::LOCAL_ADDRESS:
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000092 return AddressSpaceQualifier::Local;
Matt Arsenaultb9986742018-09-10 02:23:30 +000093 case AMDGPUAS::FLAT_ADDRESS:
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000094 return AddressSpaceQualifier::Generic;
Matt Arsenaultb9986742018-09-10 02:23:30 +000095 case AMDGPUAS::REGION_ADDRESS:
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000096 return AddressSpaceQualifier::Region;
Matt Arsenaultb9986742018-09-10 02:23:30 +000097 default:
98 return AddressSpaceQualifier::Unknown;
99 }
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000100}
101
Scott Linderf5b36e52018-12-12 19:39:27 +0000102ValueKind MetadataStreamerV2::getValueKind(Type *Ty, StringRef TypeQual,
103 StringRef BaseTypeName) const {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000104 if (TypeQual.find("pipe") != StringRef::npos)
105 return ValueKind::Pipe;
106
107 return StringSwitch<ValueKind>(BaseTypeName)
Konstantin Zhuravlyov54ba4312017-04-25 20:38:26 +0000108 .Case("image1d_t", ValueKind::Image)
109 .Case("image1d_array_t", ValueKind::Image)
110 .Case("image1d_buffer_t", ValueKind::Image)
111 .Case("image2d_t", ValueKind::Image)
112 .Case("image2d_array_t", ValueKind::Image)
113 .Case("image2d_array_depth_t", ValueKind::Image)
114 .Case("image2d_array_msaa_t", ValueKind::Image)
115 .Case("image2d_array_msaa_depth_t", ValueKind::Image)
116 .Case("image2d_depth_t", ValueKind::Image)
117 .Case("image2d_msaa_t", ValueKind::Image)
118 .Case("image2d_msaa_depth_t", ValueKind::Image)
119 .Case("image3d_t", ValueKind::Image)
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000120 .Case("sampler_t", ValueKind::Sampler)
121 .Case("queue_t", ValueKind::Queue)
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000122 .Default(isa<PointerType>(Ty) ?
123 (Ty->getPointerAddressSpace() ==
Matt Arsenault0da63502018-08-31 05:49:54 +0000124 AMDGPUAS::LOCAL_ADDRESS ?
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000125 ValueKind::DynamicSharedPointer :
126 ValueKind::GlobalBuffer) :
127 ValueKind::ByValue);
128}
129
Scott Linderf5b36e52018-12-12 19:39:27 +0000130ValueType MetadataStreamerV2::getValueType(Type *Ty, StringRef TypeName) const {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000131 switch (Ty->getTypeID()) {
132 case Type::IntegerTyID: {
133 auto Signed = !TypeName.startswith("u");
134 switch (Ty->getIntegerBitWidth()) {
135 case 8:
136 return Signed ? ValueType::I8 : ValueType::U8;
137 case 16:
138 return Signed ? ValueType::I16 : ValueType::U16;
139 case 32:
140 return Signed ? ValueType::I32 : ValueType::U32;
141 case 64:
142 return Signed ? ValueType::I64 : ValueType::U64;
143 default:
144 return ValueType::Struct;
145 }
146 }
147 case Type::HalfTyID:
148 return ValueType::F16;
149 case Type::FloatTyID:
150 return ValueType::F32;
151 case Type::DoubleTyID:
152 return ValueType::F64;
153 case Type::PointerTyID:
154 return getValueType(Ty->getPointerElementType(), TypeName);
155 case Type::VectorTyID:
156 return getValueType(Ty->getVectorElementType(), TypeName);
157 default:
158 return ValueType::Struct;
159 }
160}
161
Scott Linderf5b36e52018-12-12 19:39:27 +0000162std::string MetadataStreamerV2::getTypeName(Type *Ty, bool Signed) const {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000163 switch (Ty->getTypeID()) {
164 case Type::IntegerTyID: {
165 if (!Signed)
166 return (Twine('u') + getTypeName(Ty, true)).str();
167
168 auto BitWidth = Ty->getIntegerBitWidth();
169 switch (BitWidth) {
170 case 8:
171 return "char";
172 case 16:
173 return "short";
174 case 32:
175 return "int";
176 case 64:
177 return "long";
178 default:
179 return (Twine('i') + Twine(BitWidth)).str();
180 }
181 }
182 case Type::HalfTyID:
183 return "half";
184 case Type::FloatTyID:
185 return "float";
186 case Type::DoubleTyID:
187 return "double";
188 case Type::VectorTyID: {
189 auto VecTy = cast<VectorType>(Ty);
190 auto ElTy = VecTy->getElementType();
191 auto NumElements = VecTy->getVectorNumElements();
192 return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
193 }
194 default:
195 return "unknown";
196 }
197}
198
Scott Linderf5b36e52018-12-12 19:39:27 +0000199std::vector<uint32_t>
200MetadataStreamerV2::getWorkGroupDimensions(MDNode *Node) const {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000201 std::vector<uint32_t> Dims;
202 if (Node->getNumOperands() != 3)
203 return Dims;
204
205 for (auto &Op : Node->operands())
206 Dims.push_back(mdconst::extract<ConstantInt>(Op)->getZExtValue());
207 return Dims;
208}
209
Scott Linderf5b36e52018-12-12 19:39:27 +0000210Kernel::CodeProps::Metadata
211MetadataStreamerV2::getHSACodeProps(const MachineFunction &MF,
212 const SIProgramInfo &ProgramInfo) const {
Tom Stellard5bfbae52018-07-11 20:59:01 +0000213 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
Scott Linder2ad2c182018-07-10 17:31:32 +0000214 const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
215 HSAMD::Kernel::CodeProps::Metadata HSACodeProps;
216 const Function &F = MF.getFunction();
217
Matt Arsenault4bec7d42018-07-20 09:05:08 +0000218 assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
219 F.getCallingConv() == CallingConv::SPIR_KERNEL);
Scott Linder2ad2c182018-07-10 17:31:32 +0000220
Guillaume Chateletb65fa482019-10-15 12:56:24 +0000221 Align MaxKernArgAlign;
Matt Arsenault4bec7d42018-07-20 09:05:08 +0000222 HSACodeProps.mKernargSegmentSize = STM.getKernArgSegmentSize(F,
223 MaxKernArgAlign);
Scott Linder2ad2c182018-07-10 17:31:32 +0000224 HSACodeProps.mGroupSegmentFixedSize = ProgramInfo.LDSSize;
225 HSACodeProps.mPrivateSegmentFixedSize = ProgramInfo.ScratchSize;
Guillaume Chateletb65fa482019-10-15 12:56:24 +0000226 HSACodeProps.mKernargSegmentAlign =
227 std::max(MaxKernArgAlign, Align(4)).value();
Scott Linder2ad2c182018-07-10 17:31:32 +0000228 HSACodeProps.mWavefrontSize = STM.getWavefrontSize();
229 HSACodeProps.mNumSGPRs = ProgramInfo.NumSGPR;
230 HSACodeProps.mNumVGPRs = ProgramInfo.NumVGPR;
231 HSACodeProps.mMaxFlatWorkGroupSize = MFI.getMaxFlatWorkGroupSize();
232 HSACodeProps.mIsDynamicCallStack = ProgramInfo.DynamicCallStack;
233 HSACodeProps.mIsXNACKEnabled = STM.isXNACKEnabled();
234 HSACodeProps.mNumSpilledSGPRs = MFI.getNumSpilledSGPRs();
235 HSACodeProps.mNumSpilledVGPRs = MFI.getNumSpilledVGPRs();
236
237 return HSACodeProps;
238}
239
Scott Linderf5b36e52018-12-12 19:39:27 +0000240Kernel::DebugProps::Metadata
241MetadataStreamerV2::getHSADebugProps(const MachineFunction &MF,
242 const SIProgramInfo &ProgramInfo) const {
Matt Arsenaultaa6fb4c2019-02-21 23:27:46 +0000243 return HSAMD::Kernel::DebugProps::Metadata();
Scott Linder2ad2c182018-07-10 17:31:32 +0000244}
245
Scott Linderf5b36e52018-12-12 19:39:27 +0000246void MetadataStreamerV2::emitVersion() {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000247 auto &Version = HSAMetadata.mVersion;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000248
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000249 Version.push_back(VersionMajor);
250 Version.push_back(VersionMinor);
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000251}
252
Scott Linderf5b36e52018-12-12 19:39:27 +0000253void MetadataStreamerV2::emitPrintf(const Module &Mod) {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000254 auto &Printf = HSAMetadata.mPrintf;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000255
256 auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
257 if (!Node)
258 return;
259
260 for (auto Op : Node->operands())
261 if (Op->getNumOperands())
262 Printf.push_back(cast<MDString>(Op->getOperand(0))->getString());
263}
264
Scott Linderf5b36e52018-12-12 19:39:27 +0000265void MetadataStreamerV2::emitKernelLanguage(const Function &Func) {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000266 auto &Kernel = HSAMetadata.mKernels.back();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000267
268 // TODO: What about other languages?
269 auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
270 if (!Node || !Node->getNumOperands())
271 return;
272 auto Op0 = Node->getOperand(0);
273 if (Op0->getNumOperands() <= 1)
274 return;
275
276 Kernel.mLanguage = "OpenCL C";
277 Kernel.mLanguageVersion.push_back(
278 mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue());
279 Kernel.mLanguageVersion.push_back(
280 mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue());
281}
282
Scott Linderf5b36e52018-12-12 19:39:27 +0000283void MetadataStreamerV2::emitKernelAttrs(const Function &Func) {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000284 auto &Attrs = HSAMetadata.mKernels.back().mAttrs;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000285
286 if (auto Node = Func.getMetadata("reqd_work_group_size"))
287 Attrs.mReqdWorkGroupSize = getWorkGroupDimensions(Node);
288 if (auto Node = Func.getMetadata("work_group_size_hint"))
289 Attrs.mWorkGroupSizeHint = getWorkGroupDimensions(Node);
290 if (auto Node = Func.getMetadata("vec_type_hint")) {
291 Attrs.mVecTypeHint = getTypeName(
292 cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
293 mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue());
294 }
Yaxun Liude4b88d2017-10-10 19:39:48 +0000295 if (Func.hasFnAttribute("runtime-handle")) {
296 Attrs.mRuntimeHandle =
297 Func.getFnAttribute("runtime-handle").getValueAsString().str();
298 }
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000299}
300
Scott Linderf5b36e52018-12-12 19:39:27 +0000301void MetadataStreamerV2::emitKernelArgs(const Function &Func) {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000302 for (auto &Arg : Func.args())
303 emitKernelArg(Arg);
304
Konstantin Zhuravlyovf0badd52018-07-10 16:12:51 +0000305 emitHiddenKernelArgs(Func);
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000306}
307
Scott Linderf5b36e52018-12-12 19:39:27 +0000308void MetadataStreamerV2::emitKernelArg(const Argument &Arg) {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000309 auto Func = Arg.getParent();
310 auto ArgNo = Arg.getArgNo();
311 const MDNode *Node;
312
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000313 StringRef Name;
314 Node = Func->getMetadata("kernel_arg_name");
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000315 if (Node && ArgNo < Node->getNumOperands())
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000316 Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
Konstantin Zhuravlyove30f88f2017-12-08 19:22:12 +0000317 else if (Arg.hasName())
318 Name = Arg.getName();
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000319
320 StringRef TypeName;
321 Node = Func->getMetadata("kernel_arg_type");
322 if (Node && ArgNo < Node->getNumOperands())
323 TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000324
325 StringRef BaseTypeName;
326 Node = Func->getMetadata("kernel_arg_base_type");
327 if (Node && ArgNo < Node->getNumOperands())
328 BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
329
330 StringRef AccQual;
Stanislav Mekhanoshineff0bc72017-04-14 19:11:40 +0000331 if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
332 Arg.hasNoAliasAttr()) {
333 AccQual = "read_only";
334 } else {
335 Node = Func->getMetadata("kernel_arg_access_qual");
336 if (Node && ArgNo < Node->getNumOperands())
337 AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
338 }
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000339
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000340 StringRef TypeQual;
341 Node = Func->getMetadata("kernel_arg_type_qual");
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000342 if (Node && ArgNo < Node->getNumOperands())
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000343 TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000344
Matt Arsenault73eeb422018-06-25 14:29:04 +0000345 Type *Ty = Arg.getType();
346 const DataLayout &DL = Func->getParent()->getDataLayout();
347
348 unsigned PointeeAlign = 0;
349 if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
Matt Arsenault0da63502018-08-31 05:49:54 +0000350 if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
Matt Arsenault73eeb422018-06-25 14:29:04 +0000351 PointeeAlign = Arg.getParamAlignment();
352 if (PointeeAlign == 0)
353 PointeeAlign = DL.getABITypeAlignment(PtrTy->getElementType());
354 }
355 }
356
357 emitKernelArg(DL, Ty, getValueKind(Arg.getType(), TypeQual, BaseTypeName),
358 PointeeAlign, Name, TypeName, BaseTypeName, AccQual, TypeQual);
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000359}
360
Scott Linderf5b36e52018-12-12 19:39:27 +0000361void MetadataStreamerV2::emitKernelArg(const DataLayout &DL, Type *Ty,
362 ValueKind ValueKind,
363 unsigned PointeeAlign, StringRef Name,
364 StringRef TypeName,
365 StringRef BaseTypeName,
366 StringRef AccQual, StringRef TypeQual) {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000367 HSAMetadata.mKernels.back().mArgs.push_back(Kernel::Arg::Metadata());
368 auto &Arg = HSAMetadata.mKernels.back().mArgs.back();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000369
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000370 Arg.mName = Name;
371 Arg.mTypeName = TypeName;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000372 Arg.mSize = DL.getTypeAllocSize(Ty);
373 Arg.mAlign = DL.getABITypeAlignment(Ty);
374 Arg.mValueKind = ValueKind;
375 Arg.mValueType = getValueType(Ty, BaseTypeName);
Matt Arsenault73eeb422018-06-25 14:29:04 +0000376 Arg.mPointeeAlign = PointeeAlign;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000377
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000378 if (auto PtrTy = dyn_cast<PointerType>(Ty))
Scott Linderf5b36e52018-12-12 19:39:27 +0000379 Arg.mAddrSpaceQual = getAddressSpaceQualifier(PtrTy->getAddressSpace());
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000380
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000381 Arg.mAccQual = getAccessQualifier(AccQual);
382
383 // TODO: Emit Arg.mActualAccQual.
384
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000385 SmallVector<StringRef, 1> SplitTypeQuals;
386 TypeQual.split(SplitTypeQuals, " ", -1, false);
387 for (StringRef Key : SplitTypeQuals) {
388 auto P = StringSwitch<bool*>(Key)
389 .Case("const", &Arg.mIsConst)
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000390 .Case("restrict", &Arg.mIsRestrict)
391 .Case("volatile", &Arg.mIsVolatile)
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000392 .Case("pipe", &Arg.mIsPipe)
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000393 .Default(nullptr);
394 if (P)
395 *P = true;
396 }
Konstantin Zhuravlyova780ffa2017-03-22 23:10:46 +0000397}
398
Scott Linderf5b36e52018-12-12 19:39:27 +0000399void MetadataStreamerV2::emitHiddenKernelArgs(const Function &Func) {
Konstantin Zhuravlyovf0badd52018-07-10 16:12:51 +0000400 int HiddenArgNumBytes =
401 getIntegerAttribute(Func, "amdgpu-implicitarg-num-bytes", 0);
402
403 if (!HiddenArgNumBytes)
404 return;
405
406 auto &DL = Func.getParent()->getDataLayout();
407 auto Int64Ty = Type::getInt64Ty(Func.getContext());
408
409 if (HiddenArgNumBytes >= 8)
410 emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetX);
411 if (HiddenArgNumBytes >= 16)
412 emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetY);
413 if (HiddenArgNumBytes >= 24)
414 emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetZ);
415
416 auto Int8PtrTy = Type::getInt8PtrTy(Func.getContext(),
Matt Arsenault0da63502018-08-31 05:49:54 +0000417 AMDGPUAS::GLOBAL_ADDRESS);
Konstantin Zhuravlyovf0badd52018-07-10 16:12:51 +0000418
419 // Emit "printf buffer" argument if printf is used, otherwise emit dummy
420 // "none" argument.
421 if (HiddenArgNumBytes >= 32) {
422 if (Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
423 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenPrintfBuffer);
424 else
425 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
426 }
427
428 // Emit "default queue" and "completion action" arguments if enqueue kernel is
429 // used, otherwise emit dummy "none" arguments.
430 if (HiddenArgNumBytes >= 48) {
431 if (Func.hasFnAttribute("calls-enqueue-kernel")) {
432 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenDefaultQueue);
433 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenCompletionAction);
434 } else {
435 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
436 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
437 }
438 }
Yaxun Liua6241352019-07-05 16:05:17 +0000439
440 // Emit the pointer argument for multi-grid object.
441 if (HiddenArgNumBytes >= 56)
442 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenMultiGridSyncArg);
Konstantin Zhuravlyovf0badd52018-07-10 16:12:51 +0000443}
444
Scott Linderf5b36e52018-12-12 19:39:27 +0000445bool MetadataStreamerV2::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
446 return TargetStreamer.EmitHSAMetadata(getHSAMetadata());
447}
448
449void MetadataStreamerV2::begin(const Module &Mod) {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000450 emitVersion();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000451 emitPrintf(Mod);
452}
453
Scott Linderf5b36e52018-12-12 19:39:27 +0000454void MetadataStreamerV2::end() {
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +0000455 std::string HSAMetadataString;
Konstantin Zhuravlyov63e87f52017-10-12 17:34:05 +0000456 if (toString(HSAMetadata, HSAMetadataString))
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +0000457 return;
458
459 if (DumpHSAMetadata)
460 dump(HSAMetadataString);
461 if (VerifyHSAMetadata)
462 verify(HSAMetadataString);
463}
464
Scott Linderf5b36e52018-12-12 19:39:27 +0000465void MetadataStreamerV2::emitKernel(const MachineFunction &MF,
466 const SIProgramInfo &ProgramInfo) {
Scott Linder2ad2c182018-07-10 17:31:32 +0000467 auto &Func = MF.getFunction();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000468 if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL)
469 return;
470
Matt Arsenault4bec7d42018-07-20 09:05:08 +0000471 auto CodeProps = getHSACodeProps(MF, ProgramInfo);
472 auto DebugProps = getHSADebugProps(MF, ProgramInfo);
473
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000474 HSAMetadata.mKernels.push_back(Kernel::Metadata());
475 auto &Kernel = HSAMetadata.mKernels.back();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000476
477 Kernel.mName = Func.getName();
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000478 Kernel.mSymbolName = (Twine(Func.getName()) + Twine("@kd")).str();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000479 emitKernelLanguage(Func);
480 emitKernelAttrs(Func);
481 emitKernelArgs(Func);
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000482 HSAMetadata.mKernels.back().mCodeProps = CodeProps;
483 HSAMetadata.mKernels.back().mDebugProps = DebugProps;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000484}
485
Scott Linderf5b36e52018-12-12 19:39:27 +0000486//===----------------------------------------------------------------------===//
487// HSAMetadataStreamerV3
488//===----------------------------------------------------------------------===//
489
490void MetadataStreamerV3::dump(StringRef HSAMetadataString) const {
491 errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
492}
493
494void MetadataStreamerV3::verify(StringRef HSAMetadataString) const {
495 errs() << "AMDGPU HSA Metadata Parser Test: ";
496
Tim Renoufed0b9af2019-03-13 18:55:50 +0000497 msgpack::Document FromHSAMetadataString;
Scott Linderf5b36e52018-12-12 19:39:27 +0000498
Tim Renoufed0b9af2019-03-13 18:55:50 +0000499 if (!FromHSAMetadataString.fromYAML(HSAMetadataString)) {
Scott Linderf5b36e52018-12-12 19:39:27 +0000500 errs() << "FAIL\n";
501 return;
502 }
503
504 std::string ToHSAMetadataString;
505 raw_string_ostream StrOS(ToHSAMetadataString);
Tim Renoufed0b9af2019-03-13 18:55:50 +0000506 FromHSAMetadataString.toYAML(StrOS);
Scott Linderf5b36e52018-12-12 19:39:27 +0000507
508 errs() << (HSAMetadataString == StrOS.str() ? "PASS" : "FAIL") << '\n';
509 if (HSAMetadataString != ToHSAMetadataString) {
510 errs() << "Original input: " << HSAMetadataString << '\n'
511 << "Produced output: " << StrOS.str() << '\n';
512 }
513}
514
515Optional<StringRef>
516MetadataStreamerV3::getAccessQualifier(StringRef AccQual) const {
517 return StringSwitch<Optional<StringRef>>(AccQual)
518 .Case("read_only", StringRef("read_only"))
519 .Case("write_only", StringRef("write_only"))
520 .Case("read_write", StringRef("read_write"))
521 .Default(None);
522}
523
524Optional<StringRef>
525MetadataStreamerV3::getAddressSpaceQualifier(unsigned AddressSpace) const {
526 switch (AddressSpace) {
527 case AMDGPUAS::PRIVATE_ADDRESS:
528 return StringRef("private");
529 case AMDGPUAS::GLOBAL_ADDRESS:
530 return StringRef("global");
531 case AMDGPUAS::CONSTANT_ADDRESS:
532 return StringRef("constant");
533 case AMDGPUAS::LOCAL_ADDRESS:
534 return StringRef("local");
535 case AMDGPUAS::FLAT_ADDRESS:
536 return StringRef("generic");
537 case AMDGPUAS::REGION_ADDRESS:
538 return StringRef("region");
539 default:
540 return None;
541 }
542}
543
544StringRef MetadataStreamerV3::getValueKind(Type *Ty, StringRef TypeQual,
545 StringRef BaseTypeName) const {
546 if (TypeQual.find("pipe") != StringRef::npos)
547 return "pipe";
548
549 return StringSwitch<StringRef>(BaseTypeName)
550 .Case("image1d_t", "image")
551 .Case("image1d_array_t", "image")
552 .Case("image1d_buffer_t", "image")
553 .Case("image2d_t", "image")
554 .Case("image2d_array_t", "image")
555 .Case("image2d_array_depth_t", "image")
556 .Case("image2d_array_msaa_t", "image")
557 .Case("image2d_array_msaa_depth_t", "image")
558 .Case("image2d_depth_t", "image")
559 .Case("image2d_msaa_t", "image")
560 .Case("image2d_msaa_depth_t", "image")
561 .Case("image3d_t", "image")
562 .Case("sampler_t", "sampler")
563 .Case("queue_t", "queue")
564 .Default(isa<PointerType>(Ty)
565 ? (Ty->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS
566 ? "dynamic_shared_pointer"
567 : "global_buffer")
568 : "by_value");
569}
570
571StringRef MetadataStreamerV3::getValueType(Type *Ty, StringRef TypeName) const {
572 switch (Ty->getTypeID()) {
573 case Type::IntegerTyID: {
574 auto Signed = !TypeName.startswith("u");
575 switch (Ty->getIntegerBitWidth()) {
576 case 8:
577 return Signed ? "i8" : "u8";
578 case 16:
579 return Signed ? "i16" : "u16";
580 case 32:
581 return Signed ? "i32" : "u32";
582 case 64:
583 return Signed ? "i64" : "u64";
584 default:
585 return "struct";
586 }
587 }
588 case Type::HalfTyID:
589 return "f16";
590 case Type::FloatTyID:
591 return "f32";
592 case Type::DoubleTyID:
593 return "f64";
594 case Type::PointerTyID:
595 return getValueType(Ty->getPointerElementType(), TypeName);
596 case Type::VectorTyID:
597 return getValueType(Ty->getVectorElementType(), TypeName);
598 default:
599 return "struct";
600 }
601}
602
603std::string MetadataStreamerV3::getTypeName(Type *Ty, bool Signed) const {
604 switch (Ty->getTypeID()) {
605 case Type::IntegerTyID: {
606 if (!Signed)
607 return (Twine('u') + getTypeName(Ty, true)).str();
608
609 auto BitWidth = Ty->getIntegerBitWidth();
610 switch (BitWidth) {
611 case 8:
612 return "char";
613 case 16:
614 return "short";
615 case 32:
616 return "int";
617 case 64:
618 return "long";
619 default:
620 return (Twine('i') + Twine(BitWidth)).str();
621 }
622 }
623 case Type::HalfTyID:
624 return "half";
625 case Type::FloatTyID:
626 return "float";
627 case Type::DoubleTyID:
628 return "double";
629 case Type::VectorTyID: {
630 auto VecTy = cast<VectorType>(Ty);
631 auto ElTy = VecTy->getElementType();
632 auto NumElements = VecTy->getVectorNumElements();
633 return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
634 }
635 default:
636 return "unknown";
637 }
638}
639
Tim Renoufed0b9af2019-03-13 18:55:50 +0000640msgpack::ArrayDocNode
Scott Linderf5b36e52018-12-12 19:39:27 +0000641MetadataStreamerV3::getWorkGroupDimensions(MDNode *Node) const {
Tim Renoufed0b9af2019-03-13 18:55:50 +0000642 auto Dims = HSAMetadataDoc->getArrayNode();
Scott Linderf5b36e52018-12-12 19:39:27 +0000643 if (Node->getNumOperands() != 3)
644 return Dims;
645
646 for (auto &Op : Node->operands())
Tim Renoufed0b9af2019-03-13 18:55:50 +0000647 Dims.push_back(Dims.getDocument()->getNode(
648 uint64_t(mdconst::extract<ConstantInt>(Op)->getZExtValue())));
Scott Linderf5b36e52018-12-12 19:39:27 +0000649 return Dims;
650}
651
652void MetadataStreamerV3::emitVersion() {
Tim Renoufed0b9af2019-03-13 18:55:50 +0000653 auto Version = HSAMetadataDoc->getArrayNode();
654 Version.push_back(Version.getDocument()->getNode(VersionMajor));
655 Version.push_back(Version.getDocument()->getNode(VersionMinor));
656 getRootMetadata("amdhsa.version") = Version;
Scott Linderf5b36e52018-12-12 19:39:27 +0000657}
658
659void MetadataStreamerV3::emitPrintf(const Module &Mod) {
660 auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
661 if (!Node)
662 return;
663
Tim Renoufed0b9af2019-03-13 18:55:50 +0000664 auto Printf = HSAMetadataDoc->getArrayNode();
Scott Linderf5b36e52018-12-12 19:39:27 +0000665 for (auto Op : Node->operands())
666 if (Op->getNumOperands())
Tim Renoufed0b9af2019-03-13 18:55:50 +0000667 Printf.push_back(Printf.getDocument()->getNode(
668 cast<MDString>(Op->getOperand(0))->getString(), /*Copy=*/true));
669 getRootMetadata("amdhsa.printf") = Printf;
Scott Linderf5b36e52018-12-12 19:39:27 +0000670}
671
672void MetadataStreamerV3::emitKernelLanguage(const Function &Func,
Tim Renoufed0b9af2019-03-13 18:55:50 +0000673 msgpack::MapDocNode Kern) {
Scott Linderf5b36e52018-12-12 19:39:27 +0000674 // TODO: What about other languages?
675 auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
676 if (!Node || !Node->getNumOperands())
677 return;
678 auto Op0 = Node->getOperand(0);
679 if (Op0->getNumOperands() <= 1)
680 return;
681
Tim Renoufed0b9af2019-03-13 18:55:50 +0000682 Kern[".language"] = Kern.getDocument()->getNode("OpenCL C");
683 auto LanguageVersion = Kern.getDocument()->getArrayNode();
684 LanguageVersion.push_back(Kern.getDocument()->getNode(
Scott Linderf5b36e52018-12-12 19:39:27 +0000685 mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue()));
Tim Renoufed0b9af2019-03-13 18:55:50 +0000686 LanguageVersion.push_back(Kern.getDocument()->getNode(
Scott Linderf5b36e52018-12-12 19:39:27 +0000687 mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue()));
Tim Renoufed0b9af2019-03-13 18:55:50 +0000688 Kern[".language_version"] = LanguageVersion;
Scott Linderf5b36e52018-12-12 19:39:27 +0000689}
690
691void MetadataStreamerV3::emitKernelAttrs(const Function &Func,
Tim Renoufed0b9af2019-03-13 18:55:50 +0000692 msgpack::MapDocNode Kern) {
Scott Linderf5b36e52018-12-12 19:39:27 +0000693
694 if (auto Node = Func.getMetadata("reqd_work_group_size"))
695 Kern[".reqd_workgroup_size"] = getWorkGroupDimensions(Node);
696 if (auto Node = Func.getMetadata("work_group_size_hint"))
697 Kern[".workgroup_size_hint"] = getWorkGroupDimensions(Node);
698 if (auto Node = Func.getMetadata("vec_type_hint")) {
Tim Renoufed0b9af2019-03-13 18:55:50 +0000699 Kern[".vec_type_hint"] = Kern.getDocument()->getNode(
700 getTypeName(
701 cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
702 mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()),
703 /*Copy=*/true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000704 }
705 if (Func.hasFnAttribute("runtime-handle")) {
Tim Renoufed0b9af2019-03-13 18:55:50 +0000706 Kern[".device_enqueue_symbol"] = Kern.getDocument()->getNode(
707 Func.getFnAttribute("runtime-handle").getValueAsString().str(),
708 /*Copy=*/true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000709 }
710}
711
712void MetadataStreamerV3::emitKernelArgs(const Function &Func,
Tim Renoufed0b9af2019-03-13 18:55:50 +0000713 msgpack::MapDocNode Kern) {
Scott Linderf5b36e52018-12-12 19:39:27 +0000714 unsigned Offset = 0;
Tim Renoufed0b9af2019-03-13 18:55:50 +0000715 auto Args = HSAMetadataDoc->getArrayNode();
Scott Linderf5b36e52018-12-12 19:39:27 +0000716 for (auto &Arg : Func.args())
Tim Renoufed0b9af2019-03-13 18:55:50 +0000717 emitKernelArg(Arg, Offset, Args);
Scott Linderf5b36e52018-12-12 19:39:27 +0000718
Tim Renoufed0b9af2019-03-13 18:55:50 +0000719 emitHiddenKernelArgs(Func, Offset, Args);
Scott Linderf5b36e52018-12-12 19:39:27 +0000720
Tim Renoufed0b9af2019-03-13 18:55:50 +0000721 Kern[".args"] = Args;
Scott Linderf5b36e52018-12-12 19:39:27 +0000722}
723
724void MetadataStreamerV3::emitKernelArg(const Argument &Arg, unsigned &Offset,
Tim Renoufed0b9af2019-03-13 18:55:50 +0000725 msgpack::ArrayDocNode Args) {
Scott Linderf5b36e52018-12-12 19:39:27 +0000726 auto Func = Arg.getParent();
727 auto ArgNo = Arg.getArgNo();
728 const MDNode *Node;
729
730 StringRef Name;
731 Node = Func->getMetadata("kernel_arg_name");
732 if (Node && ArgNo < Node->getNumOperands())
733 Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
734 else if (Arg.hasName())
735 Name = Arg.getName();
736
737 StringRef TypeName;
738 Node = Func->getMetadata("kernel_arg_type");
739 if (Node && ArgNo < Node->getNumOperands())
740 TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
741
742 StringRef BaseTypeName;
743 Node = Func->getMetadata("kernel_arg_base_type");
744 if (Node && ArgNo < Node->getNumOperands())
745 BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
746
747 StringRef AccQual;
748 if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
749 Arg.hasNoAliasAttr()) {
750 AccQual = "read_only";
751 } else {
752 Node = Func->getMetadata("kernel_arg_access_qual");
753 if (Node && ArgNo < Node->getNumOperands())
754 AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
755 }
756
757 StringRef TypeQual;
758 Node = Func->getMetadata("kernel_arg_type_qual");
759 if (Node && ArgNo < Node->getNumOperands())
760 TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
761
762 Type *Ty = Arg.getType();
763 const DataLayout &DL = Func->getParent()->getDataLayout();
764
765 unsigned PointeeAlign = 0;
766 if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
767 if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
768 PointeeAlign = Arg.getParamAlignment();
769 if (PointeeAlign == 0)
770 PointeeAlign = DL.getABITypeAlignment(PtrTy->getElementType());
771 }
772 }
773
774 emitKernelArg(Func->getParent()->getDataLayout(), Arg.getType(),
775 getValueKind(Arg.getType(), TypeQual, BaseTypeName), Offset,
776 Args, PointeeAlign, Name, TypeName, BaseTypeName, AccQual,
777 TypeQual);
778}
779
780void MetadataStreamerV3::emitKernelArg(const DataLayout &DL, Type *Ty,
781 StringRef ValueKind, unsigned &Offset,
Tim Renoufed0b9af2019-03-13 18:55:50 +0000782 msgpack::ArrayDocNode Args,
Scott Linderf5b36e52018-12-12 19:39:27 +0000783 unsigned PointeeAlign, StringRef Name,
784 StringRef TypeName,
785 StringRef BaseTypeName,
786 StringRef AccQual, StringRef TypeQual) {
Tim Renoufed0b9af2019-03-13 18:55:50 +0000787 auto Arg = Args.getDocument()->getMapNode();
Scott Linderf5b36e52018-12-12 19:39:27 +0000788
789 if (!Name.empty())
Tim Renoufed0b9af2019-03-13 18:55:50 +0000790 Arg[".name"] = Arg.getDocument()->getNode(Name, /*Copy=*/true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000791 if (!TypeName.empty())
Tim Renoufed0b9af2019-03-13 18:55:50 +0000792 Arg[".type_name"] = Arg.getDocument()->getNode(TypeName, /*Copy=*/true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000793 auto Size = DL.getTypeAllocSize(Ty);
794 auto Align = DL.getABITypeAlignment(Ty);
Tim Renoufed0b9af2019-03-13 18:55:50 +0000795 Arg[".size"] = Arg.getDocument()->getNode(Size);
Scott Linderf5b36e52018-12-12 19:39:27 +0000796 Offset = alignTo(Offset, Align);
Tim Renoufed0b9af2019-03-13 18:55:50 +0000797 Arg[".offset"] = Arg.getDocument()->getNode(Offset);
Scott Linderf5b36e52018-12-12 19:39:27 +0000798 Offset += Size;
Tim Renoufed0b9af2019-03-13 18:55:50 +0000799 Arg[".value_kind"] = Arg.getDocument()->getNode(ValueKind, /*Copy=*/true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000800 Arg[".value_type"] =
Tim Renoufed0b9af2019-03-13 18:55:50 +0000801 Arg.getDocument()->getNode(getValueType(Ty, BaseTypeName), /*Copy=*/true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000802 if (PointeeAlign)
Tim Renoufed0b9af2019-03-13 18:55:50 +0000803 Arg[".pointee_align"] = Arg.getDocument()->getNode(PointeeAlign);
Scott Linderf5b36e52018-12-12 19:39:27 +0000804
805 if (auto PtrTy = dyn_cast<PointerType>(Ty))
806 if (auto Qualifier = getAddressSpaceQualifier(PtrTy->getAddressSpace()))
Tim Renoufed0b9af2019-03-13 18:55:50 +0000807 Arg[".address_space"] = Arg.getDocument()->getNode(*Qualifier, /*Copy=*/true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000808
809 if (auto AQ = getAccessQualifier(AccQual))
Tim Renoufed0b9af2019-03-13 18:55:50 +0000810 Arg[".access"] = Arg.getDocument()->getNode(*AQ, /*Copy=*/true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000811
812 // TODO: Emit Arg[".actual_access"].
813
814 SmallVector<StringRef, 1> SplitTypeQuals;
815 TypeQual.split(SplitTypeQuals, " ", -1, false);
816 for (StringRef Key : SplitTypeQuals) {
817 if (Key == "const")
Tim Renoufed0b9af2019-03-13 18:55:50 +0000818 Arg[".is_const"] = Arg.getDocument()->getNode(true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000819 else if (Key == "restrict")
Tim Renoufed0b9af2019-03-13 18:55:50 +0000820 Arg[".is_restrict"] = Arg.getDocument()->getNode(true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000821 else if (Key == "volatile")
Tim Renoufed0b9af2019-03-13 18:55:50 +0000822 Arg[".is_volatile"] = Arg.getDocument()->getNode(true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000823 else if (Key == "pipe")
Tim Renoufed0b9af2019-03-13 18:55:50 +0000824 Arg[".is_pipe"] = Arg.getDocument()->getNode(true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000825 }
826
Tim Renoufed0b9af2019-03-13 18:55:50 +0000827 Args.push_back(Arg);
Scott Linderf5b36e52018-12-12 19:39:27 +0000828}
829
830void MetadataStreamerV3::emitHiddenKernelArgs(const Function &Func,
831 unsigned &Offset,
Tim Renoufed0b9af2019-03-13 18:55:50 +0000832 msgpack::ArrayDocNode Args) {
Scott Linderf5b36e52018-12-12 19:39:27 +0000833 int HiddenArgNumBytes =
834 getIntegerAttribute(Func, "amdgpu-implicitarg-num-bytes", 0);
835
836 if (!HiddenArgNumBytes)
837 return;
838
839 auto &DL = Func.getParent()->getDataLayout();
840 auto Int64Ty = Type::getInt64Ty(Func.getContext());
841
842 if (HiddenArgNumBytes >= 8)
843 emitKernelArg(DL, Int64Ty, "hidden_global_offset_x", Offset, Args);
844 if (HiddenArgNumBytes >= 16)
845 emitKernelArg(DL, Int64Ty, "hidden_global_offset_y", Offset, Args);
846 if (HiddenArgNumBytes >= 24)
847 emitKernelArg(DL, Int64Ty, "hidden_global_offset_z", Offset, Args);
848
849 auto Int8PtrTy =
850 Type::getInt8PtrTy(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
851
852 // Emit "printf buffer" argument if printf is used, otherwise emit dummy
853 // "none" argument.
854 if (HiddenArgNumBytes >= 32) {
855 if (Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
856 emitKernelArg(DL, Int8PtrTy, "hidden_printf_buffer", Offset, Args);
857 else
858 emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, Args);
859 }
860
861 // Emit "default queue" and "completion action" arguments if enqueue kernel is
862 // used, otherwise emit dummy "none" arguments.
863 if (HiddenArgNumBytes >= 48) {
864 if (Func.hasFnAttribute("calls-enqueue-kernel")) {
865 emitKernelArg(DL, Int8PtrTy, "hidden_default_queue", Offset, Args);
866 emitKernelArg(DL, Int8PtrTy, "hidden_completion_action", Offset, Args);
867 } else {
868 emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, Args);
869 emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, Args);
870 }
871 }
Yaxun Liua6241352019-07-05 16:05:17 +0000872
873 // Emit the pointer argument for multi-grid object.
874 if (HiddenArgNumBytes >= 56)
875 emitKernelArg(DL, Int8PtrTy, "hidden_multigrid_sync_arg", Offset, Args);
Scott Linderf5b36e52018-12-12 19:39:27 +0000876}
877
Tim Renoufed0b9af2019-03-13 18:55:50 +0000878msgpack::MapDocNode
Scott Linderf5b36e52018-12-12 19:39:27 +0000879MetadataStreamerV3::getHSAKernelProps(const MachineFunction &MF,
880 const SIProgramInfo &ProgramInfo) const {
881 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
882 const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
883 const Function &F = MF.getFunction();
884
Tim Renoufed0b9af2019-03-13 18:55:50 +0000885 auto Kern = HSAMetadataDoc->getMapNode();
Scott Linderf5b36e52018-12-12 19:39:27 +0000886
Guillaume Chateletb65fa482019-10-15 12:56:24 +0000887 Align MaxKernArgAlign;
Tim Renoufed0b9af2019-03-13 18:55:50 +0000888 Kern[".kernarg_segment_size"] = Kern.getDocument()->getNode(
Scott Linderf5b36e52018-12-12 19:39:27 +0000889 STM.getKernArgSegmentSize(F, MaxKernArgAlign));
890 Kern[".group_segment_fixed_size"] =
Tim Renoufed0b9af2019-03-13 18:55:50 +0000891 Kern.getDocument()->getNode(ProgramInfo.LDSSize);
Scott Linderf5b36e52018-12-12 19:39:27 +0000892 Kern[".private_segment_fixed_size"] =
Tim Renoufed0b9af2019-03-13 18:55:50 +0000893 Kern.getDocument()->getNode(ProgramInfo.ScratchSize);
Scott Linderf5b36e52018-12-12 19:39:27 +0000894 Kern[".kernarg_segment_align"] =
Guillaume Chateletb65fa482019-10-15 12:56:24 +0000895 Kern.getDocument()->getNode(std::max(Align(4), MaxKernArgAlign).value());
Scott Linderf5b36e52018-12-12 19:39:27 +0000896 Kern[".wavefront_size"] =
Tim Renoufed0b9af2019-03-13 18:55:50 +0000897 Kern.getDocument()->getNode(STM.getWavefrontSize());
898 Kern[".sgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumSGPR);
899 Kern[".vgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumVGPR);
Scott Linderf5b36e52018-12-12 19:39:27 +0000900 Kern[".max_flat_workgroup_size"] =
Tim Renoufed0b9af2019-03-13 18:55:50 +0000901 Kern.getDocument()->getNode(MFI.getMaxFlatWorkGroupSize());
Scott Linderf5b36e52018-12-12 19:39:27 +0000902 Kern[".sgpr_spill_count"] =
Tim Renoufed0b9af2019-03-13 18:55:50 +0000903 Kern.getDocument()->getNode(MFI.getNumSpilledSGPRs());
Scott Linderf5b36e52018-12-12 19:39:27 +0000904 Kern[".vgpr_spill_count"] =
Tim Renoufed0b9af2019-03-13 18:55:50 +0000905 Kern.getDocument()->getNode(MFI.getNumSpilledVGPRs());
Scott Linderf5b36e52018-12-12 19:39:27 +0000906
Tim Renoufed0b9af2019-03-13 18:55:50 +0000907 return Kern;
Scott Linderf5b36e52018-12-12 19:39:27 +0000908}
909
910bool MetadataStreamerV3::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
Tim Renoufed0b9af2019-03-13 18:55:50 +0000911 return TargetStreamer.EmitHSAMetadata(*HSAMetadataDoc, true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000912}
913
914void MetadataStreamerV3::begin(const Module &Mod) {
915 emitVersion();
916 emitPrintf(Mod);
Tim Renoufed0b9af2019-03-13 18:55:50 +0000917 getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode();
Scott Linderf5b36e52018-12-12 19:39:27 +0000918}
919
920void MetadataStreamerV3::end() {
921 std::string HSAMetadataString;
922 raw_string_ostream StrOS(HSAMetadataString);
Tim Renoufed0b9af2019-03-13 18:55:50 +0000923 HSAMetadataDoc->toYAML(StrOS);
Scott Linderf5b36e52018-12-12 19:39:27 +0000924
925 if (DumpHSAMetadata)
926 dump(StrOS.str());
927 if (VerifyHSAMetadata)
928 verify(StrOS.str());
929}
930
931void MetadataStreamerV3::emitKernel(const MachineFunction &MF,
932 const SIProgramInfo &ProgramInfo) {
933 auto &Func = MF.getFunction();
Tim Renoufed0b9af2019-03-13 18:55:50 +0000934 auto Kern = getHSAKernelProps(MF, ProgramInfo);
Scott Linderf5b36e52018-12-12 19:39:27 +0000935
936 assert(Func.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
937 Func.getCallingConv() == CallingConv::SPIR_KERNEL);
938
Tim Renoufed0b9af2019-03-13 18:55:50 +0000939 auto Kernels =
940 getRootMetadata("amdhsa.kernels").getArray(/*Convert=*/true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000941
942 {
Tim Renoufed0b9af2019-03-13 18:55:50 +0000943 Kern[".name"] = Kern.getDocument()->getNode(Func.getName());
944 Kern[".symbol"] = Kern.getDocument()->getNode(
945 (Twine(Func.getName()) + Twine(".kd")).str(), /*Copy=*/true);
Scott Linderf5b36e52018-12-12 19:39:27 +0000946 emitKernelLanguage(Func, Kern);
947 emitKernelAttrs(Func, Kern);
948 emitKernelArgs(Func, Kern);
949 }
950
Tim Renoufed0b9af2019-03-13 18:55:50 +0000951 Kernels.push_back(Kern);
Scott Linderf5b36e52018-12-12 19:39:27 +0000952}
953
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000954} // end namespace HSAMD
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000955} // end namespace AMDGPU
956} // end namespace llvm