blob: c38b0e61558b3d2a2464c776b6dfb43dcb1f3aee [file] [log] [blame]
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +00001//===--- AMDGPUHSAMetadataStreamer.cpp --------------------------*- C++ -*-===//
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +00002//
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
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000011/// AMDGPU HSA Metadata Streamer.
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000012///
13//
14//===----------------------------------------------------------------------===//
15
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +000016#include "AMDGPUHSAMetadataStreamer.h"
Scott Linder2ad2c182018-07-10 17:31:32 +000017#include "AMDGPU.h"
18#include "AMDGPUSubtarget.h"
Scott Linderf5b36e52018-12-12 19:39:27 +000019#include "MCTargetDesc/AMDGPUTargetStreamer.h"
Scott Linder2ad2c182018-07-10 17:31:32 +000020#include "SIMachineFunctionInfo.h"
21#include "SIProgramInfo.h"
Konstantin Zhuravlyovf0badd52018-07-10 16:12:51 +000022#include "Utils/AMDGPUBaseInfo.h"
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/IR/Constants.h"
25#include "llvm/IR/Module.h"
Konstantin Zhuravlyov1e2b8782017-06-06 18:35:50 +000026#include "llvm/Support/raw_ostream.h"
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000027
28namespace llvm {
29
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +000030static cl::opt<bool> DumpHSAMetadata(
31 "amdgpu-dump-hsa-metadata",
32 cl::desc("Dump AMDGPU HSA Metadata"));
33static cl::opt<bool> VerifyHSAMetadata(
34 "amdgpu-verify-hsa-metadata",
35 cl::desc("Verify AMDGPU HSA Metadata"));
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000036
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000037namespace AMDGPU {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +000038namespace HSAMD {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000039
Scott Linderf5b36e52018-12-12 19:39:27 +000040//===----------------------------------------------------------------------===//
41// HSAMetadataStreamerV2
42//===----------------------------------------------------------------------===//
43void MetadataStreamerV2::dump(StringRef HSAMetadataString) const {
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +000044 errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000045}
46
Scott Linderf5b36e52018-12-12 19:39:27 +000047void MetadataStreamerV2::verify(StringRef HSAMetadataString) const {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +000048 errs() << "AMDGPU HSA Metadata Parser Test: ";
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000049
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +000050 HSAMD::Metadata FromHSAMetadataString;
51 if (fromString(HSAMetadataString, FromHSAMetadataString)) {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000052 errs() << "FAIL\n";
53 return;
54 }
55
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +000056 std::string ToHSAMetadataString;
57 if (toString(FromHSAMetadataString, ToHSAMetadataString)) {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000058 errs() << "FAIL\n";
59 return;
60 }
61
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +000062 errs() << (HSAMetadataString == ToHSAMetadataString ? "PASS" : "FAIL")
63 << '\n';
64 if (HSAMetadataString != ToHSAMetadataString) {
65 errs() << "Original input: " << HSAMetadataString << '\n'
66 << "Produced output: " << ToHSAMetadataString << '\n';
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000067 }
68}
69
Scott Linderf5b36e52018-12-12 19:39:27 +000070AccessQualifier
71MetadataStreamerV2::getAccessQualifier(StringRef AccQual) const {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000072 if (AccQual.empty())
73 return AccessQualifier::Unknown;
74
75 return StringSwitch<AccessQualifier>(AccQual)
76 .Case("read_only", AccessQualifier::ReadOnly)
77 .Case("write_only", AccessQualifier::WriteOnly)
78 .Case("read_write", AccessQualifier::ReadWrite)
79 .Default(AccessQualifier::Default);
80}
81
Scott Linderf5b36e52018-12-12 19:39:27 +000082AddressSpaceQualifier
83MetadataStreamerV2::getAddressSpaceQualifier(
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000084 unsigned AddressSpace) const {
Matt Arsenaultb9986742018-09-10 02:23:30 +000085 switch (AddressSpace) {
86 case AMDGPUAS::PRIVATE_ADDRESS:
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000087 return AddressSpaceQualifier::Private;
Matt Arsenaultb9986742018-09-10 02:23:30 +000088 case AMDGPUAS::GLOBAL_ADDRESS:
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000089 return AddressSpaceQualifier::Global;
Matt Arsenaultb9986742018-09-10 02:23:30 +000090 case AMDGPUAS::CONSTANT_ADDRESS:
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000091 return AddressSpaceQualifier::Constant;
Matt Arsenaultb9986742018-09-10 02:23:30 +000092 case AMDGPUAS::LOCAL_ADDRESS:
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000093 return AddressSpaceQualifier::Local;
Matt Arsenaultb9986742018-09-10 02:23:30 +000094 case AMDGPUAS::FLAT_ADDRESS:
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000095 return AddressSpaceQualifier::Generic;
Matt Arsenaultb9986742018-09-10 02:23:30 +000096 case AMDGPUAS::REGION_ADDRESS:
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000097 return AddressSpaceQualifier::Region;
Matt Arsenaultb9986742018-09-10 02:23:30 +000098 default:
99 return AddressSpaceQualifier::Unknown;
100 }
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000101}
102
Scott Linderf5b36e52018-12-12 19:39:27 +0000103ValueKind MetadataStreamerV2::getValueKind(Type *Ty, StringRef TypeQual,
104 StringRef BaseTypeName) const {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000105 if (TypeQual.find("pipe") != StringRef::npos)
106 return ValueKind::Pipe;
107
108 return StringSwitch<ValueKind>(BaseTypeName)
Konstantin Zhuravlyov54ba4312017-04-25 20:38:26 +0000109 .Case("image1d_t", ValueKind::Image)
110 .Case("image1d_array_t", ValueKind::Image)
111 .Case("image1d_buffer_t", ValueKind::Image)
112 .Case("image2d_t", ValueKind::Image)
113 .Case("image2d_array_t", ValueKind::Image)
114 .Case("image2d_array_depth_t", ValueKind::Image)
115 .Case("image2d_array_msaa_t", ValueKind::Image)
116 .Case("image2d_array_msaa_depth_t", ValueKind::Image)
117 .Case("image2d_depth_t", ValueKind::Image)
118 .Case("image2d_msaa_t", ValueKind::Image)
119 .Case("image2d_msaa_depth_t", ValueKind::Image)
120 .Case("image3d_t", ValueKind::Image)
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000121 .Case("sampler_t", ValueKind::Sampler)
122 .Case("queue_t", ValueKind::Queue)
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000123 .Default(isa<PointerType>(Ty) ?
124 (Ty->getPointerAddressSpace() ==
Matt Arsenault0da63502018-08-31 05:49:54 +0000125 AMDGPUAS::LOCAL_ADDRESS ?
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000126 ValueKind::DynamicSharedPointer :
127 ValueKind::GlobalBuffer) :
128 ValueKind::ByValue);
129}
130
Scott Linderf5b36e52018-12-12 19:39:27 +0000131ValueType MetadataStreamerV2::getValueType(Type *Ty, StringRef TypeName) const {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000132 switch (Ty->getTypeID()) {
133 case Type::IntegerTyID: {
134 auto Signed = !TypeName.startswith("u");
135 switch (Ty->getIntegerBitWidth()) {
136 case 8:
137 return Signed ? ValueType::I8 : ValueType::U8;
138 case 16:
139 return Signed ? ValueType::I16 : ValueType::U16;
140 case 32:
141 return Signed ? ValueType::I32 : ValueType::U32;
142 case 64:
143 return Signed ? ValueType::I64 : ValueType::U64;
144 default:
145 return ValueType::Struct;
146 }
147 }
148 case Type::HalfTyID:
149 return ValueType::F16;
150 case Type::FloatTyID:
151 return ValueType::F32;
152 case Type::DoubleTyID:
153 return ValueType::F64;
154 case Type::PointerTyID:
155 return getValueType(Ty->getPointerElementType(), TypeName);
156 case Type::VectorTyID:
157 return getValueType(Ty->getVectorElementType(), TypeName);
158 default:
159 return ValueType::Struct;
160 }
161}
162
Scott Linderf5b36e52018-12-12 19:39:27 +0000163std::string MetadataStreamerV2::getTypeName(Type *Ty, bool Signed) const {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000164 switch (Ty->getTypeID()) {
165 case Type::IntegerTyID: {
166 if (!Signed)
167 return (Twine('u') + getTypeName(Ty, true)).str();
168
169 auto BitWidth = Ty->getIntegerBitWidth();
170 switch (BitWidth) {
171 case 8:
172 return "char";
173 case 16:
174 return "short";
175 case 32:
176 return "int";
177 case 64:
178 return "long";
179 default:
180 return (Twine('i') + Twine(BitWidth)).str();
181 }
182 }
183 case Type::HalfTyID:
184 return "half";
185 case Type::FloatTyID:
186 return "float";
187 case Type::DoubleTyID:
188 return "double";
189 case Type::VectorTyID: {
190 auto VecTy = cast<VectorType>(Ty);
191 auto ElTy = VecTy->getElementType();
192 auto NumElements = VecTy->getVectorNumElements();
193 return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
194 }
195 default:
196 return "unknown";
197 }
198}
199
Scott Linderf5b36e52018-12-12 19:39:27 +0000200std::vector<uint32_t>
201MetadataStreamerV2::getWorkGroupDimensions(MDNode *Node) const {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000202 std::vector<uint32_t> Dims;
203 if (Node->getNumOperands() != 3)
204 return Dims;
205
206 for (auto &Op : Node->operands())
207 Dims.push_back(mdconst::extract<ConstantInt>(Op)->getZExtValue());
208 return Dims;
209}
210
Scott Linderf5b36e52018-12-12 19:39:27 +0000211Kernel::CodeProps::Metadata
212MetadataStreamerV2::getHSACodeProps(const MachineFunction &MF,
213 const SIProgramInfo &ProgramInfo) const {
Tom Stellard5bfbae52018-07-11 20:59:01 +0000214 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
Scott Linder2ad2c182018-07-10 17:31:32 +0000215 const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
216 HSAMD::Kernel::CodeProps::Metadata HSACodeProps;
217 const Function &F = MF.getFunction();
218
Matt Arsenault4bec7d42018-07-20 09:05:08 +0000219 assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
220 F.getCallingConv() == CallingConv::SPIR_KERNEL);
Scott Linder2ad2c182018-07-10 17:31:32 +0000221
Matt Arsenault4bec7d42018-07-20 09:05:08 +0000222 unsigned MaxKernArgAlign;
223 HSACodeProps.mKernargSegmentSize = STM.getKernArgSegmentSize(F,
224 MaxKernArgAlign);
Scott Linder2ad2c182018-07-10 17:31:32 +0000225 HSACodeProps.mGroupSegmentFixedSize = ProgramInfo.LDSSize;
226 HSACodeProps.mPrivateSegmentFixedSize = ProgramInfo.ScratchSize;
Matt Arsenault4bec7d42018-07-20 09:05:08 +0000227 HSACodeProps.mKernargSegmentAlign = std::max(MaxKernArgAlign, 4u);
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 {
Tom Stellard5bfbae52018-07-11 20:59:01 +0000243 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
Scott Linder2ad2c182018-07-10 17:31:32 +0000244 HSAMD::Kernel::DebugProps::Metadata HSADebugProps;
245
246 if (!STM.debuggerSupported())
247 return HSADebugProps;
248
249 HSADebugProps.mDebuggerABIVersion.push_back(1);
250 HSADebugProps.mDebuggerABIVersion.push_back(0);
251
252 if (STM.debuggerEmitPrologue()) {
253 HSADebugProps.mPrivateSegmentBufferSGPR =
254 ProgramInfo.DebuggerPrivateSegmentBufferSGPR;
255 HSADebugProps.mWavefrontPrivateSegmentOffsetSGPR =
256 ProgramInfo.DebuggerWavefrontPrivateSegmentOffsetSGPR;
257 }
258
259 return HSADebugProps;
260}
261
Scott Linderf5b36e52018-12-12 19:39:27 +0000262void MetadataStreamerV2::emitVersion() {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000263 auto &Version = HSAMetadata.mVersion;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000264
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000265 Version.push_back(VersionMajor);
266 Version.push_back(VersionMinor);
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000267}
268
Scott Linderf5b36e52018-12-12 19:39:27 +0000269void MetadataStreamerV2::emitPrintf(const Module &Mod) {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000270 auto &Printf = HSAMetadata.mPrintf;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000271
272 auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
273 if (!Node)
274 return;
275
276 for (auto Op : Node->operands())
277 if (Op->getNumOperands())
278 Printf.push_back(cast<MDString>(Op->getOperand(0))->getString());
279}
280
Scott Linderf5b36e52018-12-12 19:39:27 +0000281void MetadataStreamerV2::emitKernelLanguage(const Function &Func) {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000282 auto &Kernel = HSAMetadata.mKernels.back();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000283
284 // TODO: What about other languages?
285 auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
286 if (!Node || !Node->getNumOperands())
287 return;
288 auto Op0 = Node->getOperand(0);
289 if (Op0->getNumOperands() <= 1)
290 return;
291
292 Kernel.mLanguage = "OpenCL C";
293 Kernel.mLanguageVersion.push_back(
294 mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue());
295 Kernel.mLanguageVersion.push_back(
296 mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue());
297}
298
Scott Linderf5b36e52018-12-12 19:39:27 +0000299void MetadataStreamerV2::emitKernelAttrs(const Function &Func) {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000300 auto &Attrs = HSAMetadata.mKernels.back().mAttrs;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000301
302 if (auto Node = Func.getMetadata("reqd_work_group_size"))
303 Attrs.mReqdWorkGroupSize = getWorkGroupDimensions(Node);
304 if (auto Node = Func.getMetadata("work_group_size_hint"))
305 Attrs.mWorkGroupSizeHint = getWorkGroupDimensions(Node);
306 if (auto Node = Func.getMetadata("vec_type_hint")) {
307 Attrs.mVecTypeHint = getTypeName(
308 cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
309 mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue());
310 }
Yaxun Liude4b88d2017-10-10 19:39:48 +0000311 if (Func.hasFnAttribute("runtime-handle")) {
312 Attrs.mRuntimeHandle =
313 Func.getFnAttribute("runtime-handle").getValueAsString().str();
314 }
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000315}
316
Scott Linderf5b36e52018-12-12 19:39:27 +0000317void MetadataStreamerV2::emitKernelArgs(const Function &Func) {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000318 for (auto &Arg : Func.args())
319 emitKernelArg(Arg);
320
Konstantin Zhuravlyovf0badd52018-07-10 16:12:51 +0000321 emitHiddenKernelArgs(Func);
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000322}
323
Scott Linderf5b36e52018-12-12 19:39:27 +0000324void MetadataStreamerV2::emitKernelArg(const Argument &Arg) {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000325 auto Func = Arg.getParent();
326 auto ArgNo = Arg.getArgNo();
327 const MDNode *Node;
328
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000329 StringRef Name;
330 Node = Func->getMetadata("kernel_arg_name");
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000331 if (Node && ArgNo < Node->getNumOperands())
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000332 Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
Konstantin Zhuravlyove30f88f2017-12-08 19:22:12 +0000333 else if (Arg.hasName())
334 Name = Arg.getName();
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000335
336 StringRef TypeName;
337 Node = Func->getMetadata("kernel_arg_type");
338 if (Node && ArgNo < Node->getNumOperands())
339 TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000340
341 StringRef BaseTypeName;
342 Node = Func->getMetadata("kernel_arg_base_type");
343 if (Node && ArgNo < Node->getNumOperands())
344 BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
345
346 StringRef AccQual;
Stanislav Mekhanoshineff0bc72017-04-14 19:11:40 +0000347 if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
348 Arg.hasNoAliasAttr()) {
349 AccQual = "read_only";
350 } else {
351 Node = Func->getMetadata("kernel_arg_access_qual");
352 if (Node && ArgNo < Node->getNumOperands())
353 AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
354 }
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000355
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000356 StringRef TypeQual;
357 Node = Func->getMetadata("kernel_arg_type_qual");
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000358 if (Node && ArgNo < Node->getNumOperands())
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000359 TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000360
Matt Arsenault73eeb422018-06-25 14:29:04 +0000361 Type *Ty = Arg.getType();
362 const DataLayout &DL = Func->getParent()->getDataLayout();
363
364 unsigned PointeeAlign = 0;
365 if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
Matt Arsenault0da63502018-08-31 05:49:54 +0000366 if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
Matt Arsenault73eeb422018-06-25 14:29:04 +0000367 PointeeAlign = Arg.getParamAlignment();
368 if (PointeeAlign == 0)
369 PointeeAlign = DL.getABITypeAlignment(PtrTy->getElementType());
370 }
371 }
372
373 emitKernelArg(DL, Ty, getValueKind(Arg.getType(), TypeQual, BaseTypeName),
374 PointeeAlign, Name, TypeName, BaseTypeName, AccQual, TypeQual);
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000375}
376
Scott Linderf5b36e52018-12-12 19:39:27 +0000377void MetadataStreamerV2::emitKernelArg(const DataLayout &DL, Type *Ty,
378 ValueKind ValueKind,
379 unsigned PointeeAlign, StringRef Name,
380 StringRef TypeName,
381 StringRef BaseTypeName,
382 StringRef AccQual, StringRef TypeQual) {
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000383 HSAMetadata.mKernels.back().mArgs.push_back(Kernel::Arg::Metadata());
384 auto &Arg = HSAMetadata.mKernels.back().mArgs.back();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000385
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000386 Arg.mName = Name;
387 Arg.mTypeName = TypeName;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000388 Arg.mSize = DL.getTypeAllocSize(Ty);
389 Arg.mAlign = DL.getABITypeAlignment(Ty);
390 Arg.mValueKind = ValueKind;
391 Arg.mValueType = getValueType(Ty, BaseTypeName);
Matt Arsenault73eeb422018-06-25 14:29:04 +0000392 Arg.mPointeeAlign = PointeeAlign;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000393
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000394 if (auto PtrTy = dyn_cast<PointerType>(Ty))
Scott Linderf5b36e52018-12-12 19:39:27 +0000395 Arg.mAddrSpaceQual = getAddressSpaceQualifier(PtrTy->getAddressSpace());
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000396
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000397 Arg.mAccQual = getAccessQualifier(AccQual);
398
399 // TODO: Emit Arg.mActualAccQual.
400
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000401 SmallVector<StringRef, 1> SplitTypeQuals;
402 TypeQual.split(SplitTypeQuals, " ", -1, false);
403 for (StringRef Key : SplitTypeQuals) {
404 auto P = StringSwitch<bool*>(Key)
405 .Case("const", &Arg.mIsConst)
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000406 .Case("restrict", &Arg.mIsRestrict)
407 .Case("volatile", &Arg.mIsVolatile)
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000408 .Case("pipe", &Arg.mIsPipe)
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000409 .Default(nullptr);
410 if (P)
411 *P = true;
412 }
Konstantin Zhuravlyova780ffa2017-03-22 23:10:46 +0000413}
414
Scott Linderf5b36e52018-12-12 19:39:27 +0000415void MetadataStreamerV2::emitHiddenKernelArgs(const Function &Func) {
Konstantin Zhuravlyovf0badd52018-07-10 16:12:51 +0000416 int HiddenArgNumBytes =
417 getIntegerAttribute(Func, "amdgpu-implicitarg-num-bytes", 0);
418
419 if (!HiddenArgNumBytes)
420 return;
421
422 auto &DL = Func.getParent()->getDataLayout();
423 auto Int64Ty = Type::getInt64Ty(Func.getContext());
424
425 if (HiddenArgNumBytes >= 8)
426 emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetX);
427 if (HiddenArgNumBytes >= 16)
428 emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetY);
429 if (HiddenArgNumBytes >= 24)
430 emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetZ);
431
432 auto Int8PtrTy = Type::getInt8PtrTy(Func.getContext(),
Matt Arsenault0da63502018-08-31 05:49:54 +0000433 AMDGPUAS::GLOBAL_ADDRESS);
Konstantin Zhuravlyovf0badd52018-07-10 16:12:51 +0000434
435 // Emit "printf buffer" argument if printf is used, otherwise emit dummy
436 // "none" argument.
437 if (HiddenArgNumBytes >= 32) {
438 if (Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
439 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenPrintfBuffer);
440 else
441 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
442 }
443
444 // Emit "default queue" and "completion action" arguments if enqueue kernel is
445 // used, otherwise emit dummy "none" arguments.
446 if (HiddenArgNumBytes >= 48) {
447 if (Func.hasFnAttribute("calls-enqueue-kernel")) {
448 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenDefaultQueue);
449 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenCompletionAction);
450 } else {
451 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
452 emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
453 }
454 }
455}
456
Scott Linderf5b36e52018-12-12 19:39:27 +0000457bool MetadataStreamerV2::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
458 return TargetStreamer.EmitHSAMetadata(getHSAMetadata());
459}
460
461void MetadataStreamerV2::begin(const Module &Mod) {
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000462 emitVersion();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000463 emitPrintf(Mod);
464}
465
Scott Linderf5b36e52018-12-12 19:39:27 +0000466void MetadataStreamerV2::end() {
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +0000467 std::string HSAMetadataString;
Konstantin Zhuravlyov63e87f52017-10-12 17:34:05 +0000468 if (toString(HSAMetadata, HSAMetadataString))
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +0000469 return;
470
471 if (DumpHSAMetadata)
472 dump(HSAMetadataString);
473 if (VerifyHSAMetadata)
474 verify(HSAMetadataString);
475}
476
Scott Linderf5b36e52018-12-12 19:39:27 +0000477void MetadataStreamerV2::emitKernel(const MachineFunction &MF,
478 const SIProgramInfo &ProgramInfo) {
Scott Linder2ad2c182018-07-10 17:31:32 +0000479 auto &Func = MF.getFunction();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000480 if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL)
481 return;
482
Matt Arsenault4bec7d42018-07-20 09:05:08 +0000483 auto CodeProps = getHSACodeProps(MF, ProgramInfo);
484 auto DebugProps = getHSADebugProps(MF, ProgramInfo);
485
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000486 HSAMetadata.mKernels.push_back(Kernel::Metadata());
487 auto &Kernel = HSAMetadata.mKernels.back();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000488
489 Kernel.mName = Func.getName();
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000490 Kernel.mSymbolName = (Twine(Func.getName()) + Twine("@kd")).str();
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000491 emitKernelLanguage(Func);
492 emitKernelAttrs(Func);
493 emitKernelArgs(Func);
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000494 HSAMetadata.mKernels.back().mCodeProps = CodeProps;
495 HSAMetadata.mKernels.back().mDebugProps = DebugProps;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000496}
497
Scott Linderf5b36e52018-12-12 19:39:27 +0000498//===----------------------------------------------------------------------===//
499// HSAMetadataStreamerV3
500//===----------------------------------------------------------------------===//
501
502void MetadataStreamerV3::dump(StringRef HSAMetadataString) const {
503 errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
504}
505
506void MetadataStreamerV3::verify(StringRef HSAMetadataString) const {
507 errs() << "AMDGPU HSA Metadata Parser Test: ";
508
509 std::shared_ptr<msgpack::Node> FromHSAMetadataString =
510 std::make_shared<msgpack::MapNode>();
511
512 yaml::Input YIn(HSAMetadataString);
513 YIn >> FromHSAMetadataString;
514 if (YIn.error()) {
515 errs() << "FAIL\n";
516 return;
517 }
518
519 std::string ToHSAMetadataString;
520 raw_string_ostream StrOS(ToHSAMetadataString);
521 yaml::Output YOut(StrOS);
522 YOut << FromHSAMetadataString;
523
524 errs() << (HSAMetadataString == StrOS.str() ? "PASS" : "FAIL") << '\n';
525 if (HSAMetadataString != ToHSAMetadataString) {
526 errs() << "Original input: " << HSAMetadataString << '\n'
527 << "Produced output: " << StrOS.str() << '\n';
528 }
529}
530
531Optional<StringRef>
532MetadataStreamerV3::getAccessQualifier(StringRef AccQual) const {
533 return StringSwitch<Optional<StringRef>>(AccQual)
534 .Case("read_only", StringRef("read_only"))
535 .Case("write_only", StringRef("write_only"))
536 .Case("read_write", StringRef("read_write"))
537 .Default(None);
538}
539
540Optional<StringRef>
541MetadataStreamerV3::getAddressSpaceQualifier(unsigned AddressSpace) const {
542 switch (AddressSpace) {
543 case AMDGPUAS::PRIVATE_ADDRESS:
544 return StringRef("private");
545 case AMDGPUAS::GLOBAL_ADDRESS:
546 return StringRef("global");
547 case AMDGPUAS::CONSTANT_ADDRESS:
548 return StringRef("constant");
549 case AMDGPUAS::LOCAL_ADDRESS:
550 return StringRef("local");
551 case AMDGPUAS::FLAT_ADDRESS:
552 return StringRef("generic");
553 case AMDGPUAS::REGION_ADDRESS:
554 return StringRef("region");
555 default:
556 return None;
557 }
558}
559
560StringRef MetadataStreamerV3::getValueKind(Type *Ty, StringRef TypeQual,
561 StringRef BaseTypeName) const {
562 if (TypeQual.find("pipe") != StringRef::npos)
563 return "pipe";
564
565 return StringSwitch<StringRef>(BaseTypeName)
566 .Case("image1d_t", "image")
567 .Case("image1d_array_t", "image")
568 .Case("image1d_buffer_t", "image")
569 .Case("image2d_t", "image")
570 .Case("image2d_array_t", "image")
571 .Case("image2d_array_depth_t", "image")
572 .Case("image2d_array_msaa_t", "image")
573 .Case("image2d_array_msaa_depth_t", "image")
574 .Case("image2d_depth_t", "image")
575 .Case("image2d_msaa_t", "image")
576 .Case("image2d_msaa_depth_t", "image")
577 .Case("image3d_t", "image")
578 .Case("sampler_t", "sampler")
579 .Case("queue_t", "queue")
580 .Default(isa<PointerType>(Ty)
581 ? (Ty->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS
582 ? "dynamic_shared_pointer"
583 : "global_buffer")
584 : "by_value");
585}
586
587StringRef MetadataStreamerV3::getValueType(Type *Ty, StringRef TypeName) const {
588 switch (Ty->getTypeID()) {
589 case Type::IntegerTyID: {
590 auto Signed = !TypeName.startswith("u");
591 switch (Ty->getIntegerBitWidth()) {
592 case 8:
593 return Signed ? "i8" : "u8";
594 case 16:
595 return Signed ? "i16" : "u16";
596 case 32:
597 return Signed ? "i32" : "u32";
598 case 64:
599 return Signed ? "i64" : "u64";
600 default:
601 return "struct";
602 }
603 }
604 case Type::HalfTyID:
605 return "f16";
606 case Type::FloatTyID:
607 return "f32";
608 case Type::DoubleTyID:
609 return "f64";
610 case Type::PointerTyID:
611 return getValueType(Ty->getPointerElementType(), TypeName);
612 case Type::VectorTyID:
613 return getValueType(Ty->getVectorElementType(), TypeName);
614 default:
615 return "struct";
616 }
617}
618
619std::string MetadataStreamerV3::getTypeName(Type *Ty, bool Signed) const {
620 switch (Ty->getTypeID()) {
621 case Type::IntegerTyID: {
622 if (!Signed)
623 return (Twine('u') + getTypeName(Ty, true)).str();
624
625 auto BitWidth = Ty->getIntegerBitWidth();
626 switch (BitWidth) {
627 case 8:
628 return "char";
629 case 16:
630 return "short";
631 case 32:
632 return "int";
633 case 64:
634 return "long";
635 default:
636 return (Twine('i') + Twine(BitWidth)).str();
637 }
638 }
639 case Type::HalfTyID:
640 return "half";
641 case Type::FloatTyID:
642 return "float";
643 case Type::DoubleTyID:
644 return "double";
645 case Type::VectorTyID: {
646 auto VecTy = cast<VectorType>(Ty);
647 auto ElTy = VecTy->getElementType();
648 auto NumElements = VecTy->getVectorNumElements();
649 return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
650 }
651 default:
652 return "unknown";
653 }
654}
655
656std::shared_ptr<msgpack::ArrayNode>
657MetadataStreamerV3::getWorkGroupDimensions(MDNode *Node) const {
658 auto Dims = std::make_shared<msgpack::ArrayNode>();
659 if (Node->getNumOperands() != 3)
660 return Dims;
661
662 for (auto &Op : Node->operands())
663 Dims->push_back(std::make_shared<msgpack::ScalarNode>(
664 mdconst::extract<ConstantInt>(Op)->getZExtValue()));
665 return Dims;
666}
667
668void MetadataStreamerV3::emitVersion() {
669 auto Version = std::make_shared<msgpack::ArrayNode>();
670 Version->push_back(std::make_shared<msgpack::ScalarNode>(V3::VersionMajor));
671 Version->push_back(std::make_shared<msgpack::ScalarNode>(V3::VersionMinor));
672 getRootMetadata("amdhsa.version") = std::move(Version);
673}
674
675void MetadataStreamerV3::emitPrintf(const Module &Mod) {
676 auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
677 if (!Node)
678 return;
679
680 auto Printf = std::make_shared<msgpack::ArrayNode>();
681 for (auto Op : Node->operands())
682 if (Op->getNumOperands())
683 Printf->push_back(std::make_shared<msgpack::ScalarNode>(
684 cast<MDString>(Op->getOperand(0))->getString()));
685 getRootMetadata("amdhsa.printf") = std::move(Printf);
686}
687
688void MetadataStreamerV3::emitKernelLanguage(const Function &Func,
689 msgpack::MapNode &Kern) {
690 // TODO: What about other languages?
691 auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
692 if (!Node || !Node->getNumOperands())
693 return;
694 auto Op0 = Node->getOperand(0);
695 if (Op0->getNumOperands() <= 1)
696 return;
697
698 Kern[".language"] = std::make_shared<msgpack::ScalarNode>("OpenCL C");
699 auto LanguageVersion = std::make_shared<msgpack::ArrayNode>();
700 LanguageVersion->push_back(std::make_shared<msgpack::ScalarNode>(
701 mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue()));
702 LanguageVersion->push_back(std::make_shared<msgpack::ScalarNode>(
703 mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue()));
704 Kern[".language_version"] = std::move(LanguageVersion);
705}
706
707void MetadataStreamerV3::emitKernelAttrs(const Function &Func,
708 msgpack::MapNode &Kern) {
709
710 if (auto Node = Func.getMetadata("reqd_work_group_size"))
711 Kern[".reqd_workgroup_size"] = getWorkGroupDimensions(Node);
712 if (auto Node = Func.getMetadata("work_group_size_hint"))
713 Kern[".workgroup_size_hint"] = getWorkGroupDimensions(Node);
714 if (auto Node = Func.getMetadata("vec_type_hint")) {
715 Kern[".vec_type_hint"] = std::make_shared<msgpack::ScalarNode>(getTypeName(
716 cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
717 mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()));
718 }
719 if (Func.hasFnAttribute("runtime-handle")) {
720 Kern[".device_enqueue_symbol"] = std::make_shared<msgpack::ScalarNode>(
721 Func.getFnAttribute("runtime-handle").getValueAsString().str());
722 }
723}
724
725void MetadataStreamerV3::emitKernelArgs(const Function &Func,
726 msgpack::MapNode &Kern) {
727 unsigned Offset = 0;
728 auto Args = std::make_shared<msgpack::ArrayNode>();
729 for (auto &Arg : Func.args())
730 emitKernelArg(Arg, Offset, *Args);
731
732 emitHiddenKernelArgs(Func, Offset, *Args);
733
734 // TODO: What about other languages?
735 if (Func.getParent()->getNamedMetadata("opencl.ocl.version")) {
736 auto &DL = Func.getParent()->getDataLayout();
737 auto Int64Ty = Type::getInt64Ty(Func.getContext());
738
739 emitKernelArg(DL, Int64Ty, "hidden_global_offset_x", Offset, *Args);
740 emitKernelArg(DL, Int64Ty, "hidden_global_offset_y", Offset, *Args);
741 emitKernelArg(DL, Int64Ty, "hidden_global_offset_z", Offset, *Args);
742
743 auto Int8PtrTy =
744 Type::getInt8PtrTy(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
745
746 // Emit "printf buffer" argument if printf is used, otherwise emit dummy
747 // "none" argument.
748 if (Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
749 emitKernelArg(DL, Int8PtrTy, "hidden_printf_buffer", Offset, *Args);
750 else
751 emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, *Args);
752
753 // Emit "default queue" and "completion action" arguments if enqueue kernel
754 // is used, otherwise emit dummy "none" arguments.
755 if (Func.hasFnAttribute("calls-enqueue-kernel")) {
756 emitKernelArg(DL, Int8PtrTy, "hidden_default_queue", Offset, *Args);
757 emitKernelArg(DL, Int8PtrTy, "hidden_completion_action", Offset, *Args);
758 } else {
759 emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, *Args);
760 emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, *Args);
761 }
762 }
763
764 Kern[".args"] = std::move(Args);
765}
766
767void MetadataStreamerV3::emitKernelArg(const Argument &Arg, unsigned &Offset,
768 msgpack::ArrayNode &Args) {
769 auto Func = Arg.getParent();
770 auto ArgNo = Arg.getArgNo();
771 const MDNode *Node;
772
773 StringRef Name;
774 Node = Func->getMetadata("kernel_arg_name");
775 if (Node && ArgNo < Node->getNumOperands())
776 Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
777 else if (Arg.hasName())
778 Name = Arg.getName();
779
780 StringRef TypeName;
781 Node = Func->getMetadata("kernel_arg_type");
782 if (Node && ArgNo < Node->getNumOperands())
783 TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
784
785 StringRef BaseTypeName;
786 Node = Func->getMetadata("kernel_arg_base_type");
787 if (Node && ArgNo < Node->getNumOperands())
788 BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
789
790 StringRef AccQual;
791 if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
792 Arg.hasNoAliasAttr()) {
793 AccQual = "read_only";
794 } else {
795 Node = Func->getMetadata("kernel_arg_access_qual");
796 if (Node && ArgNo < Node->getNumOperands())
797 AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
798 }
799
800 StringRef TypeQual;
801 Node = Func->getMetadata("kernel_arg_type_qual");
802 if (Node && ArgNo < Node->getNumOperands())
803 TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
804
805 Type *Ty = Arg.getType();
806 const DataLayout &DL = Func->getParent()->getDataLayout();
807
808 unsigned PointeeAlign = 0;
809 if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
810 if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
811 PointeeAlign = Arg.getParamAlignment();
812 if (PointeeAlign == 0)
813 PointeeAlign = DL.getABITypeAlignment(PtrTy->getElementType());
814 }
815 }
816
817 emitKernelArg(Func->getParent()->getDataLayout(), Arg.getType(),
818 getValueKind(Arg.getType(), TypeQual, BaseTypeName), Offset,
819 Args, PointeeAlign, Name, TypeName, BaseTypeName, AccQual,
820 TypeQual);
821}
822
823void MetadataStreamerV3::emitKernelArg(const DataLayout &DL, Type *Ty,
824 StringRef ValueKind, unsigned &Offset,
825 msgpack::ArrayNode &Args,
826 unsigned PointeeAlign, StringRef Name,
827 StringRef TypeName,
828 StringRef BaseTypeName,
829 StringRef AccQual, StringRef TypeQual) {
830 auto ArgPtr = std::make_shared<msgpack::MapNode>();
831 auto &Arg = *ArgPtr;
832
833 if (!Name.empty())
834 Arg[".name"] = std::make_shared<msgpack::ScalarNode>(Name);
835 if (!TypeName.empty())
836 Arg[".type_name"] = std::make_shared<msgpack::ScalarNode>(TypeName);
837 auto Size = DL.getTypeAllocSize(Ty);
838 auto Align = DL.getABITypeAlignment(Ty);
839 Arg[".size"] = std::make_shared<msgpack::ScalarNode>(Size);
840 Offset = alignTo(Offset, Align);
841 Arg[".offset"] = std::make_shared<msgpack::ScalarNode>(Offset);
842 Offset += Size;
843 Arg[".value_kind"] = std::make_shared<msgpack::ScalarNode>(ValueKind);
844 Arg[".value_type"] =
845 std::make_shared<msgpack::ScalarNode>(getValueType(Ty, BaseTypeName));
846 if (PointeeAlign)
847 Arg[".pointee_align"] = std::make_shared<msgpack::ScalarNode>(PointeeAlign);
848
849 if (auto PtrTy = dyn_cast<PointerType>(Ty))
850 if (auto Qualifier = getAddressSpaceQualifier(PtrTy->getAddressSpace()))
851 Arg[".address_space"] = std::make_shared<msgpack::ScalarNode>(*Qualifier);
852
853 if (auto AQ = getAccessQualifier(AccQual))
854 Arg[".access"] = std::make_shared<msgpack::ScalarNode>(*AQ);
855
856 // TODO: Emit Arg[".actual_access"].
857
858 SmallVector<StringRef, 1> SplitTypeQuals;
859 TypeQual.split(SplitTypeQuals, " ", -1, false);
860 for (StringRef Key : SplitTypeQuals) {
861 if (Key == "const")
862 Arg[".is_const"] = std::make_shared<msgpack::ScalarNode>(true);
863 else if (Key == "restrict")
864 Arg[".is_restrict"] = std::make_shared<msgpack::ScalarNode>(true);
865 else if (Key == "volatile")
866 Arg[".is_volatile"] = std::make_shared<msgpack::ScalarNode>(true);
867 else if (Key == "pipe")
868 Arg[".is_pipe"] = std::make_shared<msgpack::ScalarNode>(true);
869 }
870
871 Args.push_back(std::move(ArgPtr));
872}
873
874void MetadataStreamerV3::emitHiddenKernelArgs(const Function &Func,
875 unsigned &Offset,
876 msgpack::ArrayNode &Args) {
877 int HiddenArgNumBytes =
878 getIntegerAttribute(Func, "amdgpu-implicitarg-num-bytes", 0);
879
880 if (!HiddenArgNumBytes)
881 return;
882
883 auto &DL = Func.getParent()->getDataLayout();
884 auto Int64Ty = Type::getInt64Ty(Func.getContext());
885
886 if (HiddenArgNumBytes >= 8)
887 emitKernelArg(DL, Int64Ty, "hidden_global_offset_x", Offset, Args);
888 if (HiddenArgNumBytes >= 16)
889 emitKernelArg(DL, Int64Ty, "hidden_global_offset_y", Offset, Args);
890 if (HiddenArgNumBytes >= 24)
891 emitKernelArg(DL, Int64Ty, "hidden_global_offset_z", Offset, Args);
892
893 auto Int8PtrTy =
894 Type::getInt8PtrTy(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
895
896 // Emit "printf buffer" argument if printf is used, otherwise emit dummy
897 // "none" argument.
898 if (HiddenArgNumBytes >= 32) {
899 if (Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
900 emitKernelArg(DL, Int8PtrTy, "hidden_printf_buffer", Offset, Args);
901 else
902 emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, Args);
903 }
904
905 // Emit "default queue" and "completion action" arguments if enqueue kernel is
906 // used, otherwise emit dummy "none" arguments.
907 if (HiddenArgNumBytes >= 48) {
908 if (Func.hasFnAttribute("calls-enqueue-kernel")) {
909 emitKernelArg(DL, Int8PtrTy, "hidden_default_queue", Offset, Args);
910 emitKernelArg(DL, Int8PtrTy, "hidden_completion_action", Offset, Args);
911 } else {
912 emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, Args);
913 emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, Args);
914 }
915 }
916}
917
918std::shared_ptr<msgpack::MapNode>
919MetadataStreamerV3::getHSAKernelProps(const MachineFunction &MF,
920 const SIProgramInfo &ProgramInfo) const {
921 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
922 const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
923 const Function &F = MF.getFunction();
924
925 auto HSAKernelProps = std::make_shared<msgpack::MapNode>();
926 auto &Kern = *HSAKernelProps;
927
928 unsigned MaxKernArgAlign;
929 Kern[".kernarg_segment_size"] = std::make_shared<msgpack::ScalarNode>(
930 STM.getKernArgSegmentSize(F, MaxKernArgAlign));
931 Kern[".group_segment_fixed_size"] =
932 std::make_shared<msgpack::ScalarNode>(ProgramInfo.LDSSize);
933 Kern[".private_segment_fixed_size"] =
934 std::make_shared<msgpack::ScalarNode>(ProgramInfo.ScratchSize);
935 Kern[".kernarg_segment_align"] =
936 std::make_shared<msgpack::ScalarNode>(std::max(uint32_t(4), MaxKernArgAlign));
937 Kern[".wavefront_size"] =
938 std::make_shared<msgpack::ScalarNode>(STM.getWavefrontSize());
939 Kern[".sgpr_count"] = std::make_shared<msgpack::ScalarNode>(ProgramInfo.NumSGPR);
940 Kern[".vgpr_count"] = std::make_shared<msgpack::ScalarNode>(ProgramInfo.NumVGPR);
941 Kern[".max_flat_workgroup_size"] =
942 std::make_shared<msgpack::ScalarNode>(MFI.getMaxFlatWorkGroupSize());
943 Kern[".sgpr_spill_count"] =
944 std::make_shared<msgpack::ScalarNode>(MFI.getNumSpilledSGPRs());
945 Kern[".vgpr_spill_count"] =
946 std::make_shared<msgpack::ScalarNode>(MFI.getNumSpilledVGPRs());
947
948 return HSAKernelProps;
949}
950
951bool MetadataStreamerV3::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
952 return TargetStreamer.EmitHSAMetadata(getHSAMetadataRoot(), true);
953}
954
955void MetadataStreamerV3::begin(const Module &Mod) {
956 emitVersion();
957 emitPrintf(Mod);
958 getRootMetadata("amdhsa.kernels").reset(new msgpack::ArrayNode());
959}
960
961void MetadataStreamerV3::end() {
962 std::string HSAMetadataString;
963 raw_string_ostream StrOS(HSAMetadataString);
964 yaml::Output YOut(StrOS);
965 YOut << HSAMetadataRoot;
966
967 if (DumpHSAMetadata)
968 dump(StrOS.str());
969 if (VerifyHSAMetadata)
970 verify(StrOS.str());
971}
972
973void MetadataStreamerV3::emitKernel(const MachineFunction &MF,
974 const SIProgramInfo &ProgramInfo) {
975 auto &Func = MF.getFunction();
976 auto KernelProps = getHSAKernelProps(MF, ProgramInfo);
977
978 assert(Func.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
979 Func.getCallingConv() == CallingConv::SPIR_KERNEL);
980
981 auto &KernelsNode = getRootMetadata("amdhsa.kernels");
982 auto Kernels = cast<msgpack::ArrayNode>(KernelsNode.get());
983
984 {
985 auto &Kern = *KernelProps;
986 Kern[".name"] = std::make_shared<msgpack::ScalarNode>(Func.getName());
987 Kern[".symbol"] = std::make_shared<msgpack::ScalarNode>(
988 (Twine(Func.getName()) + Twine(".kd")).str());
989 emitKernelLanguage(Func, Kern);
990 emitKernelAttrs(Func, Kern);
991 emitKernelArgs(Func, Kern);
992 }
993
994 Kernels->push_back(std::move(KernelProps));
995}
996
Konstantin Zhuravlyova63b0f92017-10-11 22:18:53 +0000997} // end namespace HSAMD
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000998} // end namespace AMDGPU
999} // end namespace llvm