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 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 565f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::dump(StringRef HSAMetadataString) const { 570b57cec5SDimitry Andric errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n'; 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 605f757f3fSDimitry 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> 825f757f3fSDimitry 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 905f757f3fSDimitry 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 1115f757f3fSDimitry 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 1385f757f3fSDimitry 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 1775f757f3fSDimitry 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 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 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 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 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 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 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 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 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 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 4595f757f3fSDimitry 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 5195f757f3fSDimitry Andric bool MetadataStreamerMsgPackV4::emitTo(AMDGPUTargetStreamer &TargetStreamer) { 520*0fca6ea1SDimitry Andric DelayedExprs->resolveDelayedExpressions(); 5210b57cec5SDimitry Andric return TargetStreamer.EmitHSAMetadata(*HSAMetadataDoc, true); 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric 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 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 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 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 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 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 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