10b57cec5SDimitry Andric //===--- AMDGPUHSAMetadataStreamer.cpp --------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// AMDGPU HSA Metadata Streamer.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "AMDGPUHSAMetadataStreamer.h"
160b57cec5SDimitry Andric #include "AMDGPU.h"
17e8d8bef9SDimitry Andric #include "GCNSubtarget.h"
180b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUTargetStreamer.h"
190b57cec5SDimitry Andric #include "SIMachineFunctionInfo.h"
200b57cec5SDimitry Andric #include "SIProgramInfo.h"
210b57cec5SDimitry Andric #include "llvm/IR/Module.h"
22e8d8bef9SDimitry Andric using namespace llvm;
23e8d8bef9SDimitry Andric
getArgumentTypeAlign(const Argument & Arg,const DataLayout & DL)24e8d8bef9SDimitry Andric static std::pair<Type *, Align> getArgumentTypeAlign(const Argument &Arg,
25e8d8bef9SDimitry Andric const DataLayout &DL) {
26e8d8bef9SDimitry Andric Type *Ty = Arg.getType();
27e8d8bef9SDimitry Andric MaybeAlign ArgAlign;
28e8d8bef9SDimitry Andric if (Arg.hasByRefAttr()) {
29e8d8bef9SDimitry Andric Ty = Arg.getParamByRefType();
30e8d8bef9SDimitry Andric ArgAlign = Arg.getParamAlign();
31e8d8bef9SDimitry Andric }
32e8d8bef9SDimitry Andric
33e8d8bef9SDimitry Andric if (!ArgAlign)
34e8d8bef9SDimitry Andric ArgAlign = DL.getABITypeAlign(Ty);
35e8d8bef9SDimitry Andric
36bdd1243dSDimitry Andric return std::pair(Ty, *ArgAlign);
37e8d8bef9SDimitry Andric }
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric namespace llvm {
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric static cl::opt<bool> DumpHSAMetadata(
420b57cec5SDimitry Andric "amdgpu-dump-hsa-metadata",
430b57cec5SDimitry Andric cl::desc("Dump AMDGPU HSA Metadata"));
440b57cec5SDimitry Andric static cl::opt<bool> VerifyHSAMetadata(
450b57cec5SDimitry Andric "amdgpu-verify-hsa-metadata",
460b57cec5SDimitry Andric cl::desc("Verify AMDGPU HSA Metadata"));
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric namespace AMDGPU {
490b57cec5SDimitry Andric namespace HSAMD {
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
52c9157d92SDimitry Andric // HSAMetadataStreamerV4
530b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
54c9157d92SDimitry Andric
dump(StringRef HSAMetadataString) const55c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::dump(StringRef HSAMetadataString) const {
560b57cec5SDimitry Andric errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric
verify(StringRef HSAMetadataString) const59c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::verify(StringRef HSAMetadataString) const {
600b57cec5SDimitry Andric errs() << "AMDGPU HSA Metadata Parser Test: ";
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric msgpack::Document FromHSAMetadataString;
630b57cec5SDimitry Andric
640b57cec5SDimitry Andric if (!FromHSAMetadataString.fromYAML(HSAMetadataString)) {
650b57cec5SDimitry Andric errs() << "FAIL\n";
660b57cec5SDimitry Andric return;
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric std::string ToHSAMetadataString;
700b57cec5SDimitry Andric raw_string_ostream StrOS(ToHSAMetadataString);
710b57cec5SDimitry Andric FromHSAMetadataString.toYAML(StrOS);
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric errs() << (HSAMetadataString == StrOS.str() ? "PASS" : "FAIL") << '\n';
740b57cec5SDimitry Andric if (HSAMetadataString != ToHSAMetadataString) {
750b57cec5SDimitry Andric errs() << "Original input: " << HSAMetadataString << '\n'
760b57cec5SDimitry Andric << "Produced output: " << StrOS.str() << '\n';
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric
80bdd1243dSDimitry Andric std::optional<StringRef>
getAccessQualifier(StringRef AccQual) const81c9157d92SDimitry Andric MetadataStreamerMsgPackV4::getAccessQualifier(StringRef AccQual) const {
82bdd1243dSDimitry Andric return StringSwitch<std::optional<StringRef>>(AccQual)
830b57cec5SDimitry Andric .Case("read_only", StringRef("read_only"))
840b57cec5SDimitry Andric .Case("write_only", StringRef("write_only"))
850b57cec5SDimitry Andric .Case("read_write", StringRef("read_write"))
86bdd1243dSDimitry Andric .Default(std::nullopt);
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric
getAddressSpaceQualifier(unsigned AddressSpace) const89c9157d92SDimitry Andric std::optional<StringRef> MetadataStreamerMsgPackV4::getAddressSpaceQualifier(
90bdd1243dSDimitry Andric unsigned AddressSpace) const {
910b57cec5SDimitry Andric switch (AddressSpace) {
920b57cec5SDimitry Andric case AMDGPUAS::PRIVATE_ADDRESS:
930b57cec5SDimitry Andric return StringRef("private");
940b57cec5SDimitry Andric case AMDGPUAS::GLOBAL_ADDRESS:
950b57cec5SDimitry Andric return StringRef("global");
960b57cec5SDimitry Andric case AMDGPUAS::CONSTANT_ADDRESS:
970b57cec5SDimitry Andric return StringRef("constant");
980b57cec5SDimitry Andric case AMDGPUAS::LOCAL_ADDRESS:
990b57cec5SDimitry Andric return StringRef("local");
1000b57cec5SDimitry Andric case AMDGPUAS::FLAT_ADDRESS:
1010b57cec5SDimitry Andric return StringRef("generic");
1020b57cec5SDimitry Andric case AMDGPUAS::REGION_ADDRESS:
1030b57cec5SDimitry Andric return StringRef("region");
1040b57cec5SDimitry Andric default:
105bdd1243dSDimitry Andric return std::nullopt;
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric
109bdd1243dSDimitry Andric StringRef
getValueKind(Type * Ty,StringRef TypeQual,StringRef BaseTypeName) const110c9157d92SDimitry Andric MetadataStreamerMsgPackV4::getValueKind(Type *Ty, StringRef TypeQual,
1110b57cec5SDimitry Andric StringRef BaseTypeName) const {
112349cc55cSDimitry Andric if (TypeQual.contains("pipe"))
1130b57cec5SDimitry Andric return "pipe";
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andric return StringSwitch<StringRef>(BaseTypeName)
1160b57cec5SDimitry Andric .Case("image1d_t", "image")
1170b57cec5SDimitry Andric .Case("image1d_array_t", "image")
1180b57cec5SDimitry Andric .Case("image1d_buffer_t", "image")
1190b57cec5SDimitry Andric .Case("image2d_t", "image")
1200b57cec5SDimitry Andric .Case("image2d_array_t", "image")
1210b57cec5SDimitry Andric .Case("image2d_array_depth_t", "image")
1220b57cec5SDimitry Andric .Case("image2d_array_msaa_t", "image")
1230b57cec5SDimitry Andric .Case("image2d_array_msaa_depth_t", "image")
1240b57cec5SDimitry Andric .Case("image2d_depth_t", "image")
1250b57cec5SDimitry Andric .Case("image2d_msaa_t", "image")
1260b57cec5SDimitry Andric .Case("image2d_msaa_depth_t", "image")
1270b57cec5SDimitry Andric .Case("image3d_t", "image")
1280b57cec5SDimitry Andric .Case("sampler_t", "sampler")
1290b57cec5SDimitry Andric .Case("queue_t", "queue")
1300b57cec5SDimitry Andric .Default(isa<PointerType>(Ty)
1310b57cec5SDimitry Andric ? (Ty->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS
1320b57cec5SDimitry Andric ? "dynamic_shared_pointer"
1330b57cec5SDimitry Andric : "global_buffer")
1340b57cec5SDimitry Andric : "by_value");
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric
getTypeName(Type * Ty,bool Signed) const137c9157d92SDimitry Andric std::string MetadataStreamerMsgPackV4::getTypeName(Type *Ty,
138bdd1243dSDimitry Andric bool Signed) const {
1390b57cec5SDimitry Andric switch (Ty->getTypeID()) {
1400b57cec5SDimitry Andric case Type::IntegerTyID: {
1410b57cec5SDimitry Andric if (!Signed)
1420b57cec5SDimitry Andric return (Twine('u') + getTypeName(Ty, true)).str();
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric auto BitWidth = Ty->getIntegerBitWidth();
1450b57cec5SDimitry Andric switch (BitWidth) {
1460b57cec5SDimitry Andric case 8:
1470b57cec5SDimitry Andric return "char";
1480b57cec5SDimitry Andric case 16:
1490b57cec5SDimitry Andric return "short";
1500b57cec5SDimitry Andric case 32:
1510b57cec5SDimitry Andric return "int";
1520b57cec5SDimitry Andric case 64:
1530b57cec5SDimitry Andric return "long";
1540b57cec5SDimitry Andric default:
1550b57cec5SDimitry Andric return (Twine('i') + Twine(BitWidth)).str();
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric case Type::HalfTyID:
1590b57cec5SDimitry Andric return "half";
1600b57cec5SDimitry Andric case Type::FloatTyID:
1610b57cec5SDimitry Andric return "float";
1620b57cec5SDimitry Andric case Type::DoubleTyID:
1630b57cec5SDimitry Andric return "double";
1645ffd83dbSDimitry Andric case Type::FixedVectorTyID: {
1655ffd83dbSDimitry Andric auto VecTy = cast<FixedVectorType>(Ty);
1660b57cec5SDimitry Andric auto ElTy = VecTy->getElementType();
1675ffd83dbSDimitry Andric auto NumElements = VecTy->getNumElements();
1680b57cec5SDimitry Andric return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric default:
1710b57cec5SDimitry Andric return "unknown";
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andric msgpack::ArrayDocNode
getWorkGroupDimensions(MDNode * Node) const176c9157d92SDimitry Andric MetadataStreamerMsgPackV4::getWorkGroupDimensions(MDNode *Node) const {
1770b57cec5SDimitry Andric auto Dims = HSAMetadataDoc->getArrayNode();
1780b57cec5SDimitry Andric if (Node->getNumOperands() != 3)
1790b57cec5SDimitry Andric return Dims;
1800b57cec5SDimitry Andric
1810b57cec5SDimitry Andric for (auto &Op : Node->operands())
1820b57cec5SDimitry Andric Dims.push_back(Dims.getDocument()->getNode(
1830b57cec5SDimitry Andric uint64_t(mdconst::extract<ConstantInt>(Op)->getZExtValue())));
1840b57cec5SDimitry Andric return Dims;
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric
emitVersion()187c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::emitVersion() {
1880b57cec5SDimitry Andric auto Version = HSAMetadataDoc->getArrayNode();
189c9157d92SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMajorV4));
190c9157d92SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMinorV4));
1910b57cec5SDimitry Andric getRootMetadata("amdhsa.version") = Version;
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric
emitTargetID(const IsaInfo::AMDGPUTargetID & TargetID)194c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::emitTargetID(
195c9157d92SDimitry Andric const IsaInfo::AMDGPUTargetID &TargetID) {
196c9157d92SDimitry Andric getRootMetadata("amdhsa.target") =
197c9157d92SDimitry Andric HSAMetadataDoc->getNode(TargetID.toString(), /*Copy=*/true);
198c9157d92SDimitry Andric }
199c9157d92SDimitry Andric
emitPrintf(const Module & Mod)200c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::emitPrintf(const Module &Mod) {
2010b57cec5SDimitry Andric auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
2020b57cec5SDimitry Andric if (!Node)
2030b57cec5SDimitry Andric return;
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric auto Printf = HSAMetadataDoc->getArrayNode();
206bdd1243dSDimitry Andric for (auto *Op : Node->operands())
2070b57cec5SDimitry Andric if (Op->getNumOperands())
2080b57cec5SDimitry Andric Printf.push_back(Printf.getDocument()->getNode(
2090b57cec5SDimitry Andric cast<MDString>(Op->getOperand(0))->getString(), /*Copy=*/true));
2100b57cec5SDimitry Andric getRootMetadata("amdhsa.printf") = Printf;
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric
emitKernelLanguage(const Function & Func,msgpack::MapDocNode Kern)213c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::emitKernelLanguage(const Function &Func,
2140b57cec5SDimitry Andric msgpack::MapDocNode Kern) {
2150b57cec5SDimitry Andric // TODO: What about other languages?
2160b57cec5SDimitry Andric auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
2170b57cec5SDimitry Andric if (!Node || !Node->getNumOperands())
2180b57cec5SDimitry Andric return;
2190b57cec5SDimitry Andric auto Op0 = Node->getOperand(0);
2200b57cec5SDimitry Andric if (Op0->getNumOperands() <= 1)
2210b57cec5SDimitry Andric return;
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andric Kern[".language"] = Kern.getDocument()->getNode("OpenCL C");
2240b57cec5SDimitry Andric auto LanguageVersion = Kern.getDocument()->getArrayNode();
2250b57cec5SDimitry Andric LanguageVersion.push_back(Kern.getDocument()->getNode(
2260b57cec5SDimitry Andric mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue()));
2270b57cec5SDimitry Andric LanguageVersion.push_back(Kern.getDocument()->getNode(
2280b57cec5SDimitry Andric mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue()));
2290b57cec5SDimitry Andric Kern[".language_version"] = LanguageVersion;
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric
emitKernelAttrs(const Function & Func,msgpack::MapDocNode Kern)232c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::emitKernelAttrs(const Function &Func,
2330b57cec5SDimitry Andric msgpack::MapDocNode Kern) {
2340b57cec5SDimitry Andric
2350b57cec5SDimitry Andric if (auto Node = Func.getMetadata("reqd_work_group_size"))
2360b57cec5SDimitry Andric Kern[".reqd_workgroup_size"] = getWorkGroupDimensions(Node);
2370b57cec5SDimitry Andric if (auto Node = Func.getMetadata("work_group_size_hint"))
2380b57cec5SDimitry Andric Kern[".workgroup_size_hint"] = getWorkGroupDimensions(Node);
2390b57cec5SDimitry Andric if (auto Node = Func.getMetadata("vec_type_hint")) {
2400b57cec5SDimitry Andric Kern[".vec_type_hint"] = Kern.getDocument()->getNode(
2410b57cec5SDimitry Andric getTypeName(
2420b57cec5SDimitry Andric cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
2430b57cec5SDimitry Andric mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()),
2440b57cec5SDimitry Andric /*Copy=*/true);
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric if (Func.hasFnAttribute("runtime-handle")) {
2470b57cec5SDimitry Andric Kern[".device_enqueue_symbol"] = Kern.getDocument()->getNode(
2480b57cec5SDimitry Andric Func.getFnAttribute("runtime-handle").getValueAsString().str(),
2490b57cec5SDimitry Andric /*Copy=*/true);
2500b57cec5SDimitry Andric }
251349cc55cSDimitry Andric if (Func.hasFnAttribute("device-init"))
252349cc55cSDimitry Andric Kern[".kind"] = Kern.getDocument()->getNode("init");
253349cc55cSDimitry Andric else if (Func.hasFnAttribute("device-fini"))
254349cc55cSDimitry Andric Kern[".kind"] = Kern.getDocument()->getNode("fini");
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric
emitKernelArgs(const MachineFunction & MF,msgpack::MapDocNode Kern)257c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArgs(const MachineFunction &MF,
2580b57cec5SDimitry Andric msgpack::MapDocNode Kern) {
2591fd87a68SDimitry Andric auto &Func = MF.getFunction();
2600b57cec5SDimitry Andric unsigned Offset = 0;
2610b57cec5SDimitry Andric auto Args = HSAMetadataDoc->getArrayNode();
2620b57cec5SDimitry Andric for (auto &Arg : Func.args())
2630b57cec5SDimitry Andric emitKernelArg(Arg, Offset, Args);
2640b57cec5SDimitry Andric
2651fd87a68SDimitry Andric emitHiddenKernelArgs(MF, Offset, Args);
2660b57cec5SDimitry Andric
2670b57cec5SDimitry Andric Kern[".args"] = Args;
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric
emitKernelArg(const Argument & Arg,unsigned & Offset,msgpack::ArrayDocNode Args)270c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArg(const Argument &Arg,
271bdd1243dSDimitry Andric unsigned &Offset,
2720b57cec5SDimitry Andric msgpack::ArrayDocNode Args) {
2730b57cec5SDimitry Andric auto Func = Arg.getParent();
2740b57cec5SDimitry Andric auto ArgNo = Arg.getArgNo();
2750b57cec5SDimitry Andric const MDNode *Node;
2760b57cec5SDimitry Andric
2770b57cec5SDimitry Andric StringRef Name;
2780b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_name");
2790b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
2800b57cec5SDimitry Andric Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
2810b57cec5SDimitry Andric else if (Arg.hasName())
2820b57cec5SDimitry Andric Name = Arg.getName();
2830b57cec5SDimitry Andric
2840b57cec5SDimitry Andric StringRef TypeName;
2850b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_type");
2860b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
2870b57cec5SDimitry Andric TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
2880b57cec5SDimitry Andric
2890b57cec5SDimitry Andric StringRef BaseTypeName;
2900b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_base_type");
2910b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
2920b57cec5SDimitry Andric BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
2930b57cec5SDimitry Andric
294c9157d92SDimitry Andric StringRef ActAccQual;
295c9157d92SDimitry Andric // Do we really need NoAlias check here?
296c9157d92SDimitry Andric if (Arg.getType()->isPointerTy() && Arg.hasNoAliasAttr()) {
297c9157d92SDimitry Andric if (Arg.onlyReadsMemory())
298c9157d92SDimitry Andric ActAccQual = "read_only";
299c9157d92SDimitry Andric else if (Arg.hasAttribute(Attribute::WriteOnly))
300c9157d92SDimitry Andric ActAccQual = "write_only";
301c9157d92SDimitry Andric }
302c9157d92SDimitry Andric
3030b57cec5SDimitry Andric StringRef AccQual;
3040b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_access_qual");
3050b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3060b57cec5SDimitry Andric AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
3070b57cec5SDimitry Andric
3080b57cec5SDimitry Andric StringRef TypeQual;
3090b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_type_qual");
3100b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3110b57cec5SDimitry Andric TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
3120b57cec5SDimitry Andric
3130b57cec5SDimitry Andric const DataLayout &DL = Func->getParent()->getDataLayout();
3140b57cec5SDimitry Andric
3155ffd83dbSDimitry Andric MaybeAlign PointeeAlign;
316e8d8bef9SDimitry Andric Type *Ty = Arg.hasByRefAttr() ? Arg.getParamByRefType() : Arg.getType();
317e8d8bef9SDimitry Andric
318e8d8bef9SDimitry Andric // FIXME: Need to distinguish in memory alignment from pointer alignment.
3190b57cec5SDimitry Andric if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
32004eeddc0SDimitry Andric if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS)
32104eeddc0SDimitry Andric PointeeAlign = Arg.getParamAlign().valueOrOne();
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric
324e8d8bef9SDimitry Andric // There's no distinction between byval aggregates and raw aggregates.
325e8d8bef9SDimitry Andric Type *ArgTy;
326e8d8bef9SDimitry Andric Align ArgAlign;
327e8d8bef9SDimitry Andric std::tie(ArgTy, ArgAlign) = getArgumentTypeAlign(Arg, DL);
328e8d8bef9SDimitry Andric
329e8d8bef9SDimitry Andric emitKernelArg(DL, ArgTy, ArgAlign,
330e8d8bef9SDimitry Andric getValueKind(ArgTy, TypeQual, BaseTypeName), Offset, Args,
331c9157d92SDimitry Andric PointeeAlign, Name, TypeName, BaseTypeName, ActAccQual,
332c9157d92SDimitry Andric AccQual, TypeQual);
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric
emitKernelArg(const DataLayout & DL,Type * Ty,Align Alignment,StringRef ValueKind,unsigned & Offset,msgpack::ArrayDocNode Args,MaybeAlign PointeeAlign,StringRef Name,StringRef TypeName,StringRef BaseTypeName,StringRef ActAccQual,StringRef AccQual,StringRef TypeQual)335c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArg(
336e8d8bef9SDimitry Andric const DataLayout &DL, Type *Ty, Align Alignment, StringRef ValueKind,
337e8d8bef9SDimitry Andric unsigned &Offset, msgpack::ArrayDocNode Args, MaybeAlign PointeeAlign,
338e8d8bef9SDimitry Andric StringRef Name, StringRef TypeName, StringRef BaseTypeName,
339c9157d92SDimitry Andric StringRef ActAccQual, StringRef AccQual, StringRef TypeQual) {
3400b57cec5SDimitry Andric auto Arg = Args.getDocument()->getMapNode();
3410b57cec5SDimitry Andric
3420b57cec5SDimitry Andric if (!Name.empty())
3430b57cec5SDimitry Andric Arg[".name"] = Arg.getDocument()->getNode(Name, /*Copy=*/true);
3440b57cec5SDimitry Andric if (!TypeName.empty())
3450b57cec5SDimitry Andric Arg[".type_name"] = Arg.getDocument()->getNode(TypeName, /*Copy=*/true);
3460b57cec5SDimitry Andric auto Size = DL.getTypeAllocSize(Ty);
3470b57cec5SDimitry Andric Arg[".size"] = Arg.getDocument()->getNode(Size);
3485ffd83dbSDimitry Andric Offset = alignTo(Offset, Alignment);
3490b57cec5SDimitry Andric Arg[".offset"] = Arg.getDocument()->getNode(Offset);
3500b57cec5SDimitry Andric Offset += Size;
3510b57cec5SDimitry Andric Arg[".value_kind"] = Arg.getDocument()->getNode(ValueKind, /*Copy=*/true);
3520b57cec5SDimitry Andric if (PointeeAlign)
3535ffd83dbSDimitry Andric Arg[".pointee_align"] = Arg.getDocument()->getNode(PointeeAlign->value());
3540b57cec5SDimitry Andric
3550b57cec5SDimitry Andric if (auto PtrTy = dyn_cast<PointerType>(Ty))
3560b57cec5SDimitry Andric if (auto Qualifier = getAddressSpaceQualifier(PtrTy->getAddressSpace()))
357bdd1243dSDimitry Andric // Limiting address space to emit only for a certain ValueKind.
358bdd1243dSDimitry Andric if (ValueKind == "global_buffer" || ValueKind == "dynamic_shared_pointer")
359bdd1243dSDimitry Andric Arg[".address_space"] = Arg.getDocument()->getNode(*Qualifier,
360bdd1243dSDimitry Andric /*Copy=*/true);
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andric if (auto AQ = getAccessQualifier(AccQual))
3630b57cec5SDimitry Andric Arg[".access"] = Arg.getDocument()->getNode(*AQ, /*Copy=*/true);
3640b57cec5SDimitry Andric
365c9157d92SDimitry Andric if (auto AAQ = getAccessQualifier(ActAccQual))
366c9157d92SDimitry Andric Arg[".actual_access"] = Arg.getDocument()->getNode(*AAQ, /*Copy=*/true);
3670b57cec5SDimitry Andric
3680b57cec5SDimitry Andric SmallVector<StringRef, 1> SplitTypeQuals;
3690b57cec5SDimitry Andric TypeQual.split(SplitTypeQuals, " ", -1, false);
3700b57cec5SDimitry Andric for (StringRef Key : SplitTypeQuals) {
3710b57cec5SDimitry Andric if (Key == "const")
3720b57cec5SDimitry Andric Arg[".is_const"] = Arg.getDocument()->getNode(true);
3730b57cec5SDimitry Andric else if (Key == "restrict")
3740b57cec5SDimitry Andric Arg[".is_restrict"] = Arg.getDocument()->getNode(true);
3750b57cec5SDimitry Andric else if (Key == "volatile")
3760b57cec5SDimitry Andric Arg[".is_volatile"] = Arg.getDocument()->getNode(true);
3770b57cec5SDimitry Andric else if (Key == "pipe")
3780b57cec5SDimitry Andric Arg[".is_pipe"] = Arg.getDocument()->getNode(true);
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric
3810b57cec5SDimitry Andric Args.push_back(Arg);
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric
emitHiddenKernelArgs(const MachineFunction & MF,unsigned & Offset,msgpack::ArrayDocNode Args)384c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::emitHiddenKernelArgs(
385bdd1243dSDimitry Andric const MachineFunction &MF, unsigned &Offset, msgpack::ArrayDocNode Args) {
3861fd87a68SDimitry Andric auto &Func = MF.getFunction();
3871fd87a68SDimitry Andric const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3881fd87a68SDimitry Andric
3890eae32dcSDimitry Andric unsigned HiddenArgNumBytes = ST.getImplicitArgNumBytes(Func);
3900b57cec5SDimitry Andric if (!HiddenArgNumBytes)
3910b57cec5SDimitry Andric return;
3920b57cec5SDimitry Andric
393349cc55cSDimitry Andric const Module *M = Func.getParent();
394349cc55cSDimitry Andric auto &DL = M->getDataLayout();
3950b57cec5SDimitry Andric auto Int64Ty = Type::getInt64Ty(Func.getContext());
3960b57cec5SDimitry Andric
39781ad6265SDimitry Andric Offset = alignTo(Offset, ST.getAlignmentForImplicitArgPtr());
39881ad6265SDimitry Andric
3990b57cec5SDimitry Andric if (HiddenArgNumBytes >= 8)
400e8d8bef9SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset,
401e8d8bef9SDimitry Andric Args);
4020b57cec5SDimitry Andric if (HiddenArgNumBytes >= 16)
403e8d8bef9SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset,
404e8d8bef9SDimitry Andric Args);
4050b57cec5SDimitry Andric if (HiddenArgNumBytes >= 24)
406e8d8bef9SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset,
407e8d8bef9SDimitry Andric Args);
4080b57cec5SDimitry Andric
4090b57cec5SDimitry Andric auto Int8PtrTy =
410c9157d92SDimitry Andric PointerType::get(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
4110b57cec5SDimitry Andric
4120b57cec5SDimitry Andric if (HiddenArgNumBytes >= 32) {
41381ad6265SDimitry Andric // We forbid the use of features requiring hostcall when compiling OpenCL
41481ad6265SDimitry Andric // before code object V5, which makes the mutual exclusion between the
41581ad6265SDimitry Andric // "printf buffer" and "hostcall buffer" here sound.
416349cc55cSDimitry Andric if (M->getNamedMetadata("llvm.printf.fmts"))
417e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
418e8d8bef9SDimitry Andric Args);
41981ad6265SDimitry Andric else if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr"))
420e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
421e8d8bef9SDimitry Andric Args);
42281ad6265SDimitry Andric else
423e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric
4260b57cec5SDimitry Andric // Emit "default queue" and "completion action" arguments if enqueue kernel is
4270b57cec5SDimitry Andric // used, otherwise emit dummy "none" arguments.
428bdd1243dSDimitry Andric if (HiddenArgNumBytes >= 40) {
429bdd1243dSDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-default-queue")) {
430e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
431e8d8bef9SDimitry Andric Args);
4320b57cec5SDimitry Andric } else {
433e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
434bdd1243dSDimitry Andric }
435bdd1243dSDimitry Andric }
436bdd1243dSDimitry Andric
437bdd1243dSDimitry Andric if (HiddenArgNumBytes >= 48) {
438fe013be4SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-completion-action")) {
439bdd1243dSDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
440bdd1243dSDimitry Andric Args);
441bdd1243dSDimitry Andric } else {
442e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
4430b57cec5SDimitry Andric }
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric
4460b57cec5SDimitry Andric // Emit the pointer argument for multi-grid object.
44781ad6265SDimitry Andric if (HiddenArgNumBytes >= 56) {
44881ad6265SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-multigrid-sync-arg")) {
449e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
450e8d8bef9SDimitry Andric Args);
45181ad6265SDimitry Andric } else {
45281ad6265SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
45381ad6265SDimitry Andric }
45481ad6265SDimitry Andric }
4550b57cec5SDimitry Andric }
4560b57cec5SDimitry Andric
457c9157d92SDimitry Andric msgpack::MapDocNode
getHSAKernelProps(const MachineFunction & MF,const SIProgramInfo & ProgramInfo,unsigned CodeObjectVersion) const458c9157d92SDimitry Andric MetadataStreamerMsgPackV4::getHSAKernelProps(const MachineFunction &MF,
459c9157d92SDimitry Andric const SIProgramInfo &ProgramInfo,
460fe013be4SDimitry Andric unsigned CodeObjectVersion) const {
4610b57cec5SDimitry Andric const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
4620b57cec5SDimitry Andric const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
4630b57cec5SDimitry Andric const Function &F = MF.getFunction();
4640b57cec5SDimitry Andric
4650b57cec5SDimitry Andric auto Kern = HSAMetadataDoc->getMapNode();
4660b57cec5SDimitry Andric
4678bcb0991SDimitry Andric Align MaxKernArgAlign;
4680b57cec5SDimitry Andric Kern[".kernarg_segment_size"] = Kern.getDocument()->getNode(
4690b57cec5SDimitry Andric STM.getKernArgSegmentSize(F, MaxKernArgAlign));
4700b57cec5SDimitry Andric Kern[".group_segment_fixed_size"] =
4710b57cec5SDimitry Andric Kern.getDocument()->getNode(ProgramInfo.LDSSize);
4720b57cec5SDimitry Andric Kern[".private_segment_fixed_size"] =
4730b57cec5SDimitry Andric Kern.getDocument()->getNode(ProgramInfo.ScratchSize);
474fe013be4SDimitry Andric if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5)
475fcaf7f86SDimitry Andric Kern[".uses_dynamic_stack"] =
476fcaf7f86SDimitry Andric Kern.getDocument()->getNode(ProgramInfo.DynamicCallStack);
477fe013be4SDimitry Andric
478fe013be4SDimitry Andric if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5 && STM.supportsWGP())
479bdd1243dSDimitry Andric Kern[".workgroup_processor_mode"] =
480bdd1243dSDimitry Andric Kern.getDocument()->getNode(ProgramInfo.WgpMode);
481349cc55cSDimitry Andric
482349cc55cSDimitry Andric // FIXME: The metadata treats the minimum as 16?
4830b57cec5SDimitry Andric Kern[".kernarg_segment_align"] =
4848bcb0991SDimitry Andric Kern.getDocument()->getNode(std::max(Align(4), MaxKernArgAlign).value());
4850b57cec5SDimitry Andric Kern[".wavefront_size"] =
4860b57cec5SDimitry Andric Kern.getDocument()->getNode(STM.getWavefrontSize());
4870b57cec5SDimitry Andric Kern[".sgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumSGPR);
4880b57cec5SDimitry Andric Kern[".vgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumVGPR);
48981ad6265SDimitry Andric
49081ad6265SDimitry Andric // Only add AGPR count to metadata for supported devices
49181ad6265SDimitry Andric if (STM.hasMAIInsts()) {
49281ad6265SDimitry Andric Kern[".agpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumAccVGPR);
49381ad6265SDimitry Andric }
49481ad6265SDimitry Andric
4950b57cec5SDimitry Andric Kern[".max_flat_workgroup_size"] =
4960b57cec5SDimitry Andric Kern.getDocument()->getNode(MFI.getMaxFlatWorkGroupSize());
4970b57cec5SDimitry Andric Kern[".sgpr_spill_count"] =
4980b57cec5SDimitry Andric Kern.getDocument()->getNode(MFI.getNumSpilledSGPRs());
4990b57cec5SDimitry Andric Kern[".vgpr_spill_count"] =
5000b57cec5SDimitry Andric Kern.getDocument()->getNode(MFI.getNumSpilledVGPRs());
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric return Kern;
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric
emitTo(AMDGPUTargetStreamer & TargetStreamer)505c9157d92SDimitry Andric bool MetadataStreamerMsgPackV4::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
5060b57cec5SDimitry Andric return TargetStreamer.EmitHSAMetadata(*HSAMetadataDoc, true);
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric
begin(const Module & Mod,const IsaInfo::AMDGPUTargetID & TargetID)509c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::begin(const Module &Mod,
510fe6060f1SDimitry Andric const IsaInfo::AMDGPUTargetID &TargetID) {
5110b57cec5SDimitry Andric emitVersion();
512c9157d92SDimitry Andric emitTargetID(TargetID);
5130b57cec5SDimitry Andric emitPrintf(Mod);
5140b57cec5SDimitry Andric getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode();
5150b57cec5SDimitry Andric }
5160b57cec5SDimitry Andric
end()517c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::end() {
5180b57cec5SDimitry Andric std::string HSAMetadataString;
5190b57cec5SDimitry Andric raw_string_ostream StrOS(HSAMetadataString);
5200b57cec5SDimitry Andric HSAMetadataDoc->toYAML(StrOS);
5210b57cec5SDimitry Andric
5220b57cec5SDimitry Andric if (DumpHSAMetadata)
5230b57cec5SDimitry Andric dump(StrOS.str());
5240b57cec5SDimitry Andric if (VerifyHSAMetadata)
5250b57cec5SDimitry Andric verify(StrOS.str());
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric
emitKernel(const MachineFunction & MF,const SIProgramInfo & ProgramInfo)528c9157d92SDimitry Andric void MetadataStreamerMsgPackV4::emitKernel(const MachineFunction &MF,
5290b57cec5SDimitry Andric const SIProgramInfo &ProgramInfo) {
5300b57cec5SDimitry Andric auto &Func = MF.getFunction();
531fe013be4SDimitry Andric if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL &&
532fe013be4SDimitry Andric Func.getCallingConv() != CallingConv::SPIR_KERNEL)
533fe013be4SDimitry Andric return;
5340b57cec5SDimitry Andric
535*a58f00eaSDimitry Andric auto CodeObjectVersion =
536*a58f00eaSDimitry Andric AMDGPU::getAMDHSACodeObjectVersion(*Func.getParent());
537fe013be4SDimitry Andric auto Kern = getHSAKernelProps(MF, ProgramInfo, CodeObjectVersion);
5380b57cec5SDimitry Andric
5390b57cec5SDimitry Andric auto Kernels =
5400b57cec5SDimitry Andric getRootMetadata("amdhsa.kernels").getArray(/*Convert=*/true);
5410b57cec5SDimitry Andric
5420b57cec5SDimitry Andric {
5430b57cec5SDimitry Andric Kern[".name"] = Kern.getDocument()->getNode(Func.getName());
5440b57cec5SDimitry Andric Kern[".symbol"] = Kern.getDocument()->getNode(
5450b57cec5SDimitry Andric (Twine(Func.getName()) + Twine(".kd")).str(), /*Copy=*/true);
5460b57cec5SDimitry Andric emitKernelLanguage(Func, Kern);
5470b57cec5SDimitry Andric emitKernelAttrs(Func, Kern);
5481fd87a68SDimitry Andric emitKernelArgs(MF, Kern);
5490b57cec5SDimitry Andric }
5500b57cec5SDimitry Andric
5510b57cec5SDimitry Andric Kernels.push_back(Kern);
5520b57cec5SDimitry Andric }
5530b57cec5SDimitry Andric
554fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
5551fd87a68SDimitry Andric // HSAMetadataStreamerV5
5561fd87a68SDimitry Andric //===----------------------------------------------------------------------===//
5571fd87a68SDimitry Andric
emitVersion()558bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitVersion() {
5591fd87a68SDimitry Andric auto Version = HSAMetadataDoc->getArrayNode();
5601fd87a68SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMajorV5));
5611fd87a68SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMinorV5));
5621fd87a68SDimitry Andric getRootMetadata("amdhsa.version") = Version;
5631fd87a68SDimitry Andric }
5641fd87a68SDimitry Andric
emitHiddenKernelArgs(const MachineFunction & MF,unsigned & Offset,msgpack::ArrayDocNode Args)565bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitHiddenKernelArgs(
566bdd1243dSDimitry Andric const MachineFunction &MF, unsigned &Offset, msgpack::ArrayDocNode Args) {
5671fd87a68SDimitry Andric auto &Func = MF.getFunction();
5681fd87a68SDimitry Andric const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
56981ad6265SDimitry Andric
57081ad6265SDimitry Andric // No implicit kernel argument is used.
57181ad6265SDimitry Andric if (ST.getImplicitArgNumBytes(Func) == 0)
57281ad6265SDimitry Andric return;
57381ad6265SDimitry Andric
5741fd87a68SDimitry Andric const Module *M = Func.getParent();
5751fd87a68SDimitry Andric auto &DL = M->getDataLayout();
57681ad6265SDimitry Andric const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
5771fd87a68SDimitry Andric
5781fd87a68SDimitry Andric auto Int64Ty = Type::getInt64Ty(Func.getContext());
5791fd87a68SDimitry Andric auto Int32Ty = Type::getInt32Ty(Func.getContext());
5801fd87a68SDimitry Andric auto Int16Ty = Type::getInt16Ty(Func.getContext());
5811fd87a68SDimitry Andric
58281ad6265SDimitry Andric Offset = alignTo(Offset, ST.getAlignmentForImplicitArgPtr());
5831fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_x", Offset, Args);
5841fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_y", Offset, Args);
5851fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_z", Offset, Args);
5861fd87a68SDimitry Andric
5871fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_x", Offset, Args);
5881fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_y", Offset, Args);
5891fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_z", Offset, Args);
5901fd87a68SDimitry Andric
5911fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_x", Offset, Args);
5921fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_y", Offset, Args);
5931fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_z", Offset, Args);
5941fd87a68SDimitry Andric
5951fd87a68SDimitry Andric // Reserved for hidden_tool_correlation_id.
5961fd87a68SDimitry Andric Offset += 8;
5971fd87a68SDimitry Andric
5981fd87a68SDimitry Andric Offset += 8; // Reserved.
5991fd87a68SDimitry Andric
6001fd87a68SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset, Args);
6011fd87a68SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset, Args);
6021fd87a68SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset, Args);
6031fd87a68SDimitry Andric
6041fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_grid_dims", Offset, Args);
6051fd87a68SDimitry Andric
6061fd87a68SDimitry Andric Offset += 6; // Reserved.
6071fd87a68SDimitry Andric auto Int8PtrTy =
608c9157d92SDimitry Andric PointerType::get(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
6091fd87a68SDimitry Andric
6101fd87a68SDimitry Andric if (M->getNamedMetadata("llvm.printf.fmts")) {
6111fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
6121fd87a68SDimitry Andric Args);
61381ad6265SDimitry Andric } else {
6141fd87a68SDimitry Andric Offset += 8; // Skipped.
61581ad6265SDimitry Andric }
6161fd87a68SDimitry Andric
61781ad6265SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr")) {
6181fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
6191fd87a68SDimitry Andric Args);
62081ad6265SDimitry Andric } else {
6211fd87a68SDimitry Andric Offset += 8; // Skipped.
62281ad6265SDimitry Andric }
6231fd87a68SDimitry Andric
62481ad6265SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-multigrid-sync-arg")) {
6251fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
6261fd87a68SDimitry Andric Args);
62781ad6265SDimitry Andric } else {
62881ad6265SDimitry Andric Offset += 8; // Skipped.
62981ad6265SDimitry Andric }
6301fd87a68SDimitry Andric
63181ad6265SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-heap-ptr"))
63281ad6265SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_heap_v1", Offset, Args);
63381ad6265SDimitry Andric else
63481ad6265SDimitry Andric Offset += 8; // Skipped.
6351fd87a68SDimitry Andric
636bdd1243dSDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-default-queue")) {
6371fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
6381fd87a68SDimitry Andric Args);
639bdd1243dSDimitry Andric } else {
640bdd1243dSDimitry Andric Offset += 8; // Skipped.
641bdd1243dSDimitry Andric }
642bdd1243dSDimitry Andric
643fe013be4SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-completion-action")) {
6441fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
6451fd87a68SDimitry Andric Args);
64681ad6265SDimitry Andric } else {
647bdd1243dSDimitry Andric Offset += 8; // Skipped.
64881ad6265SDimitry Andric }
6491fd87a68SDimitry Andric
650cdc20ff6SDimitry Andric // Emit argument for hidden dynamic lds size
651cdc20ff6SDimitry Andric if (MFI.isDynamicLDSUsed()) {
652cdc20ff6SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_dynamic_lds_size", Offset,
653cdc20ff6SDimitry Andric Args);
654cdc20ff6SDimitry Andric } else {
655cdc20ff6SDimitry Andric Offset += 4; // skipped
656cdc20ff6SDimitry Andric }
657cdc20ff6SDimitry Andric
658cdc20ff6SDimitry Andric Offset += 68; // Reserved.
6591fd87a68SDimitry Andric
66081ad6265SDimitry Andric // hidden_private_base and hidden_shared_base are only when the subtarget has
66181ad6265SDimitry Andric // ApertureRegs.
66281ad6265SDimitry Andric if (!ST.hasApertureRegs()) {
6631fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_private_base", Offset, Args);
6641fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_shared_base", Offset, Args);
66581ad6265SDimitry Andric } else {
6661fd87a68SDimitry Andric Offset += 8; // Skipped.
66781ad6265SDimitry Andric }
6681fd87a68SDimitry Andric
669c9157d92SDimitry Andric if (MFI.getUserSGPRInfo().hasQueuePtr())
6701fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_queue_ptr", Offset, Args);
6711fd87a68SDimitry Andric }
6721fd87a68SDimitry Andric
emitKernelAttrs(const Function & Func,msgpack::MapDocNode Kern)673bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitKernelAttrs(const Function &Func,
674bdd1243dSDimitry Andric msgpack::MapDocNode Kern) {
675c9157d92SDimitry Andric MetadataStreamerMsgPackV4::emitKernelAttrs(Func, Kern);
676bdd1243dSDimitry Andric
677bdd1243dSDimitry Andric if (Func.getFnAttribute("uniform-work-group-size").getValueAsBool())
678bdd1243dSDimitry Andric Kern[".uniform_work_group_size"] = Kern.getDocument()->getNode(1);
679bdd1243dSDimitry Andric }
680bdd1243dSDimitry Andric
681bdd1243dSDimitry Andric
6820b57cec5SDimitry Andric } // end namespace HSAMD
6830b57cec5SDimitry Andric } // end namespace AMDGPU
6840b57cec5SDimitry Andric } // end namespace llvm
685