101ce144dSScott Linder //===--- AMDGPUHSAMetadataStreamer.cpp --------------------------*- C++ -*-===// 201ce144dSScott Linder // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 601ce144dSScott Linder // 701ce144dSScott Linder //===----------------------------------------------------------------------===// 801ce144dSScott Linder // 901ce144dSScott Linder /// \file 1001ce144dSScott Linder /// AMDGPU HSA Metadata Streamer. 1101ce144dSScott Linder /// 1201ce144dSScott Linder // 1301ce144dSScott Linder //===----------------------------------------------------------------------===// 1401ce144dSScott Linder 1501ce144dSScott Linder #include "AMDGPUHSAMetadataStreamer.h" 1601ce144dSScott Linder #include "AMDGPU.h" 17560d7e04Sdfukalov #include "GCNSubtarget.h" 18f5b36e56SScott Linder #include "MCTargetDesc/AMDGPUTargetStreamer.h" 1901ce144dSScott Linder #include "SIMachineFunctionInfo.h" 2001ce144dSScott Linder #include "SIProgramInfo.h" 2101ce144dSScott Linder #include "llvm/IR/Module.h" 221168119cSMatt Arsenault using namespace llvm; 231168119cSMatt Arsenault 241168119cSMatt Arsenault static std::pair<Type *, Align> getArgumentTypeAlign(const Argument &Arg, 251168119cSMatt Arsenault const DataLayout &DL) { 261168119cSMatt Arsenault Type *Ty = Arg.getType(); 271168119cSMatt Arsenault MaybeAlign ArgAlign; 281168119cSMatt Arsenault if (Arg.hasByRefAttr()) { 291168119cSMatt Arsenault Ty = Arg.getParamByRefType(); 301168119cSMatt Arsenault ArgAlign = Arg.getParamAlign(); 311168119cSMatt Arsenault } 321168119cSMatt Arsenault 331168119cSMatt Arsenault if (!ArgAlign) 341168119cSMatt Arsenault ArgAlign = DL.getABITypeAlign(Ty); 351168119cSMatt Arsenault 361168119cSMatt Arsenault return std::make_pair(Ty, *ArgAlign); 371168119cSMatt Arsenault } 381168119cSMatt Arsenault 3901ce144dSScott Linder namespace llvm { 4001ce144dSScott Linder 4101ce144dSScott Linder static cl::opt<bool> DumpHSAMetadata( 4201ce144dSScott Linder "amdgpu-dump-hsa-metadata", 4301ce144dSScott Linder cl::desc("Dump AMDGPU HSA Metadata")); 4401ce144dSScott Linder static cl::opt<bool> VerifyHSAMetadata( 4501ce144dSScott Linder "amdgpu-verify-hsa-metadata", 4601ce144dSScott Linder cl::desc("Verify AMDGPU HSA Metadata")); 4701ce144dSScott Linder 4801ce144dSScott Linder namespace AMDGPU { 4901ce144dSScott Linder namespace HSAMD { 5001ce144dSScott Linder 51f5b36e56SScott Linder //===----------------------------------------------------------------------===// 52f5b36e56SScott Linder // HSAMetadataStreamerV2 53f5b36e56SScott Linder //===----------------------------------------------------------------------===// 54f5b36e56SScott Linder void MetadataStreamerV2::dump(StringRef HSAMetadataString) const { 5501ce144dSScott Linder errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n'; 5601ce144dSScott Linder } 5701ce144dSScott Linder 58f5b36e56SScott Linder void MetadataStreamerV2::verify(StringRef HSAMetadataString) const { 5901ce144dSScott Linder errs() << "AMDGPU HSA Metadata Parser Test: "; 6001ce144dSScott Linder 6101ce144dSScott Linder HSAMD::Metadata FromHSAMetadataString; 62f82cff31SSimon Pilgrim if (fromString(HSAMetadataString, FromHSAMetadataString)) { 6301ce144dSScott Linder errs() << "FAIL\n"; 6401ce144dSScott Linder return; 6501ce144dSScott Linder } 6601ce144dSScott Linder 6701ce144dSScott Linder std::string ToHSAMetadataString; 6801ce144dSScott Linder if (toString(FromHSAMetadataString, ToHSAMetadataString)) { 6901ce144dSScott Linder errs() << "FAIL\n"; 7001ce144dSScott Linder return; 7101ce144dSScott Linder } 7201ce144dSScott Linder 7301ce144dSScott Linder errs() << (HSAMetadataString == ToHSAMetadataString ? "PASS" : "FAIL") 7401ce144dSScott Linder << '\n'; 7501ce144dSScott Linder if (HSAMetadataString != ToHSAMetadataString) { 7601ce144dSScott Linder errs() << "Original input: " << HSAMetadataString << '\n' 7701ce144dSScott Linder << "Produced output: " << ToHSAMetadataString << '\n'; 7801ce144dSScott Linder } 7901ce144dSScott Linder } 8001ce144dSScott Linder 81f5b36e56SScott Linder AccessQualifier 82f5b36e56SScott Linder MetadataStreamerV2::getAccessQualifier(StringRef AccQual) const { 8301ce144dSScott Linder if (AccQual.empty()) 8401ce144dSScott Linder return AccessQualifier::Unknown; 8501ce144dSScott Linder 8601ce144dSScott Linder return StringSwitch<AccessQualifier>(AccQual) 8701ce144dSScott Linder .Case("read_only", AccessQualifier::ReadOnly) 8801ce144dSScott Linder .Case("write_only", AccessQualifier::WriteOnly) 8901ce144dSScott Linder .Case("read_write", AccessQualifier::ReadWrite) 9001ce144dSScott Linder .Default(AccessQualifier::Default); 9101ce144dSScott Linder } 9201ce144dSScott Linder 93f5b36e56SScott Linder AddressSpaceQualifier 94f5b36e56SScott Linder MetadataStreamerV2::getAddressSpaceQualifier( 9501ce144dSScott Linder unsigned AddressSpace) const { 96b9986746SMatt Arsenault switch (AddressSpace) { 97b9986746SMatt Arsenault case AMDGPUAS::PRIVATE_ADDRESS: 9801ce144dSScott Linder return AddressSpaceQualifier::Private; 99b9986746SMatt Arsenault case AMDGPUAS::GLOBAL_ADDRESS: 10001ce144dSScott Linder return AddressSpaceQualifier::Global; 101b9986746SMatt Arsenault case AMDGPUAS::CONSTANT_ADDRESS: 10201ce144dSScott Linder return AddressSpaceQualifier::Constant; 103b9986746SMatt Arsenault case AMDGPUAS::LOCAL_ADDRESS: 10401ce144dSScott Linder return AddressSpaceQualifier::Local; 105b9986746SMatt Arsenault case AMDGPUAS::FLAT_ADDRESS: 10601ce144dSScott Linder return AddressSpaceQualifier::Generic; 107b9986746SMatt Arsenault case AMDGPUAS::REGION_ADDRESS: 10801ce144dSScott Linder return AddressSpaceQualifier::Region; 109b9986746SMatt Arsenault default: 110b9986746SMatt Arsenault return AddressSpaceQualifier::Unknown; 111b9986746SMatt Arsenault } 11201ce144dSScott Linder } 11301ce144dSScott Linder 114f5b36e56SScott Linder ValueKind MetadataStreamerV2::getValueKind(Type *Ty, StringRef TypeQual, 11501ce144dSScott Linder StringRef BaseTypeName) const { 1166fe949c4SKazu Hirata if (TypeQual.contains("pipe")) 11701ce144dSScott Linder return ValueKind::Pipe; 11801ce144dSScott Linder 11901ce144dSScott Linder return StringSwitch<ValueKind>(BaseTypeName) 12001ce144dSScott Linder .Case("image1d_t", ValueKind::Image) 12101ce144dSScott Linder .Case("image1d_array_t", ValueKind::Image) 12201ce144dSScott Linder .Case("image1d_buffer_t", ValueKind::Image) 12301ce144dSScott Linder .Case("image2d_t", ValueKind::Image) 12401ce144dSScott Linder .Case("image2d_array_t", ValueKind::Image) 12501ce144dSScott Linder .Case("image2d_array_depth_t", ValueKind::Image) 12601ce144dSScott Linder .Case("image2d_array_msaa_t", ValueKind::Image) 12701ce144dSScott Linder .Case("image2d_array_msaa_depth_t", ValueKind::Image) 12801ce144dSScott Linder .Case("image2d_depth_t", ValueKind::Image) 12901ce144dSScott Linder .Case("image2d_msaa_t", ValueKind::Image) 13001ce144dSScott Linder .Case("image2d_msaa_depth_t", ValueKind::Image) 13101ce144dSScott Linder .Case("image3d_t", ValueKind::Image) 13201ce144dSScott Linder .Case("sampler_t", ValueKind::Sampler) 13301ce144dSScott Linder .Case("queue_t", ValueKind::Queue) 13401ce144dSScott Linder .Default(isa<PointerType>(Ty) ? 13501ce144dSScott Linder (Ty->getPointerAddressSpace() == 1360da6350dSMatt Arsenault AMDGPUAS::LOCAL_ADDRESS ? 13701ce144dSScott Linder ValueKind::DynamicSharedPointer : 13801ce144dSScott Linder ValueKind::GlobalBuffer) : 13901ce144dSScott Linder ValueKind::ByValue); 14001ce144dSScott Linder } 14101ce144dSScott Linder 142f5b36e56SScott Linder std::string MetadataStreamerV2::getTypeName(Type *Ty, bool Signed) const { 14301ce144dSScott Linder switch (Ty->getTypeID()) { 14401ce144dSScott Linder case Type::IntegerTyID: { 14501ce144dSScott Linder if (!Signed) 14601ce144dSScott Linder return (Twine('u') + getTypeName(Ty, true)).str(); 14701ce144dSScott Linder 14801ce144dSScott Linder auto BitWidth = Ty->getIntegerBitWidth(); 14901ce144dSScott Linder switch (BitWidth) { 15001ce144dSScott Linder case 8: 15101ce144dSScott Linder return "char"; 15201ce144dSScott Linder case 16: 15301ce144dSScott Linder return "short"; 15401ce144dSScott Linder case 32: 15501ce144dSScott Linder return "int"; 15601ce144dSScott Linder case 64: 15701ce144dSScott Linder return "long"; 15801ce144dSScott Linder default: 15901ce144dSScott Linder return (Twine('i') + Twine(BitWidth)).str(); 16001ce144dSScott Linder } 16101ce144dSScott Linder } 16201ce144dSScott Linder case Type::HalfTyID: 16301ce144dSScott Linder return "half"; 16401ce144dSScott Linder case Type::FloatTyID: 16501ce144dSScott Linder return "float"; 16601ce144dSScott Linder case Type::DoubleTyID: 16701ce144dSScott Linder return "double"; 1682dea3f12SChristopher Tetreault case Type::FixedVectorTyID: { 1693254a001SChristopher Tetreault auto VecTy = cast<FixedVectorType>(Ty); 17001ce144dSScott Linder auto ElTy = VecTy->getElementType(); 171e634f482SChristopher Tetreault auto NumElements = VecTy->getNumElements(); 17201ce144dSScott Linder return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str(); 17301ce144dSScott Linder } 17401ce144dSScott Linder default: 17501ce144dSScott Linder return "unknown"; 17601ce144dSScott Linder } 17701ce144dSScott Linder } 17801ce144dSScott Linder 179f5b36e56SScott Linder std::vector<uint32_t> 180f5b36e56SScott Linder MetadataStreamerV2::getWorkGroupDimensions(MDNode *Node) const { 18101ce144dSScott Linder std::vector<uint32_t> Dims; 18201ce144dSScott Linder if (Node->getNumOperands() != 3) 18301ce144dSScott Linder return Dims; 18401ce144dSScott Linder 18501ce144dSScott Linder for (auto &Op : Node->operands()) 18601ce144dSScott Linder Dims.push_back(mdconst::extract<ConstantInt>(Op)->getZExtValue()); 18701ce144dSScott Linder return Dims; 18801ce144dSScott Linder } 18901ce144dSScott Linder 190f5b36e56SScott Linder Kernel::CodeProps::Metadata 191f5b36e56SScott Linder MetadataStreamerV2::getHSACodeProps(const MachineFunction &MF, 19201ce144dSScott Linder const SIProgramInfo &ProgramInfo) const { 1935bfbae5cSTom Stellard const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>(); 19401ce144dSScott Linder const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>(); 19501ce144dSScott Linder HSAMD::Kernel::CodeProps::Metadata HSACodeProps; 19601ce144dSScott Linder const Function &F = MF.getFunction(); 19701ce144dSScott Linder 1984bec7d42SMatt Arsenault assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL || 1994bec7d42SMatt Arsenault F.getCallingConv() == CallingConv::SPIR_KERNEL); 20001ce144dSScott Linder 201b65fa483SGuillaume Chatelet Align MaxKernArgAlign; 2024bec7d42SMatt Arsenault HSACodeProps.mKernargSegmentSize = STM.getKernArgSegmentSize(F, 2034bec7d42SMatt Arsenault MaxKernArgAlign); 204b65fa483SGuillaume Chatelet HSACodeProps.mKernargSegmentAlign = 205b65fa483SGuillaume Chatelet std::max(MaxKernArgAlign, Align(4)).value(); 20690ff1487SMatt Arsenault 20790ff1487SMatt Arsenault HSACodeProps.mGroupSegmentFixedSize = ProgramInfo.LDSSize; 20890ff1487SMatt Arsenault HSACodeProps.mPrivateSegmentFixedSize = ProgramInfo.ScratchSize; 20901ce144dSScott Linder HSACodeProps.mWavefrontSize = STM.getWavefrontSize(); 21001ce144dSScott Linder HSACodeProps.mNumSGPRs = ProgramInfo.NumSGPR; 21101ce144dSScott Linder HSACodeProps.mNumVGPRs = ProgramInfo.NumVGPR; 21201ce144dSScott Linder HSACodeProps.mMaxFlatWorkGroupSize = MFI.getMaxFlatWorkGroupSize(); 21301ce144dSScott Linder HSACodeProps.mIsDynamicCallStack = ProgramInfo.DynamicCallStack; 21401ce144dSScott Linder HSACodeProps.mIsXNACKEnabled = STM.isXNACKEnabled(); 21501ce144dSScott Linder HSACodeProps.mNumSpilledSGPRs = MFI.getNumSpilledSGPRs(); 21601ce144dSScott Linder HSACodeProps.mNumSpilledVGPRs = MFI.getNumSpilledVGPRs(); 21701ce144dSScott Linder 21801ce144dSScott Linder return HSACodeProps; 21901ce144dSScott Linder } 22001ce144dSScott Linder 221f5b36e56SScott Linder Kernel::DebugProps::Metadata 222f5b36e56SScott Linder MetadataStreamerV2::getHSADebugProps(const MachineFunction &MF, 22301ce144dSScott Linder const SIProgramInfo &ProgramInfo) const { 224aa6fb4c4SMatt Arsenault return HSAMD::Kernel::DebugProps::Metadata(); 22501ce144dSScott Linder } 22601ce144dSScott Linder 227f5b36e56SScott Linder void MetadataStreamerV2::emitVersion() { 22801ce144dSScott Linder auto &Version = HSAMetadata.mVersion; 22901ce144dSScott Linder 230f4ace637SKonstantin Zhuravlyov Version.push_back(VersionMajorV2); 231f4ace637SKonstantin Zhuravlyov Version.push_back(VersionMinorV2); 23201ce144dSScott Linder } 23301ce144dSScott Linder 234f5b36e56SScott Linder void MetadataStreamerV2::emitPrintf(const Module &Mod) { 23501ce144dSScott Linder auto &Printf = HSAMetadata.mPrintf; 23601ce144dSScott Linder 23701ce144dSScott Linder auto Node = Mod.getNamedMetadata("llvm.printf.fmts"); 23801ce144dSScott Linder if (!Node) 23901ce144dSScott Linder return; 24001ce144dSScott Linder 24101ce144dSScott Linder for (auto Op : Node->operands()) 24201ce144dSScott Linder if (Op->getNumOperands()) 243adcd0268SBenjamin Kramer Printf.push_back( 244adcd0268SBenjamin Kramer std::string(cast<MDString>(Op->getOperand(0))->getString())); 24501ce144dSScott Linder } 24601ce144dSScott Linder 247f5b36e56SScott Linder void MetadataStreamerV2::emitKernelLanguage(const Function &Func) { 24801ce144dSScott Linder auto &Kernel = HSAMetadata.mKernels.back(); 24901ce144dSScott Linder 25001ce144dSScott Linder // TODO: What about other languages? 25101ce144dSScott Linder auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version"); 25201ce144dSScott Linder if (!Node || !Node->getNumOperands()) 25301ce144dSScott Linder return; 25401ce144dSScott Linder auto Op0 = Node->getOperand(0); 25501ce144dSScott Linder if (Op0->getNumOperands() <= 1) 25601ce144dSScott Linder return; 25701ce144dSScott Linder 25801ce144dSScott Linder Kernel.mLanguage = "OpenCL C"; 25901ce144dSScott Linder Kernel.mLanguageVersion.push_back( 26001ce144dSScott Linder mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue()); 26101ce144dSScott Linder Kernel.mLanguageVersion.push_back( 26201ce144dSScott Linder mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue()); 26301ce144dSScott Linder } 26401ce144dSScott Linder 265f5b36e56SScott Linder void MetadataStreamerV2::emitKernelAttrs(const Function &Func) { 26601ce144dSScott Linder auto &Attrs = HSAMetadata.mKernels.back().mAttrs; 26701ce144dSScott Linder 26801ce144dSScott Linder if (auto Node = Func.getMetadata("reqd_work_group_size")) 26901ce144dSScott Linder Attrs.mReqdWorkGroupSize = getWorkGroupDimensions(Node); 27001ce144dSScott Linder if (auto Node = Func.getMetadata("work_group_size_hint")) 27101ce144dSScott Linder Attrs.mWorkGroupSizeHint = getWorkGroupDimensions(Node); 27201ce144dSScott Linder if (auto Node = Func.getMetadata("vec_type_hint")) { 27301ce144dSScott Linder Attrs.mVecTypeHint = getTypeName( 27401ce144dSScott Linder cast<ValueAsMetadata>(Node->getOperand(0))->getType(), 27501ce144dSScott Linder mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()); 27601ce144dSScott Linder } 27701ce144dSScott Linder if (Func.hasFnAttribute("runtime-handle")) { 27801ce144dSScott Linder Attrs.mRuntimeHandle = 27901ce144dSScott Linder Func.getFnAttribute("runtime-handle").getValueAsString().str(); 28001ce144dSScott Linder } 28101ce144dSScott Linder } 28201ce144dSScott Linder 283ae0ba7deSMatt Arsenault void MetadataStreamerV2::emitKernelArgs(const Function &Func, 284ae0ba7deSMatt Arsenault const GCNSubtarget &ST) { 28501ce144dSScott Linder for (auto &Arg : Func.args()) 28601ce144dSScott Linder emitKernelArg(Arg); 28701ce144dSScott Linder 288ae0ba7deSMatt Arsenault emitHiddenKernelArgs(Func, ST); 28901ce144dSScott Linder } 29001ce144dSScott Linder 291f5b36e56SScott Linder void MetadataStreamerV2::emitKernelArg(const Argument &Arg) { 29201ce144dSScott Linder auto Func = Arg.getParent(); 29301ce144dSScott Linder auto ArgNo = Arg.getArgNo(); 29401ce144dSScott Linder const MDNode *Node; 29501ce144dSScott Linder 29601ce144dSScott Linder StringRef Name; 29701ce144dSScott Linder Node = Func->getMetadata("kernel_arg_name"); 29801ce144dSScott Linder if (Node && ArgNo < Node->getNumOperands()) 29901ce144dSScott Linder Name = cast<MDString>(Node->getOperand(ArgNo))->getString(); 30001ce144dSScott Linder else if (Arg.hasName()) 30101ce144dSScott Linder Name = Arg.getName(); 30201ce144dSScott Linder 30301ce144dSScott Linder StringRef TypeName; 30401ce144dSScott Linder Node = Func->getMetadata("kernel_arg_type"); 30501ce144dSScott Linder if (Node && ArgNo < Node->getNumOperands()) 30601ce144dSScott Linder TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString(); 30701ce144dSScott Linder 30801ce144dSScott Linder StringRef BaseTypeName; 30901ce144dSScott Linder Node = Func->getMetadata("kernel_arg_base_type"); 31001ce144dSScott Linder if (Node && ArgNo < Node->getNumOperands()) 31101ce144dSScott Linder BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString(); 31201ce144dSScott Linder 31301ce144dSScott Linder StringRef AccQual; 31401ce144dSScott Linder if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() && 31501ce144dSScott Linder Arg.hasNoAliasAttr()) { 31601ce144dSScott Linder AccQual = "read_only"; 31701ce144dSScott Linder } else { 31801ce144dSScott Linder Node = Func->getMetadata("kernel_arg_access_qual"); 31901ce144dSScott Linder if (Node && ArgNo < Node->getNumOperands()) 32001ce144dSScott Linder AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString(); 32101ce144dSScott Linder } 32201ce144dSScott Linder 32301ce144dSScott Linder StringRef TypeQual; 32401ce144dSScott Linder Node = Func->getMetadata("kernel_arg_type_qual"); 32501ce144dSScott Linder if (Node && ArgNo < Node->getNumOperands()) 32601ce144dSScott Linder TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString(); 32701ce144dSScott Linder 32801ce144dSScott Linder const DataLayout &DL = Func->getParent()->getDataLayout(); 32901ce144dSScott Linder 330d3085c25SGuillaume Chatelet MaybeAlign PointeeAlign; 3311168119cSMatt Arsenault if (auto PtrTy = dyn_cast<PointerType>(Arg.getType())) { 3320da6350dSMatt Arsenault if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) { 3331168119cSMatt Arsenault // FIXME: Should report this for all address spaces 334a5e324e3SNikita Popov PointeeAlign = Arg.getParamAlign().valueOrOne(); 33501ce144dSScott Linder } 33601ce144dSScott Linder } 33701ce144dSScott Linder 3381168119cSMatt Arsenault Type *ArgTy; 3391168119cSMatt Arsenault Align ArgAlign; 3401168119cSMatt Arsenault std::tie(ArgTy, ArgAlign) = getArgumentTypeAlign(Arg, DL); 3411168119cSMatt Arsenault 3421168119cSMatt Arsenault emitKernelArg(DL, ArgTy, ArgAlign, 3431168119cSMatt Arsenault getValueKind(ArgTy, TypeQual, BaseTypeName), PointeeAlign, Name, 3441168119cSMatt Arsenault TypeName, BaseTypeName, AccQual, TypeQual); 34501ce144dSScott Linder } 34601ce144dSScott Linder 347f5b36e56SScott Linder void MetadataStreamerV2::emitKernelArg(const DataLayout &DL, Type *Ty, 3481168119cSMatt Arsenault Align Alignment, ValueKind ValueKind, 349d3085c25SGuillaume Chatelet MaybeAlign PointeeAlign, StringRef Name, 350f5b36e56SScott Linder StringRef TypeName, 351f5b36e56SScott Linder StringRef BaseTypeName, 35201ce144dSScott Linder StringRef AccQual, StringRef TypeQual) { 35301ce144dSScott Linder HSAMetadata.mKernels.back().mArgs.push_back(Kernel::Arg::Metadata()); 35401ce144dSScott Linder auto &Arg = HSAMetadata.mKernels.back().mArgs.back(); 35501ce144dSScott Linder 356adcd0268SBenjamin Kramer Arg.mName = std::string(Name); 357adcd0268SBenjamin Kramer Arg.mTypeName = std::string(TypeName); 35801ce144dSScott Linder Arg.mSize = DL.getTypeAllocSize(Ty); 3591168119cSMatt Arsenault Arg.mAlign = Alignment.value(); 36001ce144dSScott Linder Arg.mValueKind = ValueKind; 361d3085c25SGuillaume Chatelet Arg.mPointeeAlign = PointeeAlign ? PointeeAlign->value() : 0; 36201ce144dSScott Linder 36301ce144dSScott Linder if (auto PtrTy = dyn_cast<PointerType>(Ty)) 364f5b36e56SScott Linder Arg.mAddrSpaceQual = getAddressSpaceQualifier(PtrTy->getAddressSpace()); 36501ce144dSScott Linder 36601ce144dSScott Linder Arg.mAccQual = getAccessQualifier(AccQual); 36701ce144dSScott Linder 36801ce144dSScott Linder // TODO: Emit Arg.mActualAccQual. 36901ce144dSScott Linder 37001ce144dSScott Linder SmallVector<StringRef, 1> SplitTypeQuals; 37101ce144dSScott Linder TypeQual.split(SplitTypeQuals, " ", -1, false); 37201ce144dSScott Linder for (StringRef Key : SplitTypeQuals) { 37301ce144dSScott Linder auto P = StringSwitch<bool*>(Key) 37401ce144dSScott Linder .Case("const", &Arg.mIsConst) 37501ce144dSScott Linder .Case("restrict", &Arg.mIsRestrict) 37601ce144dSScott Linder .Case("volatile", &Arg.mIsVolatile) 37701ce144dSScott Linder .Case("pipe", &Arg.mIsPipe) 37801ce144dSScott Linder .Default(nullptr); 37901ce144dSScott Linder if (P) 38001ce144dSScott Linder *P = true; 38101ce144dSScott Linder } 38201ce144dSScott Linder } 38301ce144dSScott Linder 384ae0ba7deSMatt Arsenault void MetadataStreamerV2::emitHiddenKernelArgs(const Function &Func, 385ae0ba7deSMatt Arsenault const GCNSubtarget &ST) { 386ae0ba7deSMatt Arsenault unsigned HiddenArgNumBytes = ST.getImplicitArgNumBytes(Func); 38701ce144dSScott Linder if (!HiddenArgNumBytes) 38801ce144dSScott Linder return; 38901ce144dSScott Linder 39001ce144dSScott Linder auto &DL = Func.getParent()->getDataLayout(); 39101ce144dSScott Linder auto Int64Ty = Type::getInt64Ty(Func.getContext()); 39201ce144dSScott Linder 39301ce144dSScott Linder if (HiddenArgNumBytes >= 8) 3941168119cSMatt Arsenault emitKernelArg(DL, Int64Ty, Align(8), ValueKind::HiddenGlobalOffsetX); 39501ce144dSScott Linder if (HiddenArgNumBytes >= 16) 3961168119cSMatt Arsenault emitKernelArg(DL, Int64Ty, Align(8), ValueKind::HiddenGlobalOffsetY); 39701ce144dSScott Linder if (HiddenArgNumBytes >= 24) 3981168119cSMatt Arsenault emitKernelArg(DL, Int64Ty, Align(8), ValueKind::HiddenGlobalOffsetZ); 39901ce144dSScott Linder 40001ce144dSScott Linder auto Int8PtrTy = Type::getInt8PtrTy(Func.getContext(), 4010da6350dSMatt Arsenault AMDGPUAS::GLOBAL_ADDRESS); 40201ce144dSScott Linder 40301ce144dSScott Linder // Emit "printf buffer" argument if printf is used, otherwise emit dummy 40401ce144dSScott Linder // "none" argument. 40501ce144dSScott Linder if (HiddenArgNumBytes >= 32) { 40601ce144dSScott Linder if (Func.getParent()->getNamedMetadata("llvm.printf.fmts")) 4071168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenPrintfBuffer); 408d8f99bb6SSameer Sahasrabuddhe else if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr")) { 40952c5014dSSameer Sahasrabuddhe // The printf runtime binding pass should have ensured that hostcall and 41052c5014dSSameer Sahasrabuddhe // printf are not used in the same module. 41152c5014dSSameer Sahasrabuddhe assert(!Func.getParent()->getNamedMetadata("llvm.printf.fmts")); 4121168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenHostcallBuffer); 41352c5014dSSameer Sahasrabuddhe } else 4141168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenNone); 41501ce144dSScott Linder } 41601ce144dSScott Linder 41701ce144dSScott Linder // Emit "default queue" and "completion action" arguments if enqueue kernel is 41801ce144dSScott Linder // used, otherwise emit dummy "none" arguments. 41901ce144dSScott Linder if (HiddenArgNumBytes >= 48) { 42001ce144dSScott Linder if (Func.hasFnAttribute("calls-enqueue-kernel")) { 4211168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenDefaultQueue); 4221168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenCompletionAction); 42301ce144dSScott Linder } else { 4241168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenNone); 4251168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenNone); 42601ce144dSScott Linder } 42701ce144dSScott Linder } 428a6241352SYaxun Liu 429a6241352SYaxun Liu // Emit the pointer argument for multi-grid object. 430a6241352SYaxun Liu if (HiddenArgNumBytes >= 56) 4311168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenMultiGridSyncArg); 43201ce144dSScott Linder } 43301ce144dSScott Linder 434f5b36e56SScott Linder bool MetadataStreamerV2::emitTo(AMDGPUTargetStreamer &TargetStreamer) { 435f5b36e56SScott Linder return TargetStreamer.EmitHSAMetadata(getHSAMetadata()); 436f5b36e56SScott Linder } 437f5b36e56SScott Linder 438f4ace637SKonstantin Zhuravlyov void MetadataStreamerV2::begin(const Module &Mod, 439f4ace637SKonstantin Zhuravlyov const IsaInfo::AMDGPUTargetID &TargetID) { 44001ce144dSScott Linder emitVersion(); 44101ce144dSScott Linder emitPrintf(Mod); 44201ce144dSScott Linder } 44301ce144dSScott Linder 444f5b36e56SScott Linder void MetadataStreamerV2::end() { 44501ce144dSScott Linder std::string HSAMetadataString; 44601ce144dSScott Linder if (toString(HSAMetadata, HSAMetadataString)) 44701ce144dSScott Linder return; 44801ce144dSScott Linder 44901ce144dSScott Linder if (DumpHSAMetadata) 45001ce144dSScott Linder dump(HSAMetadataString); 45101ce144dSScott Linder if (VerifyHSAMetadata) 45201ce144dSScott Linder verify(HSAMetadataString); 45301ce144dSScott Linder } 45401ce144dSScott Linder 455f5b36e56SScott Linder void MetadataStreamerV2::emitKernel(const MachineFunction &MF, 456f5b36e56SScott Linder const SIProgramInfo &ProgramInfo) { 45701ce144dSScott Linder auto &Func = MF.getFunction(); 45801ce144dSScott Linder if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL) 45901ce144dSScott Linder return; 46001ce144dSScott Linder 4614bec7d42SMatt Arsenault auto CodeProps = getHSACodeProps(MF, ProgramInfo); 4624bec7d42SMatt Arsenault auto DebugProps = getHSADebugProps(MF, ProgramInfo); 4634bec7d42SMatt Arsenault 46401ce144dSScott Linder HSAMetadata.mKernels.push_back(Kernel::Metadata()); 46501ce144dSScott Linder auto &Kernel = HSAMetadata.mKernels.back(); 46601ce144dSScott Linder 467ae0ba7deSMatt Arsenault const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); 468adcd0268SBenjamin Kramer Kernel.mName = std::string(Func.getName()); 46901ce144dSScott Linder Kernel.mSymbolName = (Twine(Func.getName()) + Twine("@kd")).str(); 47001ce144dSScott Linder emitKernelLanguage(Func); 47101ce144dSScott Linder emitKernelAttrs(Func); 472ae0ba7deSMatt Arsenault emitKernelArgs(Func, ST); 47301ce144dSScott Linder HSAMetadata.mKernels.back().mCodeProps = CodeProps; 47401ce144dSScott Linder HSAMetadata.mKernels.back().mDebugProps = DebugProps; 47501ce144dSScott Linder } 47601ce144dSScott Linder 477f5b36e56SScott Linder //===----------------------------------------------------------------------===// 478f5b36e56SScott Linder // HSAMetadataStreamerV3 479f5b36e56SScott Linder //===----------------------------------------------------------------------===// 480f5b36e56SScott Linder 481f5b36e56SScott Linder void MetadataStreamerV3::dump(StringRef HSAMetadataString) const { 482f5b36e56SScott Linder errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n'; 483f5b36e56SScott Linder } 484f5b36e56SScott Linder 485f5b36e56SScott Linder void MetadataStreamerV3::verify(StringRef HSAMetadataString) const { 486f5b36e56SScott Linder errs() << "AMDGPU HSA Metadata Parser Test: "; 487f5b36e56SScott Linder 488ed0b9af9STim Renouf msgpack::Document FromHSAMetadataString; 489f5b36e56SScott Linder 490ed0b9af9STim Renouf if (!FromHSAMetadataString.fromYAML(HSAMetadataString)) { 491f5b36e56SScott Linder errs() << "FAIL\n"; 492f5b36e56SScott Linder return; 493f5b36e56SScott Linder } 494f5b36e56SScott Linder 495f5b36e56SScott Linder std::string ToHSAMetadataString; 496f5b36e56SScott Linder raw_string_ostream StrOS(ToHSAMetadataString); 497ed0b9af9STim Renouf FromHSAMetadataString.toYAML(StrOS); 498f5b36e56SScott Linder 499f5b36e56SScott Linder errs() << (HSAMetadataString == StrOS.str() ? "PASS" : "FAIL") << '\n'; 500f5b36e56SScott Linder if (HSAMetadataString != ToHSAMetadataString) { 501f5b36e56SScott Linder errs() << "Original input: " << HSAMetadataString << '\n' 502f5b36e56SScott Linder << "Produced output: " << StrOS.str() << '\n'; 503f5b36e56SScott Linder } 504f5b36e56SScott Linder } 505f5b36e56SScott Linder 506f5b36e56SScott Linder Optional<StringRef> 507f5b36e56SScott Linder MetadataStreamerV3::getAccessQualifier(StringRef AccQual) const { 508f5b36e56SScott Linder return StringSwitch<Optional<StringRef>>(AccQual) 509f5b36e56SScott Linder .Case("read_only", StringRef("read_only")) 510f5b36e56SScott Linder .Case("write_only", StringRef("write_only")) 511f5b36e56SScott Linder .Case("read_write", StringRef("read_write")) 512f5b36e56SScott Linder .Default(None); 513f5b36e56SScott Linder } 514f5b36e56SScott Linder 515f5b36e56SScott Linder Optional<StringRef> 516f5b36e56SScott Linder MetadataStreamerV3::getAddressSpaceQualifier(unsigned AddressSpace) const { 517f5b36e56SScott Linder switch (AddressSpace) { 518f5b36e56SScott Linder case AMDGPUAS::PRIVATE_ADDRESS: 519f5b36e56SScott Linder return StringRef("private"); 520f5b36e56SScott Linder case AMDGPUAS::GLOBAL_ADDRESS: 521f5b36e56SScott Linder return StringRef("global"); 522f5b36e56SScott Linder case AMDGPUAS::CONSTANT_ADDRESS: 523f5b36e56SScott Linder return StringRef("constant"); 524f5b36e56SScott Linder case AMDGPUAS::LOCAL_ADDRESS: 525f5b36e56SScott Linder return StringRef("local"); 526f5b36e56SScott Linder case AMDGPUAS::FLAT_ADDRESS: 527f5b36e56SScott Linder return StringRef("generic"); 528f5b36e56SScott Linder case AMDGPUAS::REGION_ADDRESS: 529f5b36e56SScott Linder return StringRef("region"); 530f5b36e56SScott Linder default: 531f5b36e56SScott Linder return None; 532f5b36e56SScott Linder } 533f5b36e56SScott Linder } 534f5b36e56SScott Linder 535f5b36e56SScott Linder StringRef MetadataStreamerV3::getValueKind(Type *Ty, StringRef TypeQual, 536f5b36e56SScott Linder StringRef BaseTypeName) const { 5376fe949c4SKazu Hirata if (TypeQual.contains("pipe")) 538f5b36e56SScott Linder return "pipe"; 539f5b36e56SScott Linder 540f5b36e56SScott Linder return StringSwitch<StringRef>(BaseTypeName) 541f5b36e56SScott Linder .Case("image1d_t", "image") 542f5b36e56SScott Linder .Case("image1d_array_t", "image") 543f5b36e56SScott Linder .Case("image1d_buffer_t", "image") 544f5b36e56SScott Linder .Case("image2d_t", "image") 545f5b36e56SScott Linder .Case("image2d_array_t", "image") 546f5b36e56SScott Linder .Case("image2d_array_depth_t", "image") 547f5b36e56SScott Linder .Case("image2d_array_msaa_t", "image") 548f5b36e56SScott Linder .Case("image2d_array_msaa_depth_t", "image") 549f5b36e56SScott Linder .Case("image2d_depth_t", "image") 550f5b36e56SScott Linder .Case("image2d_msaa_t", "image") 551f5b36e56SScott Linder .Case("image2d_msaa_depth_t", "image") 552f5b36e56SScott Linder .Case("image3d_t", "image") 553f5b36e56SScott Linder .Case("sampler_t", "sampler") 554f5b36e56SScott Linder .Case("queue_t", "queue") 555f5b36e56SScott Linder .Default(isa<PointerType>(Ty) 556f5b36e56SScott Linder ? (Ty->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS 557f5b36e56SScott Linder ? "dynamic_shared_pointer" 558f5b36e56SScott Linder : "global_buffer") 559f5b36e56SScott Linder : "by_value"); 560f5b36e56SScott Linder } 561f5b36e56SScott Linder 562f5b36e56SScott Linder std::string MetadataStreamerV3::getTypeName(Type *Ty, bool Signed) const { 563f5b36e56SScott Linder switch (Ty->getTypeID()) { 564f5b36e56SScott Linder case Type::IntegerTyID: { 565f5b36e56SScott Linder if (!Signed) 566f5b36e56SScott Linder return (Twine('u') + getTypeName(Ty, true)).str(); 567f5b36e56SScott Linder 568f5b36e56SScott Linder auto BitWidth = Ty->getIntegerBitWidth(); 569f5b36e56SScott Linder switch (BitWidth) { 570f5b36e56SScott Linder case 8: 571f5b36e56SScott Linder return "char"; 572f5b36e56SScott Linder case 16: 573f5b36e56SScott Linder return "short"; 574f5b36e56SScott Linder case 32: 575f5b36e56SScott Linder return "int"; 576f5b36e56SScott Linder case 64: 577f5b36e56SScott Linder return "long"; 578f5b36e56SScott Linder default: 579f5b36e56SScott Linder return (Twine('i') + Twine(BitWidth)).str(); 580f5b36e56SScott Linder } 581f5b36e56SScott Linder } 582f5b36e56SScott Linder case Type::HalfTyID: 583f5b36e56SScott Linder return "half"; 584f5b36e56SScott Linder case Type::FloatTyID: 585f5b36e56SScott Linder return "float"; 586f5b36e56SScott Linder case Type::DoubleTyID: 587f5b36e56SScott Linder return "double"; 5882dea3f12SChristopher Tetreault case Type::FixedVectorTyID: { 5893254a001SChristopher Tetreault auto VecTy = cast<FixedVectorType>(Ty); 590f5b36e56SScott Linder auto ElTy = VecTy->getElementType(); 591e634f482SChristopher Tetreault auto NumElements = VecTy->getNumElements(); 592f5b36e56SScott Linder return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str(); 593f5b36e56SScott Linder } 594f5b36e56SScott Linder default: 595f5b36e56SScott Linder return "unknown"; 596f5b36e56SScott Linder } 597f5b36e56SScott Linder } 598f5b36e56SScott Linder 599ed0b9af9STim Renouf msgpack::ArrayDocNode 600f5b36e56SScott Linder MetadataStreamerV3::getWorkGroupDimensions(MDNode *Node) const { 601ed0b9af9STim Renouf auto Dims = HSAMetadataDoc->getArrayNode(); 602f5b36e56SScott Linder if (Node->getNumOperands() != 3) 603f5b36e56SScott Linder return Dims; 604f5b36e56SScott Linder 605f5b36e56SScott Linder for (auto &Op : Node->operands()) 606ed0b9af9STim Renouf Dims.push_back(Dims.getDocument()->getNode( 607ed0b9af9STim Renouf uint64_t(mdconst::extract<ConstantInt>(Op)->getZExtValue()))); 608f5b36e56SScott Linder return Dims; 609f5b36e56SScott Linder } 610f5b36e56SScott Linder 611f5b36e56SScott Linder void MetadataStreamerV3::emitVersion() { 612ed0b9af9STim Renouf auto Version = HSAMetadataDoc->getArrayNode(); 613f4ace637SKonstantin Zhuravlyov Version.push_back(Version.getDocument()->getNode(VersionMajorV3)); 614f4ace637SKonstantin Zhuravlyov Version.push_back(Version.getDocument()->getNode(VersionMinorV3)); 615ed0b9af9STim Renouf getRootMetadata("amdhsa.version") = Version; 616f5b36e56SScott Linder } 617f5b36e56SScott Linder 618f5b36e56SScott Linder void MetadataStreamerV3::emitPrintf(const Module &Mod) { 619f5b36e56SScott Linder auto Node = Mod.getNamedMetadata("llvm.printf.fmts"); 620f5b36e56SScott Linder if (!Node) 621f5b36e56SScott Linder return; 622f5b36e56SScott Linder 623ed0b9af9STim Renouf auto Printf = HSAMetadataDoc->getArrayNode(); 624f5b36e56SScott Linder for (auto Op : Node->operands()) 625f5b36e56SScott Linder if (Op->getNumOperands()) 626ed0b9af9STim Renouf Printf.push_back(Printf.getDocument()->getNode( 627ed0b9af9STim Renouf cast<MDString>(Op->getOperand(0))->getString(), /*Copy=*/true)); 628ed0b9af9STim Renouf getRootMetadata("amdhsa.printf") = Printf; 629f5b36e56SScott Linder } 630f5b36e56SScott Linder 631f5b36e56SScott Linder void MetadataStreamerV3::emitKernelLanguage(const Function &Func, 632ed0b9af9STim Renouf msgpack::MapDocNode Kern) { 633f5b36e56SScott Linder // TODO: What about other languages? 634f5b36e56SScott Linder auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version"); 635f5b36e56SScott Linder if (!Node || !Node->getNumOperands()) 636f5b36e56SScott Linder return; 637f5b36e56SScott Linder auto Op0 = Node->getOperand(0); 638f5b36e56SScott Linder if (Op0->getNumOperands() <= 1) 639f5b36e56SScott Linder return; 640f5b36e56SScott Linder 641ed0b9af9STim Renouf Kern[".language"] = Kern.getDocument()->getNode("OpenCL C"); 642ed0b9af9STim Renouf auto LanguageVersion = Kern.getDocument()->getArrayNode(); 643ed0b9af9STim Renouf LanguageVersion.push_back(Kern.getDocument()->getNode( 644f5b36e56SScott Linder mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue())); 645ed0b9af9STim Renouf LanguageVersion.push_back(Kern.getDocument()->getNode( 646f5b36e56SScott Linder mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue())); 647ed0b9af9STim Renouf Kern[".language_version"] = LanguageVersion; 648f5b36e56SScott Linder } 649f5b36e56SScott Linder 650f5b36e56SScott Linder void MetadataStreamerV3::emitKernelAttrs(const Function &Func, 651ed0b9af9STim Renouf msgpack::MapDocNode Kern) { 652f5b36e56SScott Linder 653f5b36e56SScott Linder if (auto Node = Func.getMetadata("reqd_work_group_size")) 654f5b36e56SScott Linder Kern[".reqd_workgroup_size"] = getWorkGroupDimensions(Node); 655f5b36e56SScott Linder if (auto Node = Func.getMetadata("work_group_size_hint")) 656f5b36e56SScott Linder Kern[".workgroup_size_hint"] = getWorkGroupDimensions(Node); 657f5b36e56SScott Linder if (auto Node = Func.getMetadata("vec_type_hint")) { 658ed0b9af9STim Renouf Kern[".vec_type_hint"] = Kern.getDocument()->getNode( 659ed0b9af9STim Renouf getTypeName( 660f5b36e56SScott Linder cast<ValueAsMetadata>(Node->getOperand(0))->getType(), 661ed0b9af9STim Renouf mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()), 662ed0b9af9STim Renouf /*Copy=*/true); 663f5b36e56SScott Linder } 664f5b36e56SScott Linder if (Func.hasFnAttribute("runtime-handle")) { 665ed0b9af9STim Renouf Kern[".device_enqueue_symbol"] = Kern.getDocument()->getNode( 666ed0b9af9STim Renouf Func.getFnAttribute("runtime-handle").getValueAsString().str(), 667ed0b9af9STim Renouf /*Copy=*/true); 668f5b36e56SScott Linder } 6695173854fSReshabh Sharma if (Func.hasFnAttribute("device-init")) 6705173854fSReshabh Sharma Kern[".kind"] = Kern.getDocument()->getNode("init"); 6715173854fSReshabh Sharma else if (Func.hasFnAttribute("device-fini")) 6725173854fSReshabh Sharma Kern[".kind"] = Kern.getDocument()->getNode("fini"); 673f5b36e56SScott Linder } 674f5b36e56SScott Linder 6751194b9cdSChangpeng Fang void MetadataStreamerV3::emitKernelArgs(const MachineFunction &MF, 676ed0b9af9STim Renouf msgpack::MapDocNode Kern) { 6771194b9cdSChangpeng Fang auto &Func = MF.getFunction(); 678f5b36e56SScott Linder unsigned Offset = 0; 679ed0b9af9STim Renouf auto Args = HSAMetadataDoc->getArrayNode(); 680f5b36e56SScott Linder for (auto &Arg : Func.args()) 681ed0b9af9STim Renouf emitKernelArg(Arg, Offset, Args); 682f5b36e56SScott Linder 6831194b9cdSChangpeng Fang emitHiddenKernelArgs(MF, Offset, Args); 684f5b36e56SScott Linder 685ed0b9af9STim Renouf Kern[".args"] = Args; 686f5b36e56SScott Linder } 687f5b36e56SScott Linder 688f5b36e56SScott Linder void MetadataStreamerV3::emitKernelArg(const Argument &Arg, unsigned &Offset, 689ed0b9af9STim Renouf msgpack::ArrayDocNode Args) { 690f5b36e56SScott Linder auto Func = Arg.getParent(); 691f5b36e56SScott Linder auto ArgNo = Arg.getArgNo(); 692f5b36e56SScott Linder const MDNode *Node; 693f5b36e56SScott Linder 694f5b36e56SScott Linder StringRef Name; 695f5b36e56SScott Linder Node = Func->getMetadata("kernel_arg_name"); 696f5b36e56SScott Linder if (Node && ArgNo < Node->getNumOperands()) 697f5b36e56SScott Linder Name = cast<MDString>(Node->getOperand(ArgNo))->getString(); 698f5b36e56SScott Linder else if (Arg.hasName()) 699f5b36e56SScott Linder Name = Arg.getName(); 700f5b36e56SScott Linder 701f5b36e56SScott Linder StringRef TypeName; 702f5b36e56SScott Linder Node = Func->getMetadata("kernel_arg_type"); 703f5b36e56SScott Linder if (Node && ArgNo < Node->getNumOperands()) 704f5b36e56SScott Linder TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString(); 705f5b36e56SScott Linder 706f5b36e56SScott Linder StringRef BaseTypeName; 707f5b36e56SScott Linder Node = Func->getMetadata("kernel_arg_base_type"); 708f5b36e56SScott Linder if (Node && ArgNo < Node->getNumOperands()) 709f5b36e56SScott Linder BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString(); 710f5b36e56SScott Linder 711f5b36e56SScott Linder StringRef AccQual; 712f5b36e56SScott Linder if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() && 713f5b36e56SScott Linder Arg.hasNoAliasAttr()) { 714f5b36e56SScott Linder AccQual = "read_only"; 715f5b36e56SScott Linder } else { 716f5b36e56SScott Linder Node = Func->getMetadata("kernel_arg_access_qual"); 717f5b36e56SScott Linder if (Node && ArgNo < Node->getNumOperands()) 718f5b36e56SScott Linder AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString(); 719f5b36e56SScott Linder } 720f5b36e56SScott Linder 721f5b36e56SScott Linder StringRef TypeQual; 722f5b36e56SScott Linder Node = Func->getMetadata("kernel_arg_type_qual"); 723f5b36e56SScott Linder if (Node && ArgNo < Node->getNumOperands()) 724f5b36e56SScott Linder TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString(); 725f5b36e56SScott Linder 726f5b36e56SScott Linder const DataLayout &DL = Func->getParent()->getDataLayout(); 727f5b36e56SScott Linder 728d3085c25SGuillaume Chatelet MaybeAlign PointeeAlign; 7291168119cSMatt Arsenault Type *Ty = Arg.hasByRefAttr() ? Arg.getParamByRefType() : Arg.getType(); 7301168119cSMatt Arsenault 7311168119cSMatt Arsenault // FIXME: Need to distinguish in memory alignment from pointer alignment. 732f5b36e56SScott Linder if (auto PtrTy = dyn_cast<PointerType>(Ty)) { 733a5e324e3SNikita Popov if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) 734a5e324e3SNikita Popov PointeeAlign = Arg.getParamAlign().valueOrOne(); 735f5b36e56SScott Linder } 736f5b36e56SScott Linder 7371168119cSMatt Arsenault // There's no distinction between byval aggregates and raw aggregates. 7381168119cSMatt Arsenault Type *ArgTy; 7391168119cSMatt Arsenault Align ArgAlign; 7401168119cSMatt Arsenault std::tie(ArgTy, ArgAlign) = getArgumentTypeAlign(Arg, DL); 7411168119cSMatt Arsenault 7421168119cSMatt Arsenault emitKernelArg(DL, ArgTy, ArgAlign, 7431168119cSMatt Arsenault getValueKind(ArgTy, TypeQual, BaseTypeName), Offset, Args, 7441168119cSMatt Arsenault PointeeAlign, Name, TypeName, BaseTypeName, AccQual, TypeQual); 745f5b36e56SScott Linder } 746f5b36e56SScott Linder 7471168119cSMatt Arsenault void MetadataStreamerV3::emitKernelArg( 7481168119cSMatt Arsenault const DataLayout &DL, Type *Ty, Align Alignment, StringRef ValueKind, 7491168119cSMatt Arsenault unsigned &Offset, msgpack::ArrayDocNode Args, MaybeAlign PointeeAlign, 7501168119cSMatt Arsenault StringRef Name, StringRef TypeName, StringRef BaseTypeName, 751f5b36e56SScott Linder StringRef AccQual, StringRef TypeQual) { 752ed0b9af9STim Renouf auto Arg = Args.getDocument()->getMapNode(); 753f5b36e56SScott Linder 754f5b36e56SScott Linder if (!Name.empty()) 755ed0b9af9STim Renouf Arg[".name"] = Arg.getDocument()->getNode(Name, /*Copy=*/true); 756f5b36e56SScott Linder if (!TypeName.empty()) 757ed0b9af9STim Renouf Arg[".type_name"] = Arg.getDocument()->getNode(TypeName, /*Copy=*/true); 758f5b36e56SScott Linder auto Size = DL.getTypeAllocSize(Ty); 759ed0b9af9STim Renouf Arg[".size"] = Arg.getDocument()->getNode(Size); 760d3085c25SGuillaume Chatelet Offset = alignTo(Offset, Alignment); 761ed0b9af9STim Renouf Arg[".offset"] = Arg.getDocument()->getNode(Offset); 762f5b36e56SScott Linder Offset += Size; 763ed0b9af9STim Renouf Arg[".value_kind"] = Arg.getDocument()->getNode(ValueKind, /*Copy=*/true); 764f5b36e56SScott Linder if (PointeeAlign) 765d3085c25SGuillaume Chatelet Arg[".pointee_align"] = Arg.getDocument()->getNode(PointeeAlign->value()); 766f5b36e56SScott Linder 767f5b36e56SScott Linder if (auto PtrTy = dyn_cast<PointerType>(Ty)) 768f5b36e56SScott Linder if (auto Qualifier = getAddressSpaceQualifier(PtrTy->getAddressSpace())) 769ed0b9af9STim Renouf Arg[".address_space"] = Arg.getDocument()->getNode(*Qualifier, /*Copy=*/true); 770f5b36e56SScott Linder 771f5b36e56SScott Linder if (auto AQ = getAccessQualifier(AccQual)) 772ed0b9af9STim Renouf Arg[".access"] = Arg.getDocument()->getNode(*AQ, /*Copy=*/true); 773f5b36e56SScott Linder 774f5b36e56SScott Linder // TODO: Emit Arg[".actual_access"]. 775f5b36e56SScott Linder 776f5b36e56SScott Linder SmallVector<StringRef, 1> SplitTypeQuals; 777f5b36e56SScott Linder TypeQual.split(SplitTypeQuals, " ", -1, false); 778f5b36e56SScott Linder for (StringRef Key : SplitTypeQuals) { 779f5b36e56SScott Linder if (Key == "const") 780ed0b9af9STim Renouf Arg[".is_const"] = Arg.getDocument()->getNode(true); 781f5b36e56SScott Linder else if (Key == "restrict") 782ed0b9af9STim Renouf Arg[".is_restrict"] = Arg.getDocument()->getNode(true); 783f5b36e56SScott Linder else if (Key == "volatile") 784ed0b9af9STim Renouf Arg[".is_volatile"] = Arg.getDocument()->getNode(true); 785f5b36e56SScott Linder else if (Key == "pipe") 786ed0b9af9STim Renouf Arg[".is_pipe"] = Arg.getDocument()->getNode(true); 787f5b36e56SScott Linder } 788f5b36e56SScott Linder 789ed0b9af9STim Renouf Args.push_back(Arg); 790f5b36e56SScott Linder } 791f5b36e56SScott Linder 7921194b9cdSChangpeng Fang void MetadataStreamerV3::emitHiddenKernelArgs(const MachineFunction &MF, 793f5b36e56SScott Linder unsigned &Offset, 794ed0b9af9STim Renouf msgpack::ArrayDocNode Args) { 7951194b9cdSChangpeng Fang auto &Func = MF.getFunction(); 7961194b9cdSChangpeng Fang const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); 797d8f99bb6SSameer Sahasrabuddhe const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>(); 7981194b9cdSChangpeng Fang 799ae0ba7deSMatt Arsenault unsigned HiddenArgNumBytes = ST.getImplicitArgNumBytes(Func); 800f5b36e56SScott Linder if (!HiddenArgNumBytes) 801f5b36e56SScott Linder return; 802f5b36e56SScott Linder 803095c48fdSkpyzhov const Module *M = Func.getParent(); 804095c48fdSkpyzhov auto &DL = M->getDataLayout(); 805f5b36e56SScott Linder auto Int64Ty = Type::getInt64Ty(Func.getContext()); 806f5b36e56SScott Linder 807f5b36e56SScott Linder if (HiddenArgNumBytes >= 8) 8081168119cSMatt Arsenault emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset, 8091168119cSMatt Arsenault Args); 810f5b36e56SScott Linder if (HiddenArgNumBytes >= 16) 8111168119cSMatt Arsenault emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset, 8121168119cSMatt Arsenault Args); 813f5b36e56SScott Linder if (HiddenArgNumBytes >= 24) 8141168119cSMatt Arsenault emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset, 8151168119cSMatt Arsenault Args); 816f5b36e56SScott Linder 817f5b36e56SScott Linder auto Int8PtrTy = 818f5b36e56SScott Linder Type::getInt8PtrTy(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS); 819f5b36e56SScott Linder 820095c48fdSkpyzhov // Emit "printf buffer" argument if printf is used, emit "hostcall buffer" 821095c48fdSkpyzhov // if "hostcall" module flag is set, otherwise emit dummy "none" argument. 822f5b36e56SScott Linder if (HiddenArgNumBytes >= 32) { 823095c48fdSkpyzhov if (M->getNamedMetadata("llvm.printf.fmts")) 8241168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset, 8251168119cSMatt Arsenault Args); 826d8f99bb6SSameer Sahasrabuddhe else if (MFI.hasHostcallPtr()) { 82752c5014dSSameer Sahasrabuddhe // The printf runtime binding pass should have ensured that hostcall and 82852c5014dSSameer Sahasrabuddhe // printf are not used in the same module. 829095c48fdSkpyzhov assert(!M->getNamedMetadata("llvm.printf.fmts")); 8301168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset, 8311168119cSMatt Arsenault Args); 83252c5014dSSameer Sahasrabuddhe } else 8331168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args); 834f5b36e56SScott Linder } 835f5b36e56SScott Linder 836f5b36e56SScott Linder // Emit "default queue" and "completion action" arguments if enqueue kernel is 837f5b36e56SScott Linder // used, otherwise emit dummy "none" arguments. 838f5b36e56SScott Linder if (HiddenArgNumBytes >= 48) { 839f5b36e56SScott Linder if (Func.hasFnAttribute("calls-enqueue-kernel")) { 8401168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset, 8411168119cSMatt Arsenault Args); 8421168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset, 8431168119cSMatt Arsenault Args); 844f5b36e56SScott Linder } else { 8451168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args); 8461168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args); 847f5b36e56SScott Linder } 848f5b36e56SScott Linder } 849a6241352SYaxun Liu 850a6241352SYaxun Liu // Emit the pointer argument for multi-grid object. 851a6241352SYaxun Liu if (HiddenArgNumBytes >= 56) 8521168119cSMatt Arsenault emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset, 8531168119cSMatt Arsenault Args); 854f5b36e56SScott Linder } 855f5b36e56SScott Linder 856ed0b9af9STim Renouf msgpack::MapDocNode 857f5b36e56SScott Linder MetadataStreamerV3::getHSAKernelProps(const MachineFunction &MF, 858f5b36e56SScott Linder const SIProgramInfo &ProgramInfo) const { 859f5b36e56SScott Linder const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>(); 860f5b36e56SScott Linder const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>(); 861f5b36e56SScott Linder const Function &F = MF.getFunction(); 862f5b36e56SScott Linder 863ed0b9af9STim Renouf auto Kern = HSAMetadataDoc->getMapNode(); 864f5b36e56SScott Linder 865b65fa483SGuillaume Chatelet Align MaxKernArgAlign; 866ed0b9af9STim Renouf Kern[".kernarg_segment_size"] = Kern.getDocument()->getNode( 867f5b36e56SScott Linder STM.getKernArgSegmentSize(F, MaxKernArgAlign)); 868f5b36e56SScott Linder Kern[".group_segment_fixed_size"] = 869ed0b9af9STim Renouf Kern.getDocument()->getNode(ProgramInfo.LDSSize); 870f5b36e56SScott Linder Kern[".private_segment_fixed_size"] = 871ed0b9af9STim Renouf Kern.getDocument()->getNode(ProgramInfo.ScratchSize); 87290ff1487SMatt Arsenault 87390ff1487SMatt Arsenault // FIXME: The metadata treats the minimum as 16? 874f5b36e56SScott Linder Kern[".kernarg_segment_align"] = 875b65fa483SGuillaume Chatelet Kern.getDocument()->getNode(std::max(Align(4), MaxKernArgAlign).value()); 876f5b36e56SScott Linder Kern[".wavefront_size"] = 877ed0b9af9STim Renouf Kern.getDocument()->getNode(STM.getWavefrontSize()); 878ed0b9af9STim Renouf Kern[".sgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumSGPR); 879ed0b9af9STim Renouf Kern[".vgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumVGPR); 88074702444SJacob Lambert 88174702444SJacob Lambert // Only add AGPR count to metadata for supported devices 88274702444SJacob Lambert if (STM.hasMAIInsts()) { 88374702444SJacob Lambert Kern[".agpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumAccVGPR); 88474702444SJacob Lambert } 88574702444SJacob Lambert 886f5b36e56SScott Linder Kern[".max_flat_workgroup_size"] = 887ed0b9af9STim Renouf Kern.getDocument()->getNode(MFI.getMaxFlatWorkGroupSize()); 888f5b36e56SScott Linder Kern[".sgpr_spill_count"] = 889ed0b9af9STim Renouf Kern.getDocument()->getNode(MFI.getNumSpilledSGPRs()); 890f5b36e56SScott Linder Kern[".vgpr_spill_count"] = 891ed0b9af9STim Renouf Kern.getDocument()->getNode(MFI.getNumSpilledVGPRs()); 892f5b36e56SScott Linder 893ed0b9af9STim Renouf return Kern; 894f5b36e56SScott Linder } 895f5b36e56SScott Linder 896f5b36e56SScott Linder bool MetadataStreamerV3::emitTo(AMDGPUTargetStreamer &TargetStreamer) { 897ed0b9af9STim Renouf return TargetStreamer.EmitHSAMetadata(*HSAMetadataDoc, true); 898f5b36e56SScott Linder } 899f5b36e56SScott Linder 900f4ace637SKonstantin Zhuravlyov void MetadataStreamerV3::begin(const Module &Mod, 901f4ace637SKonstantin Zhuravlyov const IsaInfo::AMDGPUTargetID &TargetID) { 902f5b36e56SScott Linder emitVersion(); 903f5b36e56SScott Linder emitPrintf(Mod); 904ed0b9af9STim Renouf getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode(); 905f5b36e56SScott Linder } 906f5b36e56SScott Linder 907f5b36e56SScott Linder void MetadataStreamerV3::end() { 908f5b36e56SScott Linder std::string HSAMetadataString; 909f5b36e56SScott Linder raw_string_ostream StrOS(HSAMetadataString); 910ed0b9af9STim Renouf HSAMetadataDoc->toYAML(StrOS); 911f5b36e56SScott Linder 912f5b36e56SScott Linder if (DumpHSAMetadata) 913f5b36e56SScott Linder dump(StrOS.str()); 914f5b36e56SScott Linder if (VerifyHSAMetadata) 915f5b36e56SScott Linder verify(StrOS.str()); 916f5b36e56SScott Linder } 917f5b36e56SScott Linder 918f5b36e56SScott Linder void MetadataStreamerV3::emitKernel(const MachineFunction &MF, 919f5b36e56SScott Linder const SIProgramInfo &ProgramInfo) { 920f5b36e56SScott Linder auto &Func = MF.getFunction(); 921ed0b9af9STim Renouf auto Kern = getHSAKernelProps(MF, ProgramInfo); 922f5b36e56SScott Linder 923f5b36e56SScott Linder assert(Func.getCallingConv() == CallingConv::AMDGPU_KERNEL || 924f5b36e56SScott Linder Func.getCallingConv() == CallingConv::SPIR_KERNEL); 925f5b36e56SScott Linder 926ed0b9af9STim Renouf auto Kernels = 927ed0b9af9STim Renouf getRootMetadata("amdhsa.kernels").getArray(/*Convert=*/true); 928f5b36e56SScott Linder 929f5b36e56SScott Linder { 930ed0b9af9STim Renouf Kern[".name"] = Kern.getDocument()->getNode(Func.getName()); 931ed0b9af9STim Renouf Kern[".symbol"] = Kern.getDocument()->getNode( 932ed0b9af9STim Renouf (Twine(Func.getName()) + Twine(".kd")).str(), /*Copy=*/true); 933f5b36e56SScott Linder emitKernelLanguage(Func, Kern); 934f5b36e56SScott Linder emitKernelAttrs(Func, Kern); 9351194b9cdSChangpeng Fang emitKernelArgs(MF, Kern); 936f5b36e56SScott Linder } 937f5b36e56SScott Linder 938ed0b9af9STim Renouf Kernels.push_back(Kern); 939f5b36e56SScott Linder } 940f5b36e56SScott Linder 941f4ace637SKonstantin Zhuravlyov //===----------------------------------------------------------------------===// 942f4ace637SKonstantin Zhuravlyov // HSAMetadataStreamerV4 943f4ace637SKonstantin Zhuravlyov //===----------------------------------------------------------------------===// 944f4ace637SKonstantin Zhuravlyov 945f4ace637SKonstantin Zhuravlyov void MetadataStreamerV4::emitVersion() { 946f4ace637SKonstantin Zhuravlyov auto Version = HSAMetadataDoc->getArrayNode(); 947f4ace637SKonstantin Zhuravlyov Version.push_back(Version.getDocument()->getNode(VersionMajorV4)); 948f4ace637SKonstantin Zhuravlyov Version.push_back(Version.getDocument()->getNode(VersionMinorV4)); 949f4ace637SKonstantin Zhuravlyov getRootMetadata("amdhsa.version") = Version; 950f4ace637SKonstantin Zhuravlyov } 951f4ace637SKonstantin Zhuravlyov 952f4ace637SKonstantin Zhuravlyov void MetadataStreamerV4::emitTargetID(const IsaInfo::AMDGPUTargetID &TargetID) { 953f4ace637SKonstantin Zhuravlyov getRootMetadata("amdhsa.target") = 954f4ace637SKonstantin Zhuravlyov HSAMetadataDoc->getNode(TargetID.toString(), /*Copy=*/true); 955f4ace637SKonstantin Zhuravlyov } 956f4ace637SKonstantin Zhuravlyov 957f4ace637SKonstantin Zhuravlyov void MetadataStreamerV4::begin(const Module &Mod, 958f4ace637SKonstantin Zhuravlyov const IsaInfo::AMDGPUTargetID &TargetID) { 959f4ace637SKonstantin Zhuravlyov emitVersion(); 960f4ace637SKonstantin Zhuravlyov emitTargetID(TargetID); 961f4ace637SKonstantin Zhuravlyov emitPrintf(Mod); 962f4ace637SKonstantin Zhuravlyov getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode(); 963f4ace637SKonstantin Zhuravlyov } 964f4ace637SKonstantin Zhuravlyov 9651194b9cdSChangpeng Fang //===----------------------------------------------------------------------===// 9661194b9cdSChangpeng Fang // HSAMetadataStreamerV5 9671194b9cdSChangpeng Fang //===----------------------------------------------------------------------===// 9681194b9cdSChangpeng Fang 9691194b9cdSChangpeng Fang void MetadataStreamerV5::emitVersion() { 9701194b9cdSChangpeng Fang auto Version = HSAMetadataDoc->getArrayNode(); 9711194b9cdSChangpeng Fang Version.push_back(Version.getDocument()->getNode(VersionMajorV5)); 9721194b9cdSChangpeng Fang Version.push_back(Version.getDocument()->getNode(VersionMinorV5)); 9731194b9cdSChangpeng Fang getRootMetadata("amdhsa.version") = Version; 9741194b9cdSChangpeng Fang } 9751194b9cdSChangpeng Fang 9761194b9cdSChangpeng Fang void MetadataStreamerV5::emitHiddenKernelArgs(const MachineFunction &MF, 9771194b9cdSChangpeng Fang unsigned &Offset, 9781194b9cdSChangpeng Fang msgpack::ArrayDocNode Args) { 9791194b9cdSChangpeng Fang auto &Func = MF.getFunction(); 9801194b9cdSChangpeng Fang const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); 9811194b9cdSChangpeng Fang const Module *M = Func.getParent(); 9821194b9cdSChangpeng Fang auto &DL = M->getDataLayout(); 983d8f99bb6SSameer Sahasrabuddhe const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>(); 9841194b9cdSChangpeng Fang 9851194b9cdSChangpeng Fang auto Int64Ty = Type::getInt64Ty(Func.getContext()); 9861194b9cdSChangpeng Fang auto Int32Ty = Type::getInt32Ty(Func.getContext()); 9871194b9cdSChangpeng Fang auto Int16Ty = Type::getInt16Ty(Func.getContext()); 9881194b9cdSChangpeng Fang 9891194b9cdSChangpeng Fang emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_x", Offset, Args); 9901194b9cdSChangpeng Fang emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_y", Offset, Args); 9911194b9cdSChangpeng Fang emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_z", Offset, Args); 9921194b9cdSChangpeng Fang 9931194b9cdSChangpeng Fang emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_x", Offset, Args); 9941194b9cdSChangpeng Fang emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_y", Offset, Args); 9951194b9cdSChangpeng Fang emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_z", Offset, Args); 9961194b9cdSChangpeng Fang 9971194b9cdSChangpeng Fang emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_x", Offset, Args); 9981194b9cdSChangpeng Fang emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_y", Offset, Args); 9991194b9cdSChangpeng Fang emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_z", Offset, Args); 10001194b9cdSChangpeng Fang 10011194b9cdSChangpeng Fang // Reserved for hidden_tool_correlation_id. 10021194b9cdSChangpeng Fang Offset += 8; 10031194b9cdSChangpeng Fang 10041194b9cdSChangpeng Fang Offset += 8; // Reserved. 10051194b9cdSChangpeng Fang 10061194b9cdSChangpeng Fang emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset, Args); 10071194b9cdSChangpeng Fang emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset, Args); 10081194b9cdSChangpeng Fang emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset, Args); 10091194b9cdSChangpeng Fang 10101194b9cdSChangpeng Fang emitKernelArg(DL, Int16Ty, Align(2), "hidden_grid_dims", Offset, Args); 10111194b9cdSChangpeng Fang 10121194b9cdSChangpeng Fang Offset += 6; // Reserved. 10131194b9cdSChangpeng Fang auto Int8PtrTy = 10141194b9cdSChangpeng Fang Type::getInt8PtrTy(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS); 10151194b9cdSChangpeng Fang 10161194b9cdSChangpeng Fang if (M->getNamedMetadata("llvm.printf.fmts")) { 10171194b9cdSChangpeng Fang emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset, 10181194b9cdSChangpeng Fang Args); 10191194b9cdSChangpeng Fang } else 10201194b9cdSChangpeng Fang Offset += 8; // Skipped. 10211194b9cdSChangpeng Fang 1022d8f99bb6SSameer Sahasrabuddhe if (MFI.hasHostcallPtr()) { 10231194b9cdSChangpeng Fang emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset, 10241194b9cdSChangpeng Fang Args); 10251194b9cdSChangpeng Fang } else 10261194b9cdSChangpeng Fang Offset += 8; // Skipped. 10271194b9cdSChangpeng Fang 10281194b9cdSChangpeng Fang emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset, 10291194b9cdSChangpeng Fang Args); 10301194b9cdSChangpeng Fang 1031*ca62b1dbSChangpeng Fang if (MFI.hasHeapPtr()) 1032*ca62b1dbSChangpeng Fang emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_heap_v1", Offset, Args); 1033*ca62b1dbSChangpeng Fang else 1034*ca62b1dbSChangpeng Fang Offset += 8; // Skipped. 10351194b9cdSChangpeng Fang 10361194b9cdSChangpeng Fang if (Func.hasFnAttribute("calls-enqueue-kernel")) { 10371194b9cdSChangpeng Fang emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset, 10381194b9cdSChangpeng Fang Args); 10391194b9cdSChangpeng Fang emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset, 10401194b9cdSChangpeng Fang Args); 10411194b9cdSChangpeng Fang } else 10421194b9cdSChangpeng Fang Offset += 16; // Skipped. 10431194b9cdSChangpeng Fang 10441194b9cdSChangpeng Fang Offset += 72; // Reserved. 10451194b9cdSChangpeng Fang 10461194b9cdSChangpeng Fang // hidden_private_base and hidden_shared_base are only used by GFX8. 10471194b9cdSChangpeng Fang if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) { 10481194b9cdSChangpeng Fang emitKernelArg(DL, Int32Ty, Align(4), "hidden_private_base", Offset, Args); 10491194b9cdSChangpeng Fang emitKernelArg(DL, Int32Ty, Align(4), "hidden_shared_base", Offset, Args); 10501194b9cdSChangpeng Fang } else 10511194b9cdSChangpeng Fang Offset += 8; // Skipped. 10521194b9cdSChangpeng Fang 10531194b9cdSChangpeng Fang if (MFI.hasQueuePtr()) 10541194b9cdSChangpeng Fang emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_queue_ptr", Offset, Args); 10551194b9cdSChangpeng Fang } 10561194b9cdSChangpeng Fang 105701ce144dSScott Linder } // end namespace HSAMD 105801ce144dSScott Linder } // end namespace AMDGPU 105901ce144dSScott Linder } // end namespace llvm 1060