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 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 //===----------------------------------------------------------------------===// 525f757f3fSDimitry Andric // HSAMetadataStreamerV4 530b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 545f757f3fSDimitry Andric 555f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::dump(StringRef HSAMetadataString) const { 560b57cec5SDimitry Andric errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n'; 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 595f757f3fSDimitry 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> 815f757f3fSDimitry 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 895f757f3fSDimitry 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 1105f757f3fSDimitry 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 1375f757f3fSDimitry 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 1765f757f3fSDimitry 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 1875f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitVersion() { 1880b57cec5SDimitry Andric auto Version = HSAMetadataDoc->getArrayNode(); 1895f757f3fSDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMajorV4)); 1905f757f3fSDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMinorV4)); 1910b57cec5SDimitry Andric getRootMetadata("amdhsa.version") = Version; 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1945f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitTargetID( 1955f757f3fSDimitry Andric const IsaInfo::AMDGPUTargetID &TargetID) { 1965f757f3fSDimitry Andric getRootMetadata("amdhsa.target") = 1975f757f3fSDimitry Andric HSAMetadataDoc->getNode(TargetID.toString(), /*Copy=*/true); 1985f757f3fSDimitry Andric } 1995f757f3fSDimitry Andric 2005f757f3fSDimitry 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 2135f757f3fSDimitry 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 2325f757f3fSDimitry 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 2575f757f3fSDimitry 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 2705f757f3fSDimitry 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 2945f757f3fSDimitry Andric StringRef ActAccQual; 2955f757f3fSDimitry Andric // Do we really need NoAlias check here? 2965f757f3fSDimitry Andric if (Arg.getType()->isPointerTy() && Arg.hasNoAliasAttr()) { 2975f757f3fSDimitry Andric if (Arg.onlyReadsMemory()) 2985f757f3fSDimitry Andric ActAccQual = "read_only"; 2995f757f3fSDimitry Andric else if (Arg.hasAttribute(Attribute::WriteOnly)) 3005f757f3fSDimitry Andric ActAccQual = "write_only"; 3015f757f3fSDimitry Andric } 3025f757f3fSDimitry 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, 3315f757f3fSDimitry Andric PointeeAlign, Name, TypeName, BaseTypeName, ActAccQual, 3325f757f3fSDimitry Andric AccQual, TypeQual); 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3355f757f3fSDimitry 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, 3395f757f3fSDimitry 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 3655f757f3fSDimitry Andric if (auto AAQ = getAccessQualifier(ActAccQual)) 3665f757f3fSDimitry 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 3845f757f3fSDimitry 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 = 4105f757f3fSDimitry 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) { 43806c3fb27SDimitry 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 4575f757f3fSDimitry Andric msgpack::MapDocNode 4585f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getHSAKernelProps(const MachineFunction &MF, 4595f757f3fSDimitry Andric const SIProgramInfo &ProgramInfo, 46006c3fb27SDimitry 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); 47406c3fb27SDimitry Andric if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5) 475fcaf7f86SDimitry Andric Kern[".uses_dynamic_stack"] = 476fcaf7f86SDimitry Andric Kern.getDocument()->getNode(ProgramInfo.DynamicCallStack); 47706c3fb27SDimitry Andric 47806c3fb27SDimitry 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 5055f757f3fSDimitry Andric bool MetadataStreamerMsgPackV4::emitTo(AMDGPUTargetStreamer &TargetStreamer) { 5060b57cec5SDimitry Andric return TargetStreamer.EmitHSAMetadata(*HSAMetadataDoc, true); 5070b57cec5SDimitry Andric } 5080b57cec5SDimitry Andric 5095f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::begin(const Module &Mod, 510fe6060f1SDimitry Andric const IsaInfo::AMDGPUTargetID &TargetID) { 5110b57cec5SDimitry Andric emitVersion(); 5125f757f3fSDimitry Andric emitTargetID(TargetID); 5130b57cec5SDimitry Andric emitPrintf(Mod); 5140b57cec5SDimitry Andric getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode(); 5150b57cec5SDimitry Andric } 5160b57cec5SDimitry Andric 5175f757f3fSDimitry 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 5285f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernel(const MachineFunction &MF, 5290b57cec5SDimitry Andric const SIProgramInfo &ProgramInfo) { 5300b57cec5SDimitry Andric auto &Func = MF.getFunction(); 53106c3fb27SDimitry Andric if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL && 53206c3fb27SDimitry Andric Func.getCallingConv() != CallingConv::SPIR_KERNEL) 53306c3fb27SDimitry Andric return; 5340b57cec5SDimitry Andric 53506c3fb27SDimitry Andric auto CodeObjectVersion = AMDGPU::getCodeObjectVersion(*Func.getParent()); 53606c3fb27SDimitry Andric auto Kern = getHSAKernelProps(MF, ProgramInfo, CodeObjectVersion); 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric auto Kernels = 5390b57cec5SDimitry Andric getRootMetadata("amdhsa.kernels").getArray(/*Convert=*/true); 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric { 5420b57cec5SDimitry Andric Kern[".name"] = Kern.getDocument()->getNode(Func.getName()); 5430b57cec5SDimitry Andric Kern[".symbol"] = Kern.getDocument()->getNode( 5440b57cec5SDimitry Andric (Twine(Func.getName()) + Twine(".kd")).str(), /*Copy=*/true); 5450b57cec5SDimitry Andric emitKernelLanguage(Func, Kern); 5460b57cec5SDimitry Andric emitKernelAttrs(Func, Kern); 5471fd87a68SDimitry Andric emitKernelArgs(MF, Kern); 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric Kernels.push_back(Kern); 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric 553fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 5541fd87a68SDimitry Andric // HSAMetadataStreamerV5 5551fd87a68SDimitry Andric //===----------------------------------------------------------------------===// 5561fd87a68SDimitry Andric 557bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitVersion() { 5581fd87a68SDimitry Andric auto Version = HSAMetadataDoc->getArrayNode(); 5591fd87a68SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMajorV5)); 5601fd87a68SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMinorV5)); 5611fd87a68SDimitry Andric getRootMetadata("amdhsa.version") = Version; 5621fd87a68SDimitry Andric } 5631fd87a68SDimitry Andric 564bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitHiddenKernelArgs( 565bdd1243dSDimitry Andric const MachineFunction &MF, unsigned &Offset, msgpack::ArrayDocNode Args) { 5661fd87a68SDimitry Andric auto &Func = MF.getFunction(); 5671fd87a68SDimitry Andric const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); 56881ad6265SDimitry Andric 56981ad6265SDimitry Andric // No implicit kernel argument is used. 57081ad6265SDimitry Andric if (ST.getImplicitArgNumBytes(Func) == 0) 57181ad6265SDimitry Andric return; 57281ad6265SDimitry Andric 5731fd87a68SDimitry Andric const Module *M = Func.getParent(); 5741fd87a68SDimitry Andric auto &DL = M->getDataLayout(); 57581ad6265SDimitry Andric const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>(); 5761fd87a68SDimitry Andric 5771fd87a68SDimitry Andric auto Int64Ty = Type::getInt64Ty(Func.getContext()); 5781fd87a68SDimitry Andric auto Int32Ty = Type::getInt32Ty(Func.getContext()); 5791fd87a68SDimitry Andric auto Int16Ty = Type::getInt16Ty(Func.getContext()); 5801fd87a68SDimitry Andric 58181ad6265SDimitry Andric Offset = alignTo(Offset, ST.getAlignmentForImplicitArgPtr()); 5821fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_x", Offset, Args); 5831fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_y", Offset, Args); 5841fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_z", Offset, Args); 5851fd87a68SDimitry Andric 5861fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_x", Offset, Args); 5871fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_y", Offset, Args); 5881fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_z", Offset, Args); 5891fd87a68SDimitry Andric 5901fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_x", Offset, Args); 5911fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_y", Offset, Args); 5921fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_z", Offset, Args); 5931fd87a68SDimitry Andric 5941fd87a68SDimitry Andric // Reserved for hidden_tool_correlation_id. 5951fd87a68SDimitry Andric Offset += 8; 5961fd87a68SDimitry Andric 5971fd87a68SDimitry Andric Offset += 8; // Reserved. 5981fd87a68SDimitry Andric 5991fd87a68SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset, Args); 6001fd87a68SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset, Args); 6011fd87a68SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset, Args); 6021fd87a68SDimitry Andric 6031fd87a68SDimitry Andric emitKernelArg(DL, Int16Ty, Align(2), "hidden_grid_dims", Offset, Args); 6041fd87a68SDimitry Andric 6051fd87a68SDimitry Andric Offset += 6; // Reserved. 6061fd87a68SDimitry Andric auto Int8PtrTy = 6075f757f3fSDimitry Andric PointerType::get(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS); 6081fd87a68SDimitry Andric 6091fd87a68SDimitry Andric if (M->getNamedMetadata("llvm.printf.fmts")) { 6101fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset, 6111fd87a68SDimitry Andric Args); 61281ad6265SDimitry Andric } else { 6131fd87a68SDimitry Andric Offset += 8; // Skipped. 61481ad6265SDimitry Andric } 6151fd87a68SDimitry Andric 61681ad6265SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr")) { 6171fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset, 6181fd87a68SDimitry Andric Args); 61981ad6265SDimitry Andric } else { 6201fd87a68SDimitry Andric Offset += 8; // Skipped. 62181ad6265SDimitry Andric } 6221fd87a68SDimitry Andric 62381ad6265SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-multigrid-sync-arg")) { 6241fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset, 6251fd87a68SDimitry Andric Args); 62681ad6265SDimitry Andric } else { 62781ad6265SDimitry Andric Offset += 8; // Skipped. 62881ad6265SDimitry Andric } 6291fd87a68SDimitry Andric 63081ad6265SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-heap-ptr")) 63181ad6265SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_heap_v1", Offset, Args); 63281ad6265SDimitry Andric else 63381ad6265SDimitry Andric Offset += 8; // Skipped. 6341fd87a68SDimitry Andric 635bdd1243dSDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-default-queue")) { 6361fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset, 6371fd87a68SDimitry Andric Args); 638bdd1243dSDimitry Andric } else { 639bdd1243dSDimitry Andric Offset += 8; // Skipped. 640bdd1243dSDimitry Andric } 641bdd1243dSDimitry Andric 64206c3fb27SDimitry Andric if (!Func.hasFnAttribute("amdgpu-no-completion-action")) { 6431fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset, 6441fd87a68SDimitry Andric Args); 64581ad6265SDimitry Andric } else { 646bdd1243dSDimitry Andric Offset += 8; // Skipped. 64781ad6265SDimitry Andric } 6481fd87a68SDimitry Andric 649*1db9f3b2SDimitry Andric // Emit argument for hidden dynamic lds size 650*1db9f3b2SDimitry Andric if (MFI.isDynamicLDSUsed()) { 651*1db9f3b2SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_dynamic_lds_size", Offset, 652*1db9f3b2SDimitry Andric Args); 653*1db9f3b2SDimitry Andric } else { 654*1db9f3b2SDimitry Andric Offset += 4; // skipped 655*1db9f3b2SDimitry Andric } 656*1db9f3b2SDimitry Andric 657*1db9f3b2SDimitry Andric Offset += 68; // Reserved. 6581fd87a68SDimitry Andric 65981ad6265SDimitry Andric // hidden_private_base and hidden_shared_base are only when the subtarget has 66081ad6265SDimitry Andric // ApertureRegs. 66181ad6265SDimitry Andric if (!ST.hasApertureRegs()) { 6621fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_private_base", Offset, Args); 6631fd87a68SDimitry Andric emitKernelArg(DL, Int32Ty, Align(4), "hidden_shared_base", Offset, Args); 66481ad6265SDimitry Andric } else { 6651fd87a68SDimitry Andric Offset += 8; // Skipped. 66681ad6265SDimitry Andric } 6671fd87a68SDimitry Andric 6685f757f3fSDimitry Andric if (MFI.getUserSGPRInfo().hasQueuePtr()) 6691fd87a68SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_queue_ptr", Offset, Args); 6701fd87a68SDimitry Andric } 6711fd87a68SDimitry Andric 672bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitKernelAttrs(const Function &Func, 673bdd1243dSDimitry Andric msgpack::MapDocNode Kern) { 6745f757f3fSDimitry Andric MetadataStreamerMsgPackV4::emitKernelAttrs(Func, Kern); 675bdd1243dSDimitry Andric 676bdd1243dSDimitry Andric if (Func.getFnAttribute("uniform-work-group-size").getValueAsBool()) 677bdd1243dSDimitry Andric Kern[".uniform_work_group_size"] = Kern.getDocument()->getNode(1); 678bdd1243dSDimitry Andric } 679bdd1243dSDimitry Andric 680bdd1243dSDimitry Andric 6810b57cec5SDimitry Andric } // end namespace HSAMD 6820b57cec5SDimitry Andric } // end namespace AMDGPU 6830b57cec5SDimitry Andric } // end namespace llvm 684