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"
22*0fca6ea1SDimitry Andric #include "llvm/MC/MCContext.h"
23*0fca6ea1SDimitry Andric #include "llvm/MC/MCExpr.h"
24e8d8bef9SDimitry Andric using namespace llvm;
25e8d8bef9SDimitry Andric
getArgumentTypeAlign(const Argument & Arg,const DataLayout & DL)26e8d8bef9SDimitry Andric static std::pair<Type *, Align> getArgumentTypeAlign(const Argument &Arg,
27e8d8bef9SDimitry Andric const DataLayout &DL) {
28e8d8bef9SDimitry Andric Type *Ty = Arg.getType();
29e8d8bef9SDimitry Andric MaybeAlign ArgAlign;
30e8d8bef9SDimitry Andric if (Arg.hasByRefAttr()) {
31e8d8bef9SDimitry Andric Ty = Arg.getParamByRefType();
32e8d8bef9SDimitry Andric ArgAlign = Arg.getParamAlign();
33e8d8bef9SDimitry Andric }
34e8d8bef9SDimitry Andric
35e8d8bef9SDimitry Andric if (!ArgAlign)
36e8d8bef9SDimitry Andric ArgAlign = DL.getABITypeAlign(Ty);
37e8d8bef9SDimitry Andric
38bdd1243dSDimitry Andric return std::pair(Ty, *ArgAlign);
39e8d8bef9SDimitry Andric }
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric namespace llvm {
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric static cl::opt<bool> DumpHSAMetadata(
440b57cec5SDimitry Andric "amdgpu-dump-hsa-metadata",
450b57cec5SDimitry Andric cl::desc("Dump AMDGPU HSA Metadata"));
460b57cec5SDimitry Andric static cl::opt<bool> VerifyHSAMetadata(
470b57cec5SDimitry Andric "amdgpu-verify-hsa-metadata",
480b57cec5SDimitry Andric cl::desc("Verify AMDGPU HSA Metadata"));
490b57cec5SDimitry Andric
50*0fca6ea1SDimitry Andric namespace AMDGPU::HSAMD {
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
535f757f3fSDimitry Andric // HSAMetadataStreamerV4
540b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
555f757f3fSDimitry Andric
dump(StringRef HSAMetadataString) const565f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::dump(StringRef HSAMetadataString) const {
570b57cec5SDimitry Andric errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric
verify(StringRef HSAMetadataString) const605f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::verify(StringRef HSAMetadataString) const {
610b57cec5SDimitry Andric errs() << "AMDGPU HSA Metadata Parser Test: ";
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric msgpack::Document FromHSAMetadataString;
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric if (!FromHSAMetadataString.fromYAML(HSAMetadataString)) {
660b57cec5SDimitry Andric errs() << "FAIL\n";
670b57cec5SDimitry Andric return;
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric
700b57cec5SDimitry Andric std::string ToHSAMetadataString;
710b57cec5SDimitry Andric raw_string_ostream StrOS(ToHSAMetadataString);
720b57cec5SDimitry Andric FromHSAMetadataString.toYAML(StrOS);
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric errs() << (HSAMetadataString == StrOS.str() ? "PASS" : "FAIL") << '\n';
750b57cec5SDimitry Andric if (HSAMetadataString != ToHSAMetadataString) {
760b57cec5SDimitry Andric errs() << "Original input: " << HSAMetadataString << '\n'
770b57cec5SDimitry Andric << "Produced output: " << StrOS.str() << '\n';
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric
81bdd1243dSDimitry Andric std::optional<StringRef>
getAccessQualifier(StringRef AccQual) const825f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getAccessQualifier(StringRef AccQual) const {
83bdd1243dSDimitry Andric return StringSwitch<std::optional<StringRef>>(AccQual)
840b57cec5SDimitry Andric .Case("read_only", StringRef("read_only"))
850b57cec5SDimitry Andric .Case("write_only", StringRef("write_only"))
860b57cec5SDimitry Andric .Case("read_write", StringRef("read_write"))
87bdd1243dSDimitry Andric .Default(std::nullopt);
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric
getAddressSpaceQualifier(unsigned AddressSpace) const905f757f3fSDimitry Andric std::optional<StringRef> MetadataStreamerMsgPackV4::getAddressSpaceQualifier(
91bdd1243dSDimitry Andric unsigned AddressSpace) const {
920b57cec5SDimitry Andric switch (AddressSpace) {
930b57cec5SDimitry Andric case AMDGPUAS::PRIVATE_ADDRESS:
940b57cec5SDimitry Andric return StringRef("private");
950b57cec5SDimitry Andric case AMDGPUAS::GLOBAL_ADDRESS:
960b57cec5SDimitry Andric return StringRef("global");
970b57cec5SDimitry Andric case AMDGPUAS::CONSTANT_ADDRESS:
980b57cec5SDimitry Andric return StringRef("constant");
990b57cec5SDimitry Andric case AMDGPUAS::LOCAL_ADDRESS:
1000b57cec5SDimitry Andric return StringRef("local");
1010b57cec5SDimitry Andric case AMDGPUAS::FLAT_ADDRESS:
1020b57cec5SDimitry Andric return StringRef("generic");
1030b57cec5SDimitry Andric case AMDGPUAS::REGION_ADDRESS:
1040b57cec5SDimitry Andric return StringRef("region");
1050b57cec5SDimitry Andric default:
106bdd1243dSDimitry Andric return std::nullopt;
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric
110bdd1243dSDimitry Andric StringRef
getValueKind(Type * Ty,StringRef TypeQual,StringRef BaseTypeName) const1115f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getValueKind(Type *Ty, StringRef TypeQual,
1120b57cec5SDimitry Andric StringRef BaseTypeName) const {
113349cc55cSDimitry Andric if (TypeQual.contains("pipe"))
1140b57cec5SDimitry Andric return "pipe";
1150b57cec5SDimitry Andric
1160b57cec5SDimitry Andric return StringSwitch<StringRef>(BaseTypeName)
1170b57cec5SDimitry Andric .Case("image1d_t", "image")
1180b57cec5SDimitry Andric .Case("image1d_array_t", "image")
1190b57cec5SDimitry Andric .Case("image1d_buffer_t", "image")
1200b57cec5SDimitry Andric .Case("image2d_t", "image")
1210b57cec5SDimitry Andric .Case("image2d_array_t", "image")
1220b57cec5SDimitry Andric .Case("image2d_array_depth_t", "image")
1230b57cec5SDimitry Andric .Case("image2d_array_msaa_t", "image")
1240b57cec5SDimitry Andric .Case("image2d_array_msaa_depth_t", "image")
1250b57cec5SDimitry Andric .Case("image2d_depth_t", "image")
1260b57cec5SDimitry Andric .Case("image2d_msaa_t", "image")
1270b57cec5SDimitry Andric .Case("image2d_msaa_depth_t", "image")
1280b57cec5SDimitry Andric .Case("image3d_t", "image")
1290b57cec5SDimitry Andric .Case("sampler_t", "sampler")
1300b57cec5SDimitry Andric .Case("queue_t", "queue")
1310b57cec5SDimitry Andric .Default(isa<PointerType>(Ty)
1320b57cec5SDimitry Andric ? (Ty->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS
1330b57cec5SDimitry Andric ? "dynamic_shared_pointer"
1340b57cec5SDimitry Andric : "global_buffer")
1350b57cec5SDimitry Andric : "by_value");
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric
getTypeName(Type * Ty,bool Signed) const1385f757f3fSDimitry Andric std::string MetadataStreamerMsgPackV4::getTypeName(Type *Ty,
139bdd1243dSDimitry Andric bool Signed) const {
1400b57cec5SDimitry Andric switch (Ty->getTypeID()) {
1410b57cec5SDimitry Andric case Type::IntegerTyID: {
1420b57cec5SDimitry Andric if (!Signed)
1430b57cec5SDimitry Andric return (Twine('u') + getTypeName(Ty, true)).str();
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andric auto BitWidth = Ty->getIntegerBitWidth();
1460b57cec5SDimitry Andric switch (BitWidth) {
1470b57cec5SDimitry Andric case 8:
1480b57cec5SDimitry Andric return "char";
1490b57cec5SDimitry Andric case 16:
1500b57cec5SDimitry Andric return "short";
1510b57cec5SDimitry Andric case 32:
1520b57cec5SDimitry Andric return "int";
1530b57cec5SDimitry Andric case 64:
1540b57cec5SDimitry Andric return "long";
1550b57cec5SDimitry Andric default:
1560b57cec5SDimitry Andric return (Twine('i') + Twine(BitWidth)).str();
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric case Type::HalfTyID:
1600b57cec5SDimitry Andric return "half";
1610b57cec5SDimitry Andric case Type::FloatTyID:
1620b57cec5SDimitry Andric return "float";
1630b57cec5SDimitry Andric case Type::DoubleTyID:
1640b57cec5SDimitry Andric return "double";
1655ffd83dbSDimitry Andric case Type::FixedVectorTyID: {
1665ffd83dbSDimitry Andric auto VecTy = cast<FixedVectorType>(Ty);
1670b57cec5SDimitry Andric auto ElTy = VecTy->getElementType();
1685ffd83dbSDimitry Andric auto NumElements = VecTy->getNumElements();
1690b57cec5SDimitry Andric return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric default:
1720b57cec5SDimitry Andric return "unknown";
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric msgpack::ArrayDocNode
getWorkGroupDimensions(MDNode * Node) const1775f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getWorkGroupDimensions(MDNode *Node) const {
1780b57cec5SDimitry Andric auto Dims = HSAMetadataDoc->getArrayNode();
1790b57cec5SDimitry Andric if (Node->getNumOperands() != 3)
1800b57cec5SDimitry Andric return Dims;
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric for (auto &Op : Node->operands())
1830b57cec5SDimitry Andric Dims.push_back(Dims.getDocument()->getNode(
1840b57cec5SDimitry Andric uint64_t(mdconst::extract<ConstantInt>(Op)->getZExtValue())));
1850b57cec5SDimitry Andric return Dims;
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric
emitVersion()1885f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitVersion() {
1890b57cec5SDimitry Andric auto Version = HSAMetadataDoc->getArrayNode();
1905f757f3fSDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMajorV4));
1915f757f3fSDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMinorV4));
1920b57cec5SDimitry Andric getRootMetadata("amdhsa.version") = Version;
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric
emitTargetID(const IsaInfo::AMDGPUTargetID & TargetID)1955f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitTargetID(
1965f757f3fSDimitry Andric const IsaInfo::AMDGPUTargetID &TargetID) {
1975f757f3fSDimitry Andric getRootMetadata("amdhsa.target") =
1985f757f3fSDimitry Andric HSAMetadataDoc->getNode(TargetID.toString(), /*Copy=*/true);
1995f757f3fSDimitry Andric }
2005f757f3fSDimitry Andric
emitPrintf(const Module & Mod)2015f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitPrintf(const Module &Mod) {
2020b57cec5SDimitry Andric auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
2030b57cec5SDimitry Andric if (!Node)
2040b57cec5SDimitry Andric return;
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andric auto Printf = HSAMetadataDoc->getArrayNode();
207bdd1243dSDimitry Andric for (auto *Op : Node->operands())
2080b57cec5SDimitry Andric if (Op->getNumOperands())
2090b57cec5SDimitry Andric Printf.push_back(Printf.getDocument()->getNode(
2100b57cec5SDimitry Andric cast<MDString>(Op->getOperand(0))->getString(), /*Copy=*/true));
2110b57cec5SDimitry Andric getRootMetadata("amdhsa.printf") = Printf;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric
emitKernelLanguage(const Function & Func,msgpack::MapDocNode Kern)2145f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelLanguage(const Function &Func,
2150b57cec5SDimitry Andric msgpack::MapDocNode Kern) {
2160b57cec5SDimitry Andric // TODO: What about other languages?
2170b57cec5SDimitry Andric auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
2180b57cec5SDimitry Andric if (!Node || !Node->getNumOperands())
2190b57cec5SDimitry Andric return;
2200b57cec5SDimitry Andric auto Op0 = Node->getOperand(0);
2210b57cec5SDimitry Andric if (Op0->getNumOperands() <= 1)
2220b57cec5SDimitry Andric return;
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric Kern[".language"] = Kern.getDocument()->getNode("OpenCL C");
2250b57cec5SDimitry Andric auto LanguageVersion = Kern.getDocument()->getArrayNode();
2260b57cec5SDimitry Andric LanguageVersion.push_back(Kern.getDocument()->getNode(
2270b57cec5SDimitry Andric mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue()));
2280b57cec5SDimitry Andric LanguageVersion.push_back(Kern.getDocument()->getNode(
2290b57cec5SDimitry Andric mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue()));
2300b57cec5SDimitry Andric Kern[".language_version"] = LanguageVersion;
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric
emitKernelAttrs(const Function & Func,msgpack::MapDocNode Kern)2335f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelAttrs(const Function &Func,
2340b57cec5SDimitry Andric msgpack::MapDocNode Kern) {
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric if (auto Node = Func.getMetadata("reqd_work_group_size"))
2370b57cec5SDimitry Andric Kern[".reqd_workgroup_size"] = getWorkGroupDimensions(Node);
2380b57cec5SDimitry Andric if (auto Node = Func.getMetadata("work_group_size_hint"))
2390b57cec5SDimitry Andric Kern[".workgroup_size_hint"] = getWorkGroupDimensions(Node);
2400b57cec5SDimitry Andric if (auto Node = Func.getMetadata("vec_type_hint")) {
2410b57cec5SDimitry Andric Kern[".vec_type_hint"] = Kern.getDocument()->getNode(
2420b57cec5SDimitry Andric getTypeName(
2430b57cec5SDimitry Andric cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
2440b57cec5SDimitry Andric mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()),
2450b57cec5SDimitry Andric /*Copy=*/true);
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric if (Func.hasFnAttribute("runtime-handle")) {
2480b57cec5SDimitry Andric Kern[".device_enqueue_symbol"] = Kern.getDocument()->getNode(
2490b57cec5SDimitry Andric Func.getFnAttribute("runtime-handle").getValueAsString().str(),
2500b57cec5SDimitry Andric /*Copy=*/true);
2510b57cec5SDimitry Andric }
252349cc55cSDimitry Andric if (Func.hasFnAttribute("device-init"))
253349cc55cSDimitry Andric Kern[".kind"] = Kern.getDocument()->getNode("init");
254349cc55cSDimitry Andric else if (Func.hasFnAttribute("device-fini"))
255349cc55cSDimitry Andric Kern[".kind"] = Kern.getDocument()->getNode("fini");
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric
emitKernelArgs(const MachineFunction & MF,msgpack::MapDocNode Kern)2585f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArgs(const MachineFunction &MF,
2590b57cec5SDimitry Andric msgpack::MapDocNode Kern) {
2601fd87a68SDimitry Andric auto &Func = MF.getFunction();
2610b57cec5SDimitry Andric unsigned Offset = 0;
2620b57cec5SDimitry Andric auto Args = HSAMetadataDoc->getArrayNode();
2630b57cec5SDimitry Andric for (auto &Arg : Func.args())
2640b57cec5SDimitry Andric emitKernelArg(Arg, Offset, Args);
2650b57cec5SDimitry Andric
2661fd87a68SDimitry Andric emitHiddenKernelArgs(MF, Offset, Args);
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric Kern[".args"] = Args;
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric
emitKernelArg(const Argument & Arg,unsigned & Offset,msgpack::ArrayDocNode Args)2715f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArg(const Argument &Arg,
272bdd1243dSDimitry Andric unsigned &Offset,
2730b57cec5SDimitry Andric msgpack::ArrayDocNode Args) {
2740b57cec5SDimitry Andric auto Func = Arg.getParent();
2750b57cec5SDimitry Andric auto ArgNo = Arg.getArgNo();
2760b57cec5SDimitry Andric const MDNode *Node;
2770b57cec5SDimitry Andric
2780b57cec5SDimitry Andric StringRef Name;
2790b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_name");
2800b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
2810b57cec5SDimitry Andric Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
2820b57cec5SDimitry Andric else if (Arg.hasName())
2830b57cec5SDimitry Andric Name = Arg.getName();
2840b57cec5SDimitry Andric
2850b57cec5SDimitry Andric StringRef TypeName;
2860b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_type");
2870b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
2880b57cec5SDimitry Andric TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
2890b57cec5SDimitry Andric
2900b57cec5SDimitry Andric StringRef BaseTypeName;
2910b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_base_type");
2920b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
2930b57cec5SDimitry Andric BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
2940b57cec5SDimitry Andric
2955f757f3fSDimitry Andric StringRef ActAccQual;
2965f757f3fSDimitry Andric // Do we really need NoAlias check here?
2975f757f3fSDimitry Andric if (Arg.getType()->isPointerTy() && Arg.hasNoAliasAttr()) {
2985f757f3fSDimitry Andric if (Arg.onlyReadsMemory())
2995f757f3fSDimitry Andric ActAccQual = "read_only";
3005f757f3fSDimitry Andric else if (Arg.hasAttribute(Attribute::WriteOnly))
3015f757f3fSDimitry Andric ActAccQual = "write_only";
3025f757f3fSDimitry Andric }
3035f757f3fSDimitry Andric
3040b57cec5SDimitry Andric StringRef AccQual;
3050b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_access_qual");
3060b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3070b57cec5SDimitry Andric AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
3080b57cec5SDimitry Andric
3090b57cec5SDimitry Andric StringRef TypeQual;
3100b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_type_qual");
3110b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3120b57cec5SDimitry Andric TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
3130b57cec5SDimitry Andric
314*0fca6ea1SDimitry Andric const DataLayout &DL = Func->getDataLayout();
3150b57cec5SDimitry Andric
3165ffd83dbSDimitry Andric MaybeAlign PointeeAlign;
317e8d8bef9SDimitry Andric Type *Ty = Arg.hasByRefAttr() ? Arg.getParamByRefType() : Arg.getType();
318e8d8bef9SDimitry Andric
319e8d8bef9SDimitry Andric // FIXME: Need to distinguish in memory alignment from pointer alignment.
3200b57cec5SDimitry Andric if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
32104eeddc0SDimitry Andric if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS)
32204eeddc0SDimitry Andric PointeeAlign = Arg.getParamAlign().valueOrOne();
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric
325e8d8bef9SDimitry Andric // There's no distinction between byval aggregates and raw aggregates.
326e8d8bef9SDimitry Andric Type *ArgTy;
327e8d8bef9SDimitry Andric Align ArgAlign;
328e8d8bef9SDimitry Andric std::tie(ArgTy, ArgAlign) = getArgumentTypeAlign(Arg, DL);
329e8d8bef9SDimitry Andric
330e8d8bef9SDimitry Andric emitKernelArg(DL, ArgTy, ArgAlign,
331e8d8bef9SDimitry Andric getValueKind(ArgTy, TypeQual, BaseTypeName), Offset, Args,
3325f757f3fSDimitry Andric PointeeAlign, Name, TypeName, BaseTypeName, ActAccQual,
3335f757f3fSDimitry Andric AccQual, TypeQual);
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry 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)3365f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArg(
337e8d8bef9SDimitry Andric const DataLayout &DL, Type *Ty, Align Alignment, StringRef ValueKind,
338e8d8bef9SDimitry Andric unsigned &Offset, msgpack::ArrayDocNode Args, MaybeAlign PointeeAlign,
339e8d8bef9SDimitry Andric StringRef Name, StringRef TypeName, StringRef BaseTypeName,
3405f757f3fSDimitry Andric StringRef ActAccQual, StringRef AccQual, StringRef TypeQual) {
3410b57cec5SDimitry Andric auto Arg = Args.getDocument()->getMapNode();
3420b57cec5SDimitry Andric
3430b57cec5SDimitry Andric if (!Name.empty())
3440b57cec5SDimitry Andric Arg[".name"] = Arg.getDocument()->getNode(Name, /*Copy=*/true);
3450b57cec5SDimitry Andric if (!TypeName.empty())
3460b57cec5SDimitry Andric Arg[".type_name"] = Arg.getDocument()->getNode(TypeName, /*Copy=*/true);
3470b57cec5SDimitry Andric auto Size = DL.getTypeAllocSize(Ty);
3480b57cec5SDimitry Andric Arg[".size"] = Arg.getDocument()->getNode(Size);
3495ffd83dbSDimitry Andric Offset = alignTo(Offset, Alignment);
3500b57cec5SDimitry Andric Arg[".offset"] = Arg.getDocument()->getNode(Offset);
3510b57cec5SDimitry Andric Offset += Size;
3520b57cec5SDimitry Andric Arg[".value_kind"] = Arg.getDocument()->getNode(ValueKind, /*Copy=*/true);
3530b57cec5SDimitry Andric if (PointeeAlign)
3545ffd83dbSDimitry Andric Arg[".pointee_align"] = Arg.getDocument()->getNode(PointeeAlign->value());
3550b57cec5SDimitry Andric
3560b57cec5SDimitry Andric if (auto PtrTy = dyn_cast<PointerType>(Ty))
3570b57cec5SDimitry Andric if (auto Qualifier = getAddressSpaceQualifier(PtrTy->getAddressSpace()))
358bdd1243dSDimitry Andric // Limiting address space to emit only for a certain ValueKind.
359bdd1243dSDimitry Andric if (ValueKind == "global_buffer" || ValueKind == "dynamic_shared_pointer")
360bdd1243dSDimitry Andric Arg[".address_space"] = Arg.getDocument()->getNode(*Qualifier,
361bdd1243dSDimitry Andric /*Copy=*/true);
3620b57cec5SDimitry Andric
3630b57cec5SDimitry Andric if (auto AQ = getAccessQualifier(AccQual))
3640b57cec5SDimitry Andric Arg[".access"] = Arg.getDocument()->getNode(*AQ, /*Copy=*/true);
3650b57cec5SDimitry Andric
3665f757f3fSDimitry Andric if (auto AAQ = getAccessQualifier(ActAccQual))
3675f757f3fSDimitry Andric Arg[".actual_access"] = Arg.getDocument()->getNode(*AAQ, /*Copy=*/true);
3680b57cec5SDimitry Andric
3690b57cec5SDimitry Andric SmallVector<StringRef, 1> SplitTypeQuals;
3700b57cec5SDimitry Andric TypeQual.split(SplitTypeQuals, " ", -1, false);
3710b57cec5SDimitry Andric for (StringRef Key : SplitTypeQuals) {
3720b57cec5SDimitry Andric if (Key == "const")
3730b57cec5SDimitry Andric Arg[".is_const"] = Arg.getDocument()->getNode(true);
3740b57cec5SDimitry Andric else if (Key == "restrict")
3750b57cec5SDimitry Andric Arg[".is_restrict"] = Arg.getDocument()->getNode(true);
3760b57cec5SDimitry Andric else if (Key == "volatile")
3770b57cec5SDimitry Andric Arg[".is_volatile"] = Arg.getDocument()->getNode(true);
3780b57cec5SDimitry Andric else if (Key == "pipe")
3790b57cec5SDimitry Andric Arg[".is_pipe"] = Arg.getDocument()->getNode(true);
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric
3820b57cec5SDimitry Andric Args.push_back(Arg);
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric
emitHiddenKernelArgs(const MachineFunction & MF,unsigned & Offset,msgpack::ArrayDocNode Args)3855f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitHiddenKernelArgs(
386bdd1243dSDimitry Andric const MachineFunction &MF, unsigned &Offset, msgpack::ArrayDocNode Args) {
3871fd87a68SDimitry Andric auto &Func = MF.getFunction();
3881fd87a68SDimitry Andric const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3891fd87a68SDimitry Andric
3900eae32dcSDimitry Andric unsigned HiddenArgNumBytes = ST.getImplicitArgNumBytes(Func);
3910b57cec5SDimitry Andric if (!HiddenArgNumBytes)
3920b57cec5SDimitry Andric return;
3930b57cec5SDimitry Andric
394349cc55cSDimitry Andric const Module *M = Func.getParent();
395349cc55cSDimitry Andric auto &DL = M->getDataLayout();
3960b57cec5SDimitry Andric auto Int64Ty = Type::getInt64Ty(Func.getContext());
3970b57cec5SDimitry Andric
39881ad6265SDimitry Andric Offset = alignTo(Offset, ST.getAlignmentForImplicitArgPtr());
39981ad6265SDimitry Andric
4000b57cec5SDimitry Andric if (HiddenArgNumBytes >= 8)
401e8d8bef9SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset,
402e8d8bef9SDimitry Andric Args);
4030b57cec5SDimitry Andric if (HiddenArgNumBytes >= 16)
404e8d8bef9SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset,
405e8d8bef9SDimitry Andric Args);
4060b57cec5SDimitry Andric if (HiddenArgNumBytes >= 24)
407e8d8bef9SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset,
408e8d8bef9SDimitry Andric Args);
4090b57cec5SDimitry Andric
4100b57cec5SDimitry Andric auto Int8PtrTy =
4115f757f3fSDimitry Andric PointerType::get(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
4120b57cec5SDimitry Andric
4130b57cec5SDimitry Andric if (HiddenArgNumBytes >= 32) {
41481ad6265SDimitry Andric // We forbid the use of features requiring hostcall when compiling OpenCL
41581ad6265SDimitry Andric // before code object V5, which makes the mutual exclusion between the
41681ad6265SDimitry Andric // "printf buffer" and "hostcall buffer" here sound.
417349cc55cSDimitry Andric if (M->getNamedMetadata("llvm.printf.fmts"))
418e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
419e8d8bef9SDimitry Andric Args);
42081ad6265SDimitry Andric else if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr"))
421e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
422e8d8bef9SDimitry Andric Args);
42381ad6265SDimitry Andric else
424e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
4250b57cec5SDimitry Andric }
4260b57cec5SDimitry Andric
4270b57cec5SDimitry Andric // Emit "default queue" and "completion action" arguments if enqueue kernel is
4280b57cec5SDimitry Andric // used, otherwise emit dummy "none" arguments.
429bdd1243dSDimitry Andric if (HiddenArgNumBytes >= 40) {
430bdd1243dSDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-default-queue")) {
431e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
432e8d8bef9SDimitry Andric Args);
4330b57cec5SDimitry Andric } else {
434e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
435bdd1243dSDimitry Andric }
436bdd1243dSDimitry Andric }
437bdd1243dSDimitry Andric
438bdd1243dSDimitry Andric if (HiddenArgNumBytes >= 48) {
43906c3fb27SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-completion-action")) {
440bdd1243dSDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
441bdd1243dSDimitry Andric Args);
442bdd1243dSDimitry Andric } else {
443e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric }
4460b57cec5SDimitry Andric
4470b57cec5SDimitry Andric // Emit the pointer argument for multi-grid object.
44881ad6265SDimitry Andric if (HiddenArgNumBytes >= 56) {
44981ad6265SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-multigrid-sync-arg")) {
450e8d8bef9SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
451e8d8bef9SDimitry Andric Args);
45281ad6265SDimitry Andric } else {
45381ad6265SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
45481ad6265SDimitry Andric }
45581ad6265SDimitry Andric }
4560b57cec5SDimitry Andric }
4570b57cec5SDimitry Andric
4585f757f3fSDimitry Andric msgpack::MapDocNode
getHSAKernelProps(const MachineFunction & MF,const SIProgramInfo & ProgramInfo,unsigned CodeObjectVersion) const4595f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getHSAKernelProps(const MachineFunction &MF,
4605f757f3fSDimitry Andric const SIProgramInfo &ProgramInfo,
46106c3fb27SDimitry Andric unsigned CodeObjectVersion) const {
4620b57cec5SDimitry Andric const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
4630b57cec5SDimitry Andric const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
4640b57cec5SDimitry Andric const Function &F = MF.getFunction();
4650b57cec5SDimitry Andric
4660b57cec5SDimitry Andric auto Kern = HSAMetadataDoc->getMapNode();
4670b57cec5SDimitry Andric
4688bcb0991SDimitry Andric Align MaxKernArgAlign;
4690b57cec5SDimitry Andric Kern[".kernarg_segment_size"] = Kern.getDocument()->getNode(
4700b57cec5SDimitry Andric STM.getKernArgSegmentSize(F, MaxKernArgAlign));
4710b57cec5SDimitry Andric Kern[".group_segment_fixed_size"] =
4720b57cec5SDimitry Andric Kern.getDocument()->getNode(ProgramInfo.LDSSize);
473*0fca6ea1SDimitry Andric DelayedExprs->assignDocNode(Kern[".private_segment_fixed_size"],
474*0fca6ea1SDimitry Andric msgpack::Type::UInt, ProgramInfo.ScratchSize);
475*0fca6ea1SDimitry Andric if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5) {
476*0fca6ea1SDimitry Andric DelayedExprs->assignDocNode(Kern[".uses_dynamic_stack"],
477*0fca6ea1SDimitry Andric msgpack::Type::Boolean,
478*0fca6ea1SDimitry Andric ProgramInfo.DynamicCallStack);
479*0fca6ea1SDimitry Andric }
48006c3fb27SDimitry Andric
48106c3fb27SDimitry Andric if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5 && STM.supportsWGP())
482bdd1243dSDimitry Andric Kern[".workgroup_processor_mode"] =
483bdd1243dSDimitry Andric Kern.getDocument()->getNode(ProgramInfo.WgpMode);
484349cc55cSDimitry Andric
485349cc55cSDimitry Andric // FIXME: The metadata treats the minimum as 16?
4860b57cec5SDimitry Andric Kern[".kernarg_segment_align"] =
4878bcb0991SDimitry Andric Kern.getDocument()->getNode(std::max(Align(4), MaxKernArgAlign).value());
4880b57cec5SDimitry Andric Kern[".wavefront_size"] =
4890b57cec5SDimitry Andric Kern.getDocument()->getNode(STM.getWavefrontSize());
490*0fca6ea1SDimitry Andric DelayedExprs->assignDocNode(Kern[".sgpr_count"], msgpack::Type::UInt,
491*0fca6ea1SDimitry Andric ProgramInfo.NumSGPR);
492*0fca6ea1SDimitry Andric DelayedExprs->assignDocNode(Kern[".vgpr_count"], msgpack::Type::UInt,
493*0fca6ea1SDimitry Andric ProgramInfo.NumVGPR);
49481ad6265SDimitry Andric
49581ad6265SDimitry Andric // Only add AGPR count to metadata for supported devices
49681ad6265SDimitry Andric if (STM.hasMAIInsts()) {
497*0fca6ea1SDimitry Andric DelayedExprs->assignDocNode(Kern[".agpr_count"], msgpack::Type::UInt,
498*0fca6ea1SDimitry Andric ProgramInfo.NumAccVGPR);
49981ad6265SDimitry Andric }
50081ad6265SDimitry Andric
5010b57cec5SDimitry Andric Kern[".max_flat_workgroup_size"] =
5020b57cec5SDimitry Andric Kern.getDocument()->getNode(MFI.getMaxFlatWorkGroupSize());
503*0fca6ea1SDimitry Andric unsigned NumWGX = MFI.getMaxNumWorkGroupsX();
504*0fca6ea1SDimitry Andric unsigned NumWGY = MFI.getMaxNumWorkGroupsY();
505*0fca6ea1SDimitry Andric unsigned NumWGZ = MFI.getMaxNumWorkGroupsZ();
506*0fca6ea1SDimitry Andric if (NumWGX != 0 && NumWGY != 0 && NumWGZ != 0) {
507*0fca6ea1SDimitry Andric Kern[".max_num_workgroups_x"] = Kern.getDocument()->getNode(NumWGX);
508*0fca6ea1SDimitry Andric Kern[".max_num_workgroups_y"] = Kern.getDocument()->getNode(NumWGY);
509*0fca6ea1SDimitry Andric Kern[".max_num_workgroups_z"] = Kern.getDocument()->getNode(NumWGZ);
510*0fca6ea1SDimitry Andric }
5110b57cec5SDimitry Andric Kern[".sgpr_spill_count"] =
5120b57cec5SDimitry Andric Kern.getDocument()->getNode(MFI.getNumSpilledSGPRs());
5130b57cec5SDimitry Andric Kern[".vgpr_spill_count"] =
5140b57cec5SDimitry Andric Kern.getDocument()->getNode(MFI.getNumSpilledVGPRs());
5150b57cec5SDimitry Andric
5160b57cec5SDimitry Andric return Kern;
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric
emitTo(AMDGPUTargetStreamer & TargetStreamer)5195f757f3fSDimitry Andric bool MetadataStreamerMsgPackV4::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
520*0fca6ea1SDimitry Andric DelayedExprs->resolveDelayedExpressions();
5210b57cec5SDimitry Andric return TargetStreamer.EmitHSAMetadata(*HSAMetadataDoc, true);
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric
begin(const Module & Mod,const IsaInfo::AMDGPUTargetID & TargetID)5245f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::begin(const Module &Mod,
525fe6060f1SDimitry Andric const IsaInfo::AMDGPUTargetID &TargetID) {
5260b57cec5SDimitry Andric emitVersion();
5275f757f3fSDimitry Andric emitTargetID(TargetID);
5280b57cec5SDimitry Andric emitPrintf(Mod);
5290b57cec5SDimitry Andric getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode();
530*0fca6ea1SDimitry Andric DelayedExprs->clear();
5310b57cec5SDimitry Andric }
5320b57cec5SDimitry Andric
end()5335f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::end() {
534*0fca6ea1SDimitry Andric DelayedExprs->resolveDelayedExpressions();
5350b57cec5SDimitry Andric std::string HSAMetadataString;
5360b57cec5SDimitry Andric raw_string_ostream StrOS(HSAMetadataString);
5370b57cec5SDimitry Andric HSAMetadataDoc->toYAML(StrOS);
5380b57cec5SDimitry Andric
5390b57cec5SDimitry Andric if (DumpHSAMetadata)
5400b57cec5SDimitry Andric dump(StrOS.str());
5410b57cec5SDimitry Andric if (VerifyHSAMetadata)
5420b57cec5SDimitry Andric verify(StrOS.str());
5430b57cec5SDimitry Andric }
5440b57cec5SDimitry Andric
emitKernel(const MachineFunction & MF,const SIProgramInfo & ProgramInfo)5455f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernel(const MachineFunction &MF,
5460b57cec5SDimitry Andric const SIProgramInfo &ProgramInfo) {
5470b57cec5SDimitry Andric auto &Func = MF.getFunction();
54806c3fb27SDimitry Andric if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL &&
54906c3fb27SDimitry Andric Func.getCallingConv() != CallingConv::SPIR_KERNEL)
55006c3fb27SDimitry Andric return;
5510b57cec5SDimitry Andric
5527a6dacacSDimitry Andric auto CodeObjectVersion =
5537a6dacacSDimitry Andric AMDGPU::getAMDHSACodeObjectVersion(*Func.getParent());
55406c3fb27SDimitry Andric auto Kern = getHSAKernelProps(MF, ProgramInfo, CodeObjectVersion);
5550b57cec5SDimitry Andric
5560b57cec5SDimitry Andric auto Kernels =
5570b57cec5SDimitry Andric getRootMetadata("amdhsa.kernels").getArray(/*Convert=*/true);
5580b57cec5SDimitry Andric
5590b57cec5SDimitry Andric {
5600b57cec5SDimitry Andric Kern[".name"] = Kern.getDocument()->getNode(Func.getName());
5610b57cec5SDimitry Andric Kern[".symbol"] = Kern.getDocument()->getNode(
5620b57cec5SDimitry Andric (Twine(Func.getName()) + Twine(".kd")).str(), /*Copy=*/true);
5630b57cec5SDimitry Andric emitKernelLanguage(Func, Kern);
5640b57cec5SDimitry Andric emitKernelAttrs(Func, Kern);
5651fd87a68SDimitry Andric emitKernelArgs(MF, Kern);
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric
5680b57cec5SDimitry Andric Kernels.push_back(Kern);
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric
571fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
5721fd87a68SDimitry Andric // HSAMetadataStreamerV5
5731fd87a68SDimitry Andric //===----------------------------------------------------------------------===//
5741fd87a68SDimitry Andric
emitVersion()575bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitVersion() {
5761fd87a68SDimitry Andric auto Version = HSAMetadataDoc->getArrayNode();
5771fd87a68SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMajorV5));
5781fd87a68SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMinorV5));
5791fd87a68SDimitry Andric getRootMetadata("amdhsa.version") = Version;
5801fd87a68SDimitry Andric }
5811fd87a68SDimitry Andric
emitHiddenKernelArgs(const MachineFunction & MF,unsigned & Offset,msgpack::ArrayDocNode Args)582bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitHiddenKernelArgs(
583bdd1243dSDimitry Andric const MachineFunction &MF, unsigned &Offset, msgpack::ArrayDocNode Args) {
5841fd87a68SDimitry Andric auto &Func = MF.getFunction();
5851fd87a68SDimitry Andric const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
58681ad6265SDimitry Andric
58781ad6265SDimitry Andric // No implicit kernel argument is used.
58881ad6265SDimitry Andric if (ST.getImplicitArgNumBytes(Func) == 0)
58981ad6265SDimitry Andric return;
59081ad6265SDimitry Andric
5911fd87a68SDimitry Andric const Module *M = Func.getParent();
5921fd87a68SDimitry Andric auto &DL = M->getDataLayout();
59381ad6265SDimitry Andric const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
5941fd87a68SDimitry Andric
5951fd87a68SDimitry Andric auto Int64Ty = Type::getInt64Ty(Func.getContext());
5961fd87a68SDimitry Andric auto Int32Ty = Type::getInt32Ty(Func.getContext());
5971fd87a68SDimitry Andric auto Int16Ty = Type::getInt16Ty(Func.getContext());
5981fd87a68SDimitry Andric
59981ad6265SDimitry Andric Offset = alignTo(Offset, ST.getAlignmentForImplicitArgPtr());
6001fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_x", Offset, Args);
6011fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_y", Offset, Args);
6021fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_z", Offset, Args);
6031fd87a68SDimitry Andric
6041fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_x", Offset, Args);
6051fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_y", Offset, Args);
6061fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_z", Offset, Args);
6071fd87a68SDimitry Andric
6081fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_x", Offset, Args);
6091fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_y", Offset, Args);
6101fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_z", Offset, Args);
6111fd87a68SDimitry Andric
6121fd87a68SDimitry Andric // Reserved for hidden_tool_correlation_id.
6131fd87a68SDimitry Andric Offset += 8;
6141fd87a68SDimitry Andric
6151fd87a68SDimitry Andric Offset += 8; // Reserved.
6161fd87a68SDimitry Andric
6171fd87a68SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset, Args);
6181fd87a68SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset, Args);
6191fd87a68SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset, Args);
6201fd87a68SDimitry Andric
6211fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_grid_dims", Offset, Args);
6221fd87a68SDimitry Andric
6231fd87a68SDimitry Andric Offset += 6; // Reserved.
6241fd87a68SDimitry Andric auto Int8PtrTy =
6255f757f3fSDimitry Andric PointerType::get(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
6261fd87a68SDimitry Andric
6271fd87a68SDimitry Andric if (M->getNamedMetadata("llvm.printf.fmts")) {
6281fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
6291fd87a68SDimitry Andric Args);
63081ad6265SDimitry Andric } else {
6311fd87a68SDimitry Andric Offset += 8; // Skipped.
63281ad6265SDimitry Andric }
6331fd87a68SDimitry Andric
63481ad6265SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr")) {
6351fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
6361fd87a68SDimitry Andric Args);
63781ad6265SDimitry Andric } else {
6381fd87a68SDimitry Andric Offset += 8; // Skipped.
63981ad6265SDimitry Andric }
6401fd87a68SDimitry Andric
64181ad6265SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-multigrid-sync-arg")) {
6421fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
6431fd87a68SDimitry Andric Args);
64481ad6265SDimitry Andric } else {
64581ad6265SDimitry Andric Offset += 8; // Skipped.
64681ad6265SDimitry Andric }
6471fd87a68SDimitry Andric
64881ad6265SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-heap-ptr"))
64981ad6265SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_heap_v1", Offset, Args);
65081ad6265SDimitry Andric else
65181ad6265SDimitry Andric Offset += 8; // Skipped.
6521fd87a68SDimitry Andric
653bdd1243dSDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-default-queue")) {
6541fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
6551fd87a68SDimitry Andric Args);
656bdd1243dSDimitry Andric } else {
657bdd1243dSDimitry Andric Offset += 8; // Skipped.
658bdd1243dSDimitry Andric }
659bdd1243dSDimitry Andric
66006c3fb27SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-completion-action")) {
6611fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
6621fd87a68SDimitry Andric Args);
66381ad6265SDimitry Andric } else {
664bdd1243dSDimitry Andric Offset += 8; // Skipped.
66581ad6265SDimitry Andric }
6661fd87a68SDimitry Andric
6671db9f3b2SDimitry Andric // Emit argument for hidden dynamic lds size
6681db9f3b2SDimitry Andric if (MFI.isDynamicLDSUsed()) {
6691db9f3b2SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_dynamic_lds_size", Offset,
6701db9f3b2SDimitry Andric Args);
6711db9f3b2SDimitry Andric } else {
6721db9f3b2SDimitry Andric Offset += 4; // skipped
6731db9f3b2SDimitry Andric }
6741db9f3b2SDimitry Andric
6751db9f3b2SDimitry Andric Offset += 68; // Reserved.
6761fd87a68SDimitry Andric
67781ad6265SDimitry Andric // hidden_private_base and hidden_shared_base are only when the subtarget has
67881ad6265SDimitry Andric // ApertureRegs.
67981ad6265SDimitry Andric if (!ST.hasApertureRegs()) {
6801fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_private_base", Offset, Args);
6811fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_shared_base", Offset, Args);
68281ad6265SDimitry Andric } else {
6831fd87a68SDimitry Andric Offset += 8; // Skipped.
68481ad6265SDimitry Andric }
6851fd87a68SDimitry Andric
6865f757f3fSDimitry Andric if (MFI.getUserSGPRInfo().hasQueuePtr())
6871fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_queue_ptr", Offset, Args);
6881fd87a68SDimitry Andric }
6891fd87a68SDimitry Andric
emitKernelAttrs(const Function & Func,msgpack::MapDocNode Kern)690bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitKernelAttrs(const Function &Func,
691bdd1243dSDimitry Andric msgpack::MapDocNode Kern) {
6925f757f3fSDimitry Andric MetadataStreamerMsgPackV4::emitKernelAttrs(Func, Kern);
693bdd1243dSDimitry Andric
694bdd1243dSDimitry Andric if (Func.getFnAttribute("uniform-work-group-size").getValueAsBool())
695bdd1243dSDimitry Andric Kern[".uniform_work_group_size"] = Kern.getDocument()->getNode(1);
696bdd1243dSDimitry Andric }
697bdd1243dSDimitry Andric
698*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
699*0fca6ea1SDimitry Andric // HSAMetadataStreamerV6
700*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
701bdd1243dSDimitry Andric
emitVersion()702*0fca6ea1SDimitry Andric void MetadataStreamerMsgPackV6::emitVersion() {
703*0fca6ea1SDimitry Andric auto Version = HSAMetadataDoc->getArrayNode();
704*0fca6ea1SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMajorV6));
705*0fca6ea1SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMinorV6));
706*0fca6ea1SDimitry Andric getRootMetadata("amdhsa.version") = Version;
707*0fca6ea1SDimitry Andric }
708*0fca6ea1SDimitry Andric
709*0fca6ea1SDimitry Andric } // end namespace AMDGPU::HSAMD
7100b57cec5SDimitry Andric } // end namespace llvm
711