| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 1 | //===--- AMDGPUHSAMetadataStreamer.cpp --------------------------*- C++ -*-===// | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 2 | // | 
| Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | 4 | // See https://llvm.org/LICENSE.txt for license information. | 
|  | 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 6 | // | 
|  | 7 | //===----------------------------------------------------------------------===// | 
|  | 8 | // | 
|  | 9 | /// \file | 
| Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 10 | /// AMDGPU HSA Metadata Streamer. | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 11 | /// | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 15 | #include "AMDGPUHSAMetadataStreamer.h" | 
| Scott Linder | 2ad2c18 | 2018-07-10 17:31:32 +0000 | [diff] [blame] | 16 | #include "AMDGPU.h" | 
|  | 17 | #include "AMDGPUSubtarget.h" | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 18 | #include "MCTargetDesc/AMDGPUTargetStreamer.h" | 
| Scott Linder | 2ad2c18 | 2018-07-10 17:31:32 +0000 | [diff] [blame] | 19 | #include "SIMachineFunctionInfo.h" | 
|  | 20 | #include "SIProgramInfo.h" | 
| Konstantin Zhuravlyov | f0badd5 | 2018-07-10 16:12:51 +0000 | [diff] [blame] | 21 | #include "Utils/AMDGPUBaseInfo.h" | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 22 | #include "llvm/ADT/StringSwitch.h" | 
|  | 23 | #include "llvm/IR/Constants.h" | 
|  | 24 | #include "llvm/IR/Module.h" | 
| Konstantin Zhuravlyov | 1e2b878 | 2017-06-06 18:35:50 +0000 | [diff] [blame] | 25 | #include "llvm/Support/raw_ostream.h" | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 26 |  | 
|  | 27 | namespace llvm { | 
|  | 28 |  | 
| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 29 | static cl::opt<bool> DumpHSAMetadata( | 
|  | 30 | "amdgpu-dump-hsa-metadata", | 
|  | 31 | cl::desc("Dump AMDGPU HSA Metadata")); | 
|  | 32 | static cl::opt<bool> VerifyHSAMetadata( | 
|  | 33 | "amdgpu-verify-hsa-metadata", | 
|  | 34 | cl::desc("Verify AMDGPU HSA Metadata")); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 35 |  | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 36 | namespace AMDGPU { | 
| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 37 | namespace HSAMD { | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 38 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 39 | //===----------------------------------------------------------------------===// | 
|  | 40 | // HSAMetadataStreamerV2 | 
|  | 41 | //===----------------------------------------------------------------------===// | 
|  | 42 | void MetadataStreamerV2::dump(StringRef HSAMetadataString) const { | 
| Konstantin Zhuravlyov | 516651b | 2017-10-11 22:59:35 +0000 | [diff] [blame] | 43 | errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n'; | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 44 | } | 
|  | 45 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 46 | void MetadataStreamerV2::verify(StringRef HSAMetadataString) const { | 
| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 47 | errs() << "AMDGPU HSA Metadata Parser Test: "; | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 48 |  | 
| Konstantin Zhuravlyov | 516651b | 2017-10-11 22:59:35 +0000 | [diff] [blame] | 49 | HSAMD::Metadata FromHSAMetadataString; | 
|  | 50 | if (fromString(HSAMetadataString, FromHSAMetadataString)) { | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 51 | errs() << "FAIL\n"; | 
|  | 52 | return; | 
|  | 53 | } | 
|  | 54 |  | 
| Konstantin Zhuravlyov | 516651b | 2017-10-11 22:59:35 +0000 | [diff] [blame] | 55 | std::string ToHSAMetadataString; | 
|  | 56 | if (toString(FromHSAMetadataString, ToHSAMetadataString)) { | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 57 | errs() << "FAIL\n"; | 
|  | 58 | return; | 
|  | 59 | } | 
|  | 60 |  | 
| Konstantin Zhuravlyov | 516651b | 2017-10-11 22:59:35 +0000 | [diff] [blame] | 61 | errs() << (HSAMetadataString == ToHSAMetadataString ? "PASS" : "FAIL") | 
|  | 62 | << '\n'; | 
|  | 63 | if (HSAMetadataString != ToHSAMetadataString) { | 
|  | 64 | errs() << "Original input: " << HSAMetadataString << '\n' | 
|  | 65 | << "Produced output: " << ToHSAMetadataString << '\n'; | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 66 | } | 
|  | 67 | } | 
|  | 68 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 69 | AccessQualifier | 
|  | 70 | MetadataStreamerV2::getAccessQualifier(StringRef AccQual) const { | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 71 | if (AccQual.empty()) | 
|  | 72 | return AccessQualifier::Unknown; | 
|  | 73 |  | 
|  | 74 | return StringSwitch<AccessQualifier>(AccQual) | 
|  | 75 | .Case("read_only",  AccessQualifier::ReadOnly) | 
|  | 76 | .Case("write_only", AccessQualifier::WriteOnly) | 
|  | 77 | .Case("read_write", AccessQualifier::ReadWrite) | 
|  | 78 | .Default(AccessQualifier::Default); | 
|  | 79 | } | 
|  | 80 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 81 | AddressSpaceQualifier | 
|  | 82 | MetadataStreamerV2::getAddressSpaceQualifier( | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 83 | unsigned AddressSpace) const { | 
| Matt Arsenault | b998674 | 2018-09-10 02:23:30 +0000 | [diff] [blame] | 84 | switch (AddressSpace) { | 
|  | 85 | case AMDGPUAS::PRIVATE_ADDRESS: | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 86 | return AddressSpaceQualifier::Private; | 
| Matt Arsenault | b998674 | 2018-09-10 02:23:30 +0000 | [diff] [blame] | 87 | case AMDGPUAS::GLOBAL_ADDRESS: | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 88 | return AddressSpaceQualifier::Global; | 
| Matt Arsenault | b998674 | 2018-09-10 02:23:30 +0000 | [diff] [blame] | 89 | case AMDGPUAS::CONSTANT_ADDRESS: | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 90 | return AddressSpaceQualifier::Constant; | 
| Matt Arsenault | b998674 | 2018-09-10 02:23:30 +0000 | [diff] [blame] | 91 | case AMDGPUAS::LOCAL_ADDRESS: | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 92 | return AddressSpaceQualifier::Local; | 
| Matt Arsenault | b998674 | 2018-09-10 02:23:30 +0000 | [diff] [blame] | 93 | case AMDGPUAS::FLAT_ADDRESS: | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 94 | return AddressSpaceQualifier::Generic; | 
| Matt Arsenault | b998674 | 2018-09-10 02:23:30 +0000 | [diff] [blame] | 95 | case AMDGPUAS::REGION_ADDRESS: | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 96 | return AddressSpaceQualifier::Region; | 
| Matt Arsenault | b998674 | 2018-09-10 02:23:30 +0000 | [diff] [blame] | 97 | default: | 
|  | 98 | return AddressSpaceQualifier::Unknown; | 
|  | 99 | } | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 100 | } | 
|  | 101 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 102 | ValueKind MetadataStreamerV2::getValueKind(Type *Ty, StringRef TypeQual, | 
|  | 103 | StringRef BaseTypeName) const { | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 104 | if (TypeQual.find("pipe") != StringRef::npos) | 
|  | 105 | return ValueKind::Pipe; | 
|  | 106 |  | 
|  | 107 | return StringSwitch<ValueKind>(BaseTypeName) | 
| Konstantin Zhuravlyov | 54ba431 | 2017-04-25 20:38:26 +0000 | [diff] [blame] | 108 | .Case("image1d_t", ValueKind::Image) | 
|  | 109 | .Case("image1d_array_t", ValueKind::Image) | 
|  | 110 | .Case("image1d_buffer_t", ValueKind::Image) | 
|  | 111 | .Case("image2d_t", ValueKind::Image) | 
|  | 112 | .Case("image2d_array_t", ValueKind::Image) | 
|  | 113 | .Case("image2d_array_depth_t", ValueKind::Image) | 
|  | 114 | .Case("image2d_array_msaa_t", ValueKind::Image) | 
|  | 115 | .Case("image2d_array_msaa_depth_t", ValueKind::Image) | 
|  | 116 | .Case("image2d_depth_t", ValueKind::Image) | 
|  | 117 | .Case("image2d_msaa_t", ValueKind::Image) | 
|  | 118 | .Case("image2d_msaa_depth_t", ValueKind::Image) | 
|  | 119 | .Case("image3d_t", ValueKind::Image) | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 120 | .Case("sampler_t", ValueKind::Sampler) | 
|  | 121 | .Case("queue_t", ValueKind::Queue) | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 122 | .Default(isa<PointerType>(Ty) ? | 
|  | 123 | (Ty->getPointerAddressSpace() == | 
| Matt Arsenault | 0da6350 | 2018-08-31 05:49:54 +0000 | [diff] [blame] | 124 | AMDGPUAS::LOCAL_ADDRESS ? | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 125 | ValueKind::DynamicSharedPointer : | 
|  | 126 | ValueKind::GlobalBuffer) : | 
|  | 127 | ValueKind::ByValue); | 
|  | 128 | } | 
|  | 129 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 130 | ValueType MetadataStreamerV2::getValueType(Type *Ty, StringRef TypeName) const { | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 131 | switch (Ty->getTypeID()) { | 
|  | 132 | case Type::IntegerTyID: { | 
|  | 133 | auto Signed = !TypeName.startswith("u"); | 
|  | 134 | switch (Ty->getIntegerBitWidth()) { | 
|  | 135 | case 8: | 
|  | 136 | return Signed ? ValueType::I8 : ValueType::U8; | 
|  | 137 | case 16: | 
|  | 138 | return Signed ? ValueType::I16 : ValueType::U16; | 
|  | 139 | case 32: | 
|  | 140 | return Signed ? ValueType::I32 : ValueType::U32; | 
|  | 141 | case 64: | 
|  | 142 | return Signed ? ValueType::I64 : ValueType::U64; | 
|  | 143 | default: | 
|  | 144 | return ValueType::Struct; | 
|  | 145 | } | 
|  | 146 | } | 
|  | 147 | case Type::HalfTyID: | 
|  | 148 | return ValueType::F16; | 
|  | 149 | case Type::FloatTyID: | 
|  | 150 | return ValueType::F32; | 
|  | 151 | case Type::DoubleTyID: | 
|  | 152 | return ValueType::F64; | 
|  | 153 | case Type::PointerTyID: | 
|  | 154 | return getValueType(Ty->getPointerElementType(), TypeName); | 
|  | 155 | case Type::VectorTyID: | 
|  | 156 | return getValueType(Ty->getVectorElementType(), TypeName); | 
|  | 157 | default: | 
|  | 158 | return ValueType::Struct; | 
|  | 159 | } | 
|  | 160 | } | 
|  | 161 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 162 | std::string MetadataStreamerV2::getTypeName(Type *Ty, bool Signed) const { | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 163 | switch (Ty->getTypeID()) { | 
|  | 164 | case Type::IntegerTyID: { | 
|  | 165 | if (!Signed) | 
|  | 166 | return (Twine('u') + getTypeName(Ty, true)).str(); | 
|  | 167 |  | 
|  | 168 | auto BitWidth = Ty->getIntegerBitWidth(); | 
|  | 169 | switch (BitWidth) { | 
|  | 170 | case 8: | 
|  | 171 | return "char"; | 
|  | 172 | case 16: | 
|  | 173 | return "short"; | 
|  | 174 | case 32: | 
|  | 175 | return "int"; | 
|  | 176 | case 64: | 
|  | 177 | return "long"; | 
|  | 178 | default: | 
|  | 179 | return (Twine('i') + Twine(BitWidth)).str(); | 
|  | 180 | } | 
|  | 181 | } | 
|  | 182 | case Type::HalfTyID: | 
|  | 183 | return "half"; | 
|  | 184 | case Type::FloatTyID: | 
|  | 185 | return "float"; | 
|  | 186 | case Type::DoubleTyID: | 
|  | 187 | return "double"; | 
|  | 188 | case Type::VectorTyID: { | 
|  | 189 | auto VecTy = cast<VectorType>(Ty); | 
|  | 190 | auto ElTy = VecTy->getElementType(); | 
|  | 191 | auto NumElements = VecTy->getVectorNumElements(); | 
|  | 192 | return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str(); | 
|  | 193 | } | 
|  | 194 | default: | 
|  | 195 | return "unknown"; | 
|  | 196 | } | 
|  | 197 | } | 
|  | 198 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 199 | std::vector<uint32_t> | 
|  | 200 | MetadataStreamerV2::getWorkGroupDimensions(MDNode *Node) const { | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 201 | std::vector<uint32_t> Dims; | 
|  | 202 | if (Node->getNumOperands() != 3) | 
|  | 203 | return Dims; | 
|  | 204 |  | 
|  | 205 | for (auto &Op : Node->operands()) | 
|  | 206 | Dims.push_back(mdconst::extract<ConstantInt>(Op)->getZExtValue()); | 
|  | 207 | return Dims; | 
|  | 208 | } | 
|  | 209 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 210 | Kernel::CodeProps::Metadata | 
|  | 211 | MetadataStreamerV2::getHSACodeProps(const MachineFunction &MF, | 
|  | 212 | const SIProgramInfo &ProgramInfo) const { | 
| Tom Stellard | 5bfbae5 | 2018-07-11 20:59:01 +0000 | [diff] [blame] | 213 | const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>(); | 
| Scott Linder | 2ad2c18 | 2018-07-10 17:31:32 +0000 | [diff] [blame] | 214 | const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>(); | 
|  | 215 | HSAMD::Kernel::CodeProps::Metadata HSACodeProps; | 
|  | 216 | const Function &F = MF.getFunction(); | 
|  | 217 |  | 
| Matt Arsenault | 4bec7d4 | 2018-07-20 09:05:08 +0000 | [diff] [blame] | 218 | assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL || | 
|  | 219 | F.getCallingConv() == CallingConv::SPIR_KERNEL); | 
| Scott Linder | 2ad2c18 | 2018-07-10 17:31:32 +0000 | [diff] [blame] | 220 |  | 
| Matt Arsenault | 4bec7d4 | 2018-07-20 09:05:08 +0000 | [diff] [blame] | 221 | unsigned MaxKernArgAlign; | 
|  | 222 | HSACodeProps.mKernargSegmentSize = STM.getKernArgSegmentSize(F, | 
|  | 223 | MaxKernArgAlign); | 
| Scott Linder | 2ad2c18 | 2018-07-10 17:31:32 +0000 | [diff] [blame] | 224 | HSACodeProps.mGroupSegmentFixedSize = ProgramInfo.LDSSize; | 
|  | 225 | HSACodeProps.mPrivateSegmentFixedSize = ProgramInfo.ScratchSize; | 
| Matt Arsenault | 4bec7d4 | 2018-07-20 09:05:08 +0000 | [diff] [blame] | 226 | HSACodeProps.mKernargSegmentAlign = std::max(MaxKernArgAlign, 4u); | 
| Scott Linder | 2ad2c18 | 2018-07-10 17:31:32 +0000 | [diff] [blame] | 227 | HSACodeProps.mWavefrontSize = STM.getWavefrontSize(); | 
|  | 228 | HSACodeProps.mNumSGPRs = ProgramInfo.NumSGPR; | 
|  | 229 | HSACodeProps.mNumVGPRs = ProgramInfo.NumVGPR; | 
|  | 230 | HSACodeProps.mMaxFlatWorkGroupSize = MFI.getMaxFlatWorkGroupSize(); | 
|  | 231 | HSACodeProps.mIsDynamicCallStack = ProgramInfo.DynamicCallStack; | 
|  | 232 | HSACodeProps.mIsXNACKEnabled = STM.isXNACKEnabled(); | 
|  | 233 | HSACodeProps.mNumSpilledSGPRs = MFI.getNumSpilledSGPRs(); | 
|  | 234 | HSACodeProps.mNumSpilledVGPRs = MFI.getNumSpilledVGPRs(); | 
|  | 235 |  | 
|  | 236 | return HSACodeProps; | 
|  | 237 | } | 
|  | 238 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 239 | Kernel::DebugProps::Metadata | 
|  | 240 | MetadataStreamerV2::getHSADebugProps(const MachineFunction &MF, | 
|  | 241 | const SIProgramInfo &ProgramInfo) const { | 
| Matt Arsenault | aa6fb4c | 2019-02-21 23:27:46 +0000 | [diff] [blame] | 242 | return HSAMD::Kernel::DebugProps::Metadata(); | 
| Scott Linder | 2ad2c18 | 2018-07-10 17:31:32 +0000 | [diff] [blame] | 243 | } | 
|  | 244 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 245 | void MetadataStreamerV2::emitVersion() { | 
| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 246 | auto &Version = HSAMetadata.mVersion; | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 247 |  | 
| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 248 | Version.push_back(VersionMajor); | 
|  | 249 | Version.push_back(VersionMinor); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 250 | } | 
|  | 251 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 252 | void MetadataStreamerV2::emitPrintf(const Module &Mod) { | 
| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 253 | auto &Printf = HSAMetadata.mPrintf; | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 254 |  | 
|  | 255 | auto Node = Mod.getNamedMetadata("llvm.printf.fmts"); | 
|  | 256 | if (!Node) | 
|  | 257 | return; | 
|  | 258 |  | 
|  | 259 | for (auto Op : Node->operands()) | 
|  | 260 | if (Op->getNumOperands()) | 
|  | 261 | Printf.push_back(cast<MDString>(Op->getOperand(0))->getString()); | 
|  | 262 | } | 
|  | 263 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 264 | void MetadataStreamerV2::emitKernelLanguage(const Function &Func) { | 
| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 265 | auto &Kernel = HSAMetadata.mKernels.back(); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 266 |  | 
|  | 267 | // TODO: What about other languages? | 
|  | 268 | auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version"); | 
|  | 269 | if (!Node || !Node->getNumOperands()) | 
|  | 270 | return; | 
|  | 271 | auto Op0 = Node->getOperand(0); | 
|  | 272 | if (Op0->getNumOperands() <= 1) | 
|  | 273 | return; | 
|  | 274 |  | 
|  | 275 | Kernel.mLanguage = "OpenCL C"; | 
|  | 276 | Kernel.mLanguageVersion.push_back( | 
|  | 277 | mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue()); | 
|  | 278 | Kernel.mLanguageVersion.push_back( | 
|  | 279 | mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue()); | 
|  | 280 | } | 
|  | 281 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 282 | void MetadataStreamerV2::emitKernelAttrs(const Function &Func) { | 
| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 283 | auto &Attrs = HSAMetadata.mKernels.back().mAttrs; | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 284 |  | 
|  | 285 | if (auto Node = Func.getMetadata("reqd_work_group_size")) | 
|  | 286 | Attrs.mReqdWorkGroupSize = getWorkGroupDimensions(Node); | 
|  | 287 | if (auto Node = Func.getMetadata("work_group_size_hint")) | 
|  | 288 | Attrs.mWorkGroupSizeHint = getWorkGroupDimensions(Node); | 
|  | 289 | if (auto Node = Func.getMetadata("vec_type_hint")) { | 
|  | 290 | Attrs.mVecTypeHint = getTypeName( | 
|  | 291 | cast<ValueAsMetadata>(Node->getOperand(0))->getType(), | 
|  | 292 | mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()); | 
|  | 293 | } | 
| Yaxun Liu | de4b88d | 2017-10-10 19:39:48 +0000 | [diff] [blame] | 294 | if (Func.hasFnAttribute("runtime-handle")) { | 
|  | 295 | Attrs.mRuntimeHandle = | 
|  | 296 | Func.getFnAttribute("runtime-handle").getValueAsString().str(); | 
|  | 297 | } | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 298 | } | 
|  | 299 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 300 | void MetadataStreamerV2::emitKernelArgs(const Function &Func) { | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 301 | for (auto &Arg : Func.args()) | 
|  | 302 | emitKernelArg(Arg); | 
|  | 303 |  | 
| Konstantin Zhuravlyov | f0badd5 | 2018-07-10 16:12:51 +0000 | [diff] [blame] | 304 | emitHiddenKernelArgs(Func); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 305 | } | 
|  | 306 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 307 | void MetadataStreamerV2::emitKernelArg(const Argument &Arg) { | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 308 | auto Func = Arg.getParent(); | 
|  | 309 | auto ArgNo = Arg.getArgNo(); | 
|  | 310 | const MDNode *Node; | 
|  | 311 |  | 
| Konstantin Zhuravlyov | a01d8b0 | 2017-10-14 19:03:51 +0000 | [diff] [blame] | 312 | StringRef Name; | 
|  | 313 | Node = Func->getMetadata("kernel_arg_name"); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 314 | if (Node && ArgNo < Node->getNumOperands()) | 
| Konstantin Zhuravlyov | a01d8b0 | 2017-10-14 19:03:51 +0000 | [diff] [blame] | 315 | Name = cast<MDString>(Node->getOperand(ArgNo))->getString(); | 
| Konstantin Zhuravlyov | e30f88f | 2017-12-08 19:22:12 +0000 | [diff] [blame] | 316 | else if (Arg.hasName()) | 
|  | 317 | Name = Arg.getName(); | 
| Konstantin Zhuravlyov | a01d8b0 | 2017-10-14 19:03:51 +0000 | [diff] [blame] | 318 |  | 
|  | 319 | StringRef TypeName; | 
|  | 320 | Node = Func->getMetadata("kernel_arg_type"); | 
|  | 321 | if (Node && ArgNo < Node->getNumOperands()) | 
|  | 322 | TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString(); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 323 |  | 
|  | 324 | StringRef BaseTypeName; | 
|  | 325 | Node = Func->getMetadata("kernel_arg_base_type"); | 
|  | 326 | if (Node && ArgNo < Node->getNumOperands()) | 
|  | 327 | BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString(); | 
|  | 328 |  | 
|  | 329 | StringRef AccQual; | 
| Stanislav Mekhanoshin | eff0bc7 | 2017-04-14 19:11:40 +0000 | [diff] [blame] | 330 | if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() && | 
|  | 331 | Arg.hasNoAliasAttr()) { | 
|  | 332 | AccQual = "read_only"; | 
|  | 333 | } else { | 
|  | 334 | Node = Func->getMetadata("kernel_arg_access_qual"); | 
|  | 335 | if (Node && ArgNo < Node->getNumOperands()) | 
|  | 336 | AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString(); | 
|  | 337 | } | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 338 |  | 
| Konstantin Zhuravlyov | a01d8b0 | 2017-10-14 19:03:51 +0000 | [diff] [blame] | 339 | StringRef TypeQual; | 
|  | 340 | Node = Func->getMetadata("kernel_arg_type_qual"); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 341 | if (Node && ArgNo < Node->getNumOperands()) | 
| Konstantin Zhuravlyov | a01d8b0 | 2017-10-14 19:03:51 +0000 | [diff] [blame] | 342 | TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString(); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 343 |  | 
| Matt Arsenault | 73eeb42 | 2018-06-25 14:29:04 +0000 | [diff] [blame] | 344 | Type *Ty = Arg.getType(); | 
|  | 345 | const DataLayout &DL = Func->getParent()->getDataLayout(); | 
|  | 346 |  | 
|  | 347 | unsigned PointeeAlign = 0; | 
|  | 348 | if (auto PtrTy = dyn_cast<PointerType>(Ty)) { | 
| Matt Arsenault | 0da6350 | 2018-08-31 05:49:54 +0000 | [diff] [blame] | 349 | if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) { | 
| Matt Arsenault | 73eeb42 | 2018-06-25 14:29:04 +0000 | [diff] [blame] | 350 | PointeeAlign = Arg.getParamAlignment(); | 
|  | 351 | if (PointeeAlign == 0) | 
|  | 352 | PointeeAlign = DL.getABITypeAlignment(PtrTy->getElementType()); | 
|  | 353 | } | 
|  | 354 | } | 
|  | 355 |  | 
|  | 356 | emitKernelArg(DL, Ty, getValueKind(Arg.getType(), TypeQual, BaseTypeName), | 
|  | 357 | PointeeAlign, Name, TypeName, BaseTypeName, AccQual, TypeQual); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 358 | } | 
|  | 359 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 360 | void MetadataStreamerV2::emitKernelArg(const DataLayout &DL, Type *Ty, | 
|  | 361 | ValueKind ValueKind, | 
|  | 362 | unsigned PointeeAlign, StringRef Name, | 
|  | 363 | StringRef TypeName, | 
|  | 364 | StringRef BaseTypeName, | 
|  | 365 | StringRef AccQual, StringRef TypeQual) { | 
| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 366 | HSAMetadata.mKernels.back().mArgs.push_back(Kernel::Arg::Metadata()); | 
|  | 367 | auto &Arg = HSAMetadata.mKernels.back().mArgs.back(); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 368 |  | 
| Konstantin Zhuravlyov | a01d8b0 | 2017-10-14 19:03:51 +0000 | [diff] [blame] | 369 | Arg.mName = Name; | 
|  | 370 | Arg.mTypeName = TypeName; | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 371 | Arg.mSize = DL.getTypeAllocSize(Ty); | 
|  | 372 | Arg.mAlign = DL.getABITypeAlignment(Ty); | 
|  | 373 | Arg.mValueKind = ValueKind; | 
|  | 374 | Arg.mValueType = getValueType(Ty, BaseTypeName); | 
| Matt Arsenault | 73eeb42 | 2018-06-25 14:29:04 +0000 | [diff] [blame] | 375 | Arg.mPointeeAlign = PointeeAlign; | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 376 |  | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 377 | if (auto PtrTy = dyn_cast<PointerType>(Ty)) | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 378 | Arg.mAddrSpaceQual = getAddressSpaceQualifier(PtrTy->getAddressSpace()); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 379 |  | 
| Konstantin Zhuravlyov | a01d8b0 | 2017-10-14 19:03:51 +0000 | [diff] [blame] | 380 | Arg.mAccQual = getAccessQualifier(AccQual); | 
|  | 381 |  | 
|  | 382 | // TODO: Emit Arg.mActualAccQual. | 
|  | 383 |  | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 384 | SmallVector<StringRef, 1> SplitTypeQuals; | 
|  | 385 | TypeQual.split(SplitTypeQuals, " ", -1, false); | 
|  | 386 | for (StringRef Key : SplitTypeQuals) { | 
|  | 387 | auto P = StringSwitch<bool*>(Key) | 
|  | 388 | .Case("const",    &Arg.mIsConst) | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 389 | .Case("restrict", &Arg.mIsRestrict) | 
|  | 390 | .Case("volatile", &Arg.mIsVolatile) | 
| Konstantin Zhuravlyov | a01d8b0 | 2017-10-14 19:03:51 +0000 | [diff] [blame] | 391 | .Case("pipe",     &Arg.mIsPipe) | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 392 | .Default(nullptr); | 
|  | 393 | if (P) | 
|  | 394 | *P = true; | 
|  | 395 | } | 
| Konstantin Zhuravlyov | a780ffa | 2017-03-22 23:10:46 +0000 | [diff] [blame] | 396 | } | 
|  | 397 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 398 | void MetadataStreamerV2::emitHiddenKernelArgs(const Function &Func) { | 
| Konstantin Zhuravlyov | f0badd5 | 2018-07-10 16:12:51 +0000 | [diff] [blame] | 399 | int HiddenArgNumBytes = | 
|  | 400 | getIntegerAttribute(Func, "amdgpu-implicitarg-num-bytes", 0); | 
|  | 401 |  | 
|  | 402 | if (!HiddenArgNumBytes) | 
|  | 403 | return; | 
|  | 404 |  | 
|  | 405 | auto &DL = Func.getParent()->getDataLayout(); | 
|  | 406 | auto Int64Ty = Type::getInt64Ty(Func.getContext()); | 
|  | 407 |  | 
|  | 408 | if (HiddenArgNumBytes >= 8) | 
|  | 409 | emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetX); | 
|  | 410 | if (HiddenArgNumBytes >= 16) | 
|  | 411 | emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetY); | 
|  | 412 | if (HiddenArgNumBytes >= 24) | 
|  | 413 | emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetZ); | 
|  | 414 |  | 
|  | 415 | auto Int8PtrTy = Type::getInt8PtrTy(Func.getContext(), | 
| Matt Arsenault | 0da6350 | 2018-08-31 05:49:54 +0000 | [diff] [blame] | 416 | AMDGPUAS::GLOBAL_ADDRESS); | 
| Konstantin Zhuravlyov | f0badd5 | 2018-07-10 16:12:51 +0000 | [diff] [blame] | 417 |  | 
|  | 418 | // Emit "printf buffer" argument if printf is used, otherwise emit dummy | 
|  | 419 | // "none" argument. | 
|  | 420 | if (HiddenArgNumBytes >= 32) { | 
|  | 421 | if (Func.getParent()->getNamedMetadata("llvm.printf.fmts")) | 
|  | 422 | emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenPrintfBuffer); | 
|  | 423 | else | 
|  | 424 | emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone); | 
|  | 425 | } | 
|  | 426 |  | 
|  | 427 | // Emit "default queue" and "completion action" arguments if enqueue kernel is | 
|  | 428 | // used, otherwise emit dummy "none" arguments. | 
|  | 429 | if (HiddenArgNumBytes >= 48) { | 
|  | 430 | if (Func.hasFnAttribute("calls-enqueue-kernel")) { | 
|  | 431 | emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenDefaultQueue); | 
|  | 432 | emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenCompletionAction); | 
|  | 433 | } else { | 
|  | 434 | emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone); | 
|  | 435 | emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone); | 
|  | 436 | } | 
|  | 437 | } | 
| Yaxun Liu | a624135 | 2019-07-05 16:05:17 +0000 | [diff] [blame] | 438 |  | 
|  | 439 | // Emit the pointer argument for multi-grid object. | 
|  | 440 | if (HiddenArgNumBytes >= 56) | 
|  | 441 | emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenMultiGridSyncArg); | 
| Konstantin Zhuravlyov | f0badd5 | 2018-07-10 16:12:51 +0000 | [diff] [blame] | 442 | } | 
|  | 443 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 444 | bool MetadataStreamerV2::emitTo(AMDGPUTargetStreamer &TargetStreamer) { | 
|  | 445 | return TargetStreamer.EmitHSAMetadata(getHSAMetadata()); | 
|  | 446 | } | 
|  | 447 |  | 
|  | 448 | void MetadataStreamerV2::begin(const Module &Mod) { | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 449 | emitVersion(); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 450 | emitPrintf(Mod); | 
|  | 451 | } | 
|  | 452 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 453 | void MetadataStreamerV2::end() { | 
| Konstantin Zhuravlyov | 516651b | 2017-10-11 22:59:35 +0000 | [diff] [blame] | 454 | std::string HSAMetadataString; | 
| Konstantin Zhuravlyov | 63e87f5 | 2017-10-12 17:34:05 +0000 | [diff] [blame] | 455 | if (toString(HSAMetadata, HSAMetadataString)) | 
| Konstantin Zhuravlyov | 516651b | 2017-10-11 22:59:35 +0000 | [diff] [blame] | 456 | return; | 
|  | 457 |  | 
|  | 458 | if (DumpHSAMetadata) | 
|  | 459 | dump(HSAMetadataString); | 
|  | 460 | if (VerifyHSAMetadata) | 
|  | 461 | verify(HSAMetadataString); | 
|  | 462 | } | 
|  | 463 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 464 | void MetadataStreamerV2::emitKernel(const MachineFunction &MF, | 
|  | 465 | const SIProgramInfo &ProgramInfo) { | 
| Scott Linder | 2ad2c18 | 2018-07-10 17:31:32 +0000 | [diff] [blame] | 466 | auto &Func = MF.getFunction(); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 467 | if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL) | 
|  | 468 | return; | 
|  | 469 |  | 
| Matt Arsenault | 4bec7d4 | 2018-07-20 09:05:08 +0000 | [diff] [blame] | 470 | auto CodeProps = getHSACodeProps(MF, ProgramInfo); | 
|  | 471 | auto DebugProps = getHSADebugProps(MF, ProgramInfo); | 
|  | 472 |  | 
| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 473 | HSAMetadata.mKernels.push_back(Kernel::Metadata()); | 
|  | 474 | auto &Kernel = HSAMetadata.mKernels.back(); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 475 |  | 
|  | 476 | Kernel.mName = Func.getName(); | 
| Konstantin Zhuravlyov | a01d8b0 | 2017-10-14 19:03:51 +0000 | [diff] [blame] | 477 | Kernel.mSymbolName = (Twine(Func.getName()) + Twine("@kd")).str(); | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 478 | emitKernelLanguage(Func); | 
|  | 479 | emitKernelAttrs(Func); | 
|  | 480 | emitKernelArgs(Func); | 
| Konstantin Zhuravlyov | a01d8b0 | 2017-10-14 19:03:51 +0000 | [diff] [blame] | 481 | HSAMetadata.mKernels.back().mCodeProps = CodeProps; | 
|  | 482 | HSAMetadata.mKernels.back().mDebugProps = DebugProps; | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 483 | } | 
|  | 484 |  | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 485 | //===----------------------------------------------------------------------===// | 
|  | 486 | // HSAMetadataStreamerV3 | 
|  | 487 | //===----------------------------------------------------------------------===// | 
|  | 488 |  | 
|  | 489 | void MetadataStreamerV3::dump(StringRef HSAMetadataString) const { | 
|  | 490 | errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n'; | 
|  | 491 | } | 
|  | 492 |  | 
|  | 493 | void MetadataStreamerV3::verify(StringRef HSAMetadataString) const { | 
|  | 494 | errs() << "AMDGPU HSA Metadata Parser Test: "; | 
|  | 495 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 496 | msgpack::Document FromHSAMetadataString; | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 497 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 498 | if (!FromHSAMetadataString.fromYAML(HSAMetadataString)) { | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 499 | errs() << "FAIL\n"; | 
|  | 500 | return; | 
|  | 501 | } | 
|  | 502 |  | 
|  | 503 | std::string ToHSAMetadataString; | 
|  | 504 | raw_string_ostream StrOS(ToHSAMetadataString); | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 505 | FromHSAMetadataString.toYAML(StrOS); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 506 |  | 
|  | 507 | errs() << (HSAMetadataString == StrOS.str() ? "PASS" : "FAIL") << '\n'; | 
|  | 508 | if (HSAMetadataString != ToHSAMetadataString) { | 
|  | 509 | errs() << "Original input: " << HSAMetadataString << '\n' | 
|  | 510 | << "Produced output: " << StrOS.str() << '\n'; | 
|  | 511 | } | 
|  | 512 | } | 
|  | 513 |  | 
|  | 514 | Optional<StringRef> | 
|  | 515 | MetadataStreamerV3::getAccessQualifier(StringRef AccQual) const { | 
|  | 516 | return StringSwitch<Optional<StringRef>>(AccQual) | 
|  | 517 | .Case("read_only", StringRef("read_only")) | 
|  | 518 | .Case("write_only", StringRef("write_only")) | 
|  | 519 | .Case("read_write", StringRef("read_write")) | 
|  | 520 | .Default(None); | 
|  | 521 | } | 
|  | 522 |  | 
|  | 523 | Optional<StringRef> | 
|  | 524 | MetadataStreamerV3::getAddressSpaceQualifier(unsigned AddressSpace) const { | 
|  | 525 | switch (AddressSpace) { | 
|  | 526 | case AMDGPUAS::PRIVATE_ADDRESS: | 
|  | 527 | return StringRef("private"); | 
|  | 528 | case AMDGPUAS::GLOBAL_ADDRESS: | 
|  | 529 | return StringRef("global"); | 
|  | 530 | case AMDGPUAS::CONSTANT_ADDRESS: | 
|  | 531 | return StringRef("constant"); | 
|  | 532 | case AMDGPUAS::LOCAL_ADDRESS: | 
|  | 533 | return StringRef("local"); | 
|  | 534 | case AMDGPUAS::FLAT_ADDRESS: | 
|  | 535 | return StringRef("generic"); | 
|  | 536 | case AMDGPUAS::REGION_ADDRESS: | 
|  | 537 | return StringRef("region"); | 
|  | 538 | default: | 
|  | 539 | return None; | 
|  | 540 | } | 
|  | 541 | } | 
|  | 542 |  | 
|  | 543 | StringRef MetadataStreamerV3::getValueKind(Type *Ty, StringRef TypeQual, | 
|  | 544 | StringRef BaseTypeName) const { | 
|  | 545 | if (TypeQual.find("pipe") != StringRef::npos) | 
|  | 546 | return "pipe"; | 
|  | 547 |  | 
|  | 548 | return StringSwitch<StringRef>(BaseTypeName) | 
|  | 549 | .Case("image1d_t", "image") | 
|  | 550 | .Case("image1d_array_t", "image") | 
|  | 551 | .Case("image1d_buffer_t", "image") | 
|  | 552 | .Case("image2d_t", "image") | 
|  | 553 | .Case("image2d_array_t", "image") | 
|  | 554 | .Case("image2d_array_depth_t", "image") | 
|  | 555 | .Case("image2d_array_msaa_t", "image") | 
|  | 556 | .Case("image2d_array_msaa_depth_t", "image") | 
|  | 557 | .Case("image2d_depth_t", "image") | 
|  | 558 | .Case("image2d_msaa_t", "image") | 
|  | 559 | .Case("image2d_msaa_depth_t", "image") | 
|  | 560 | .Case("image3d_t", "image") | 
|  | 561 | .Case("sampler_t", "sampler") | 
|  | 562 | .Case("queue_t", "queue") | 
|  | 563 | .Default(isa<PointerType>(Ty) | 
|  | 564 | ? (Ty->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS | 
|  | 565 | ? "dynamic_shared_pointer" | 
|  | 566 | : "global_buffer") | 
|  | 567 | : "by_value"); | 
|  | 568 | } | 
|  | 569 |  | 
|  | 570 | StringRef MetadataStreamerV3::getValueType(Type *Ty, StringRef TypeName) const { | 
|  | 571 | switch (Ty->getTypeID()) { | 
|  | 572 | case Type::IntegerTyID: { | 
|  | 573 | auto Signed = !TypeName.startswith("u"); | 
|  | 574 | switch (Ty->getIntegerBitWidth()) { | 
|  | 575 | case 8: | 
|  | 576 | return Signed ? "i8" : "u8"; | 
|  | 577 | case 16: | 
|  | 578 | return Signed ? "i16" : "u16"; | 
|  | 579 | case 32: | 
|  | 580 | return Signed ? "i32" : "u32"; | 
|  | 581 | case 64: | 
|  | 582 | return Signed ? "i64" : "u64"; | 
|  | 583 | default: | 
|  | 584 | return "struct"; | 
|  | 585 | } | 
|  | 586 | } | 
|  | 587 | case Type::HalfTyID: | 
|  | 588 | return "f16"; | 
|  | 589 | case Type::FloatTyID: | 
|  | 590 | return "f32"; | 
|  | 591 | case Type::DoubleTyID: | 
|  | 592 | return "f64"; | 
|  | 593 | case Type::PointerTyID: | 
|  | 594 | return getValueType(Ty->getPointerElementType(), TypeName); | 
|  | 595 | case Type::VectorTyID: | 
|  | 596 | return getValueType(Ty->getVectorElementType(), TypeName); | 
|  | 597 | default: | 
|  | 598 | return "struct"; | 
|  | 599 | } | 
|  | 600 | } | 
|  | 601 |  | 
|  | 602 | std::string MetadataStreamerV3::getTypeName(Type *Ty, bool Signed) const { | 
|  | 603 | switch (Ty->getTypeID()) { | 
|  | 604 | case Type::IntegerTyID: { | 
|  | 605 | if (!Signed) | 
|  | 606 | return (Twine('u') + getTypeName(Ty, true)).str(); | 
|  | 607 |  | 
|  | 608 | auto BitWidth = Ty->getIntegerBitWidth(); | 
|  | 609 | switch (BitWidth) { | 
|  | 610 | case 8: | 
|  | 611 | return "char"; | 
|  | 612 | case 16: | 
|  | 613 | return "short"; | 
|  | 614 | case 32: | 
|  | 615 | return "int"; | 
|  | 616 | case 64: | 
|  | 617 | return "long"; | 
|  | 618 | default: | 
|  | 619 | return (Twine('i') + Twine(BitWidth)).str(); | 
|  | 620 | } | 
|  | 621 | } | 
|  | 622 | case Type::HalfTyID: | 
|  | 623 | return "half"; | 
|  | 624 | case Type::FloatTyID: | 
|  | 625 | return "float"; | 
|  | 626 | case Type::DoubleTyID: | 
|  | 627 | return "double"; | 
|  | 628 | case Type::VectorTyID: { | 
|  | 629 | auto VecTy = cast<VectorType>(Ty); | 
|  | 630 | auto ElTy = VecTy->getElementType(); | 
|  | 631 | auto NumElements = VecTy->getVectorNumElements(); | 
|  | 632 | return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str(); | 
|  | 633 | } | 
|  | 634 | default: | 
|  | 635 | return "unknown"; | 
|  | 636 | } | 
|  | 637 | } | 
|  | 638 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 639 | msgpack::ArrayDocNode | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 640 | MetadataStreamerV3::getWorkGroupDimensions(MDNode *Node) const { | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 641 | auto Dims = HSAMetadataDoc->getArrayNode(); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 642 | if (Node->getNumOperands() != 3) | 
|  | 643 | return Dims; | 
|  | 644 |  | 
|  | 645 | for (auto &Op : Node->operands()) | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 646 | Dims.push_back(Dims.getDocument()->getNode( | 
|  | 647 | uint64_t(mdconst::extract<ConstantInt>(Op)->getZExtValue()))); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 648 | return Dims; | 
|  | 649 | } | 
|  | 650 |  | 
|  | 651 | void MetadataStreamerV3::emitVersion() { | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 652 | auto Version = HSAMetadataDoc->getArrayNode(); | 
|  | 653 | Version.push_back(Version.getDocument()->getNode(VersionMajor)); | 
|  | 654 | Version.push_back(Version.getDocument()->getNode(VersionMinor)); | 
|  | 655 | getRootMetadata("amdhsa.version") = Version; | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 656 | } | 
|  | 657 |  | 
|  | 658 | void MetadataStreamerV3::emitPrintf(const Module &Mod) { | 
|  | 659 | auto Node = Mod.getNamedMetadata("llvm.printf.fmts"); | 
|  | 660 | if (!Node) | 
|  | 661 | return; | 
|  | 662 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 663 | auto Printf = HSAMetadataDoc->getArrayNode(); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 664 | for (auto Op : Node->operands()) | 
|  | 665 | if (Op->getNumOperands()) | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 666 | Printf.push_back(Printf.getDocument()->getNode( | 
|  | 667 | cast<MDString>(Op->getOperand(0))->getString(), /*Copy=*/true)); | 
|  | 668 | getRootMetadata("amdhsa.printf") = Printf; | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 669 | } | 
|  | 670 |  | 
|  | 671 | void MetadataStreamerV3::emitKernelLanguage(const Function &Func, | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 672 | msgpack::MapDocNode Kern) { | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 673 | // TODO: What about other languages? | 
|  | 674 | auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version"); | 
|  | 675 | if (!Node || !Node->getNumOperands()) | 
|  | 676 | return; | 
|  | 677 | auto Op0 = Node->getOperand(0); | 
|  | 678 | if (Op0->getNumOperands() <= 1) | 
|  | 679 | return; | 
|  | 680 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 681 | Kern[".language"] = Kern.getDocument()->getNode("OpenCL C"); | 
|  | 682 | auto LanguageVersion = Kern.getDocument()->getArrayNode(); | 
|  | 683 | LanguageVersion.push_back(Kern.getDocument()->getNode( | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 684 | mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue())); | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 685 | LanguageVersion.push_back(Kern.getDocument()->getNode( | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 686 | mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue())); | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 687 | Kern[".language_version"] = LanguageVersion; | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 688 | } | 
|  | 689 |  | 
|  | 690 | void MetadataStreamerV3::emitKernelAttrs(const Function &Func, | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 691 | msgpack::MapDocNode Kern) { | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 692 |  | 
|  | 693 | if (auto Node = Func.getMetadata("reqd_work_group_size")) | 
|  | 694 | Kern[".reqd_workgroup_size"] = getWorkGroupDimensions(Node); | 
|  | 695 | if (auto Node = Func.getMetadata("work_group_size_hint")) | 
|  | 696 | Kern[".workgroup_size_hint"] = getWorkGroupDimensions(Node); | 
|  | 697 | if (auto Node = Func.getMetadata("vec_type_hint")) { | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 698 | Kern[".vec_type_hint"] = Kern.getDocument()->getNode( | 
|  | 699 | getTypeName( | 
|  | 700 | cast<ValueAsMetadata>(Node->getOperand(0))->getType(), | 
|  | 701 | mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()), | 
|  | 702 | /*Copy=*/true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 703 | } | 
|  | 704 | if (Func.hasFnAttribute("runtime-handle")) { | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 705 | Kern[".device_enqueue_symbol"] = Kern.getDocument()->getNode( | 
|  | 706 | Func.getFnAttribute("runtime-handle").getValueAsString().str(), | 
|  | 707 | /*Copy=*/true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 708 | } | 
|  | 709 | } | 
|  | 710 |  | 
|  | 711 | void MetadataStreamerV3::emitKernelArgs(const Function &Func, | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 712 | msgpack::MapDocNode Kern) { | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 713 | unsigned Offset = 0; | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 714 | auto Args = HSAMetadataDoc->getArrayNode(); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 715 | for (auto &Arg : Func.args()) | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 716 | emitKernelArg(Arg, Offset, Args); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 717 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 718 | emitHiddenKernelArgs(Func, Offset, Args); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 719 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 720 | Kern[".args"] = Args; | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 721 | } | 
|  | 722 |  | 
|  | 723 | void MetadataStreamerV3::emitKernelArg(const Argument &Arg, unsigned &Offset, | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 724 | msgpack::ArrayDocNode Args) { | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 725 | auto Func = Arg.getParent(); | 
|  | 726 | auto ArgNo = Arg.getArgNo(); | 
|  | 727 | const MDNode *Node; | 
|  | 728 |  | 
|  | 729 | StringRef Name; | 
|  | 730 | Node = Func->getMetadata("kernel_arg_name"); | 
|  | 731 | if (Node && ArgNo < Node->getNumOperands()) | 
|  | 732 | Name = cast<MDString>(Node->getOperand(ArgNo))->getString(); | 
|  | 733 | else if (Arg.hasName()) | 
|  | 734 | Name = Arg.getName(); | 
|  | 735 |  | 
|  | 736 | StringRef TypeName; | 
|  | 737 | Node = Func->getMetadata("kernel_arg_type"); | 
|  | 738 | if (Node && ArgNo < Node->getNumOperands()) | 
|  | 739 | TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString(); | 
|  | 740 |  | 
|  | 741 | StringRef BaseTypeName; | 
|  | 742 | Node = Func->getMetadata("kernel_arg_base_type"); | 
|  | 743 | if (Node && ArgNo < Node->getNumOperands()) | 
|  | 744 | BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString(); | 
|  | 745 |  | 
|  | 746 | StringRef AccQual; | 
|  | 747 | if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() && | 
|  | 748 | Arg.hasNoAliasAttr()) { | 
|  | 749 | AccQual = "read_only"; | 
|  | 750 | } else { | 
|  | 751 | Node = Func->getMetadata("kernel_arg_access_qual"); | 
|  | 752 | if (Node && ArgNo < Node->getNumOperands()) | 
|  | 753 | AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString(); | 
|  | 754 | } | 
|  | 755 |  | 
|  | 756 | StringRef TypeQual; | 
|  | 757 | Node = Func->getMetadata("kernel_arg_type_qual"); | 
|  | 758 | if (Node && ArgNo < Node->getNumOperands()) | 
|  | 759 | TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString(); | 
|  | 760 |  | 
|  | 761 | Type *Ty = Arg.getType(); | 
|  | 762 | const DataLayout &DL = Func->getParent()->getDataLayout(); | 
|  | 763 |  | 
|  | 764 | unsigned PointeeAlign = 0; | 
|  | 765 | if (auto PtrTy = dyn_cast<PointerType>(Ty)) { | 
|  | 766 | if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) { | 
|  | 767 | PointeeAlign = Arg.getParamAlignment(); | 
|  | 768 | if (PointeeAlign == 0) | 
|  | 769 | PointeeAlign = DL.getABITypeAlignment(PtrTy->getElementType()); | 
|  | 770 | } | 
|  | 771 | } | 
|  | 772 |  | 
|  | 773 | emitKernelArg(Func->getParent()->getDataLayout(), Arg.getType(), | 
|  | 774 | getValueKind(Arg.getType(), TypeQual, BaseTypeName), Offset, | 
|  | 775 | Args, PointeeAlign, Name, TypeName, BaseTypeName, AccQual, | 
|  | 776 | TypeQual); | 
|  | 777 | } | 
|  | 778 |  | 
|  | 779 | void MetadataStreamerV3::emitKernelArg(const DataLayout &DL, Type *Ty, | 
|  | 780 | StringRef ValueKind, unsigned &Offset, | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 781 | msgpack::ArrayDocNode Args, | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 782 | unsigned PointeeAlign, StringRef Name, | 
|  | 783 | StringRef TypeName, | 
|  | 784 | StringRef BaseTypeName, | 
|  | 785 | StringRef AccQual, StringRef TypeQual) { | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 786 | auto Arg = Args.getDocument()->getMapNode(); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 787 |  | 
|  | 788 | if (!Name.empty()) | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 789 | Arg[".name"] = Arg.getDocument()->getNode(Name, /*Copy=*/true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 790 | if (!TypeName.empty()) | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 791 | Arg[".type_name"] = Arg.getDocument()->getNode(TypeName, /*Copy=*/true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 792 | auto Size = DL.getTypeAllocSize(Ty); | 
|  | 793 | auto Align = DL.getABITypeAlignment(Ty); | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 794 | Arg[".size"] = Arg.getDocument()->getNode(Size); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 795 | Offset = alignTo(Offset, Align); | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 796 | Arg[".offset"] = Arg.getDocument()->getNode(Offset); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 797 | Offset += Size; | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 798 | Arg[".value_kind"] = Arg.getDocument()->getNode(ValueKind, /*Copy=*/true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 799 | Arg[".value_type"] = | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 800 | Arg.getDocument()->getNode(getValueType(Ty, BaseTypeName), /*Copy=*/true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 801 | if (PointeeAlign) | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 802 | Arg[".pointee_align"] = Arg.getDocument()->getNode(PointeeAlign); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 803 |  | 
|  | 804 | if (auto PtrTy = dyn_cast<PointerType>(Ty)) | 
|  | 805 | if (auto Qualifier = getAddressSpaceQualifier(PtrTy->getAddressSpace())) | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 806 | Arg[".address_space"] = Arg.getDocument()->getNode(*Qualifier, /*Copy=*/true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 807 |  | 
|  | 808 | if (auto AQ = getAccessQualifier(AccQual)) | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 809 | Arg[".access"] = Arg.getDocument()->getNode(*AQ, /*Copy=*/true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 810 |  | 
|  | 811 | // TODO: Emit Arg[".actual_access"]. | 
|  | 812 |  | 
|  | 813 | SmallVector<StringRef, 1> SplitTypeQuals; | 
|  | 814 | TypeQual.split(SplitTypeQuals, " ", -1, false); | 
|  | 815 | for (StringRef Key : SplitTypeQuals) { | 
|  | 816 | if (Key == "const") | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 817 | Arg[".is_const"] = Arg.getDocument()->getNode(true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 818 | else if (Key == "restrict") | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 819 | Arg[".is_restrict"] = Arg.getDocument()->getNode(true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 820 | else if (Key == "volatile") | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 821 | Arg[".is_volatile"] = Arg.getDocument()->getNode(true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 822 | else if (Key == "pipe") | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 823 | Arg[".is_pipe"] = Arg.getDocument()->getNode(true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 824 | } | 
|  | 825 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 826 | Args.push_back(Arg); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 827 | } | 
|  | 828 |  | 
|  | 829 | void MetadataStreamerV3::emitHiddenKernelArgs(const Function &Func, | 
|  | 830 | unsigned &Offset, | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 831 | msgpack::ArrayDocNode Args) { | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 832 | int HiddenArgNumBytes = | 
|  | 833 | getIntegerAttribute(Func, "amdgpu-implicitarg-num-bytes", 0); | 
|  | 834 |  | 
|  | 835 | if (!HiddenArgNumBytes) | 
|  | 836 | return; | 
|  | 837 |  | 
|  | 838 | auto &DL = Func.getParent()->getDataLayout(); | 
|  | 839 | auto Int64Ty = Type::getInt64Ty(Func.getContext()); | 
|  | 840 |  | 
|  | 841 | if (HiddenArgNumBytes >= 8) | 
|  | 842 | emitKernelArg(DL, Int64Ty, "hidden_global_offset_x", Offset, Args); | 
|  | 843 | if (HiddenArgNumBytes >= 16) | 
|  | 844 | emitKernelArg(DL, Int64Ty, "hidden_global_offset_y", Offset, Args); | 
|  | 845 | if (HiddenArgNumBytes >= 24) | 
|  | 846 | emitKernelArg(DL, Int64Ty, "hidden_global_offset_z", Offset, Args); | 
|  | 847 |  | 
|  | 848 | auto Int8PtrTy = | 
|  | 849 | Type::getInt8PtrTy(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS); | 
|  | 850 |  | 
|  | 851 | // Emit "printf buffer" argument if printf is used, otherwise emit dummy | 
|  | 852 | // "none" argument. | 
|  | 853 | if (HiddenArgNumBytes >= 32) { | 
|  | 854 | if (Func.getParent()->getNamedMetadata("llvm.printf.fmts")) | 
|  | 855 | emitKernelArg(DL, Int8PtrTy, "hidden_printf_buffer", Offset, Args); | 
|  | 856 | else | 
|  | 857 | emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, Args); | 
|  | 858 | } | 
|  | 859 |  | 
|  | 860 | // Emit "default queue" and "completion action" arguments if enqueue kernel is | 
|  | 861 | // used, otherwise emit dummy "none" arguments. | 
|  | 862 | if (HiddenArgNumBytes >= 48) { | 
|  | 863 | if (Func.hasFnAttribute("calls-enqueue-kernel")) { | 
|  | 864 | emitKernelArg(DL, Int8PtrTy, "hidden_default_queue", Offset, Args); | 
|  | 865 | emitKernelArg(DL, Int8PtrTy, "hidden_completion_action", Offset, Args); | 
|  | 866 | } else { | 
|  | 867 | emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, Args); | 
|  | 868 | emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, Args); | 
|  | 869 | } | 
|  | 870 | } | 
| Yaxun Liu | a624135 | 2019-07-05 16:05:17 +0000 | [diff] [blame] | 871 |  | 
|  | 872 | // Emit the pointer argument for multi-grid object. | 
|  | 873 | if (HiddenArgNumBytes >= 56) | 
|  | 874 | emitKernelArg(DL, Int8PtrTy, "hidden_multigrid_sync_arg", Offset, Args); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 875 | } | 
|  | 876 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 877 | msgpack::MapDocNode | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 878 | MetadataStreamerV3::getHSAKernelProps(const MachineFunction &MF, | 
|  | 879 | const SIProgramInfo &ProgramInfo) const { | 
|  | 880 | const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>(); | 
|  | 881 | const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>(); | 
|  | 882 | const Function &F = MF.getFunction(); | 
|  | 883 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 884 | auto Kern = HSAMetadataDoc->getMapNode(); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 885 |  | 
|  | 886 | unsigned MaxKernArgAlign; | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 887 | Kern[".kernarg_segment_size"] = Kern.getDocument()->getNode( | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 888 | STM.getKernArgSegmentSize(F, MaxKernArgAlign)); | 
|  | 889 | Kern[".group_segment_fixed_size"] = | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 890 | Kern.getDocument()->getNode(ProgramInfo.LDSSize); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 891 | Kern[".private_segment_fixed_size"] = | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 892 | Kern.getDocument()->getNode(ProgramInfo.ScratchSize); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 893 | Kern[".kernarg_segment_align"] = | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 894 | Kern.getDocument()->getNode(std::max(uint32_t(4), MaxKernArgAlign)); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 895 | Kern[".wavefront_size"] = | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 896 | Kern.getDocument()->getNode(STM.getWavefrontSize()); | 
|  | 897 | Kern[".sgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumSGPR); | 
|  | 898 | Kern[".vgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumVGPR); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 899 | Kern[".max_flat_workgroup_size"] = | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 900 | Kern.getDocument()->getNode(MFI.getMaxFlatWorkGroupSize()); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 901 | Kern[".sgpr_spill_count"] = | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 902 | Kern.getDocument()->getNode(MFI.getNumSpilledSGPRs()); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 903 | Kern[".vgpr_spill_count"] = | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 904 | Kern.getDocument()->getNode(MFI.getNumSpilledVGPRs()); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 905 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 906 | return Kern; | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 907 | } | 
|  | 908 |  | 
|  | 909 | bool MetadataStreamerV3::emitTo(AMDGPUTargetStreamer &TargetStreamer) { | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 910 | return TargetStreamer.EmitHSAMetadata(*HSAMetadataDoc, true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 911 | } | 
|  | 912 |  | 
|  | 913 | void MetadataStreamerV3::begin(const Module &Mod) { | 
|  | 914 | emitVersion(); | 
|  | 915 | emitPrintf(Mod); | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 916 | getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode(); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 917 | } | 
|  | 918 |  | 
|  | 919 | void MetadataStreamerV3::end() { | 
|  | 920 | std::string HSAMetadataString; | 
|  | 921 | raw_string_ostream StrOS(HSAMetadataString); | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 922 | HSAMetadataDoc->toYAML(StrOS); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 923 |  | 
|  | 924 | if (DumpHSAMetadata) | 
|  | 925 | dump(StrOS.str()); | 
|  | 926 | if (VerifyHSAMetadata) | 
|  | 927 | verify(StrOS.str()); | 
|  | 928 | } | 
|  | 929 |  | 
|  | 930 | void MetadataStreamerV3::emitKernel(const MachineFunction &MF, | 
|  | 931 | const SIProgramInfo &ProgramInfo) { | 
|  | 932 | auto &Func = MF.getFunction(); | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 933 | auto Kern = getHSAKernelProps(MF, ProgramInfo); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 934 |  | 
|  | 935 | assert(Func.getCallingConv() == CallingConv::AMDGPU_KERNEL || | 
|  | 936 | Func.getCallingConv() == CallingConv::SPIR_KERNEL); | 
|  | 937 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 938 | auto Kernels = | 
|  | 939 | getRootMetadata("amdhsa.kernels").getArray(/*Convert=*/true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 940 |  | 
|  | 941 | { | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 942 | Kern[".name"] = Kern.getDocument()->getNode(Func.getName()); | 
|  | 943 | Kern[".symbol"] = Kern.getDocument()->getNode( | 
|  | 944 | (Twine(Func.getName()) + Twine(".kd")).str(), /*Copy=*/true); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 945 | emitKernelLanguage(Func, Kern); | 
|  | 946 | emitKernelAttrs(Func, Kern); | 
|  | 947 | emitKernelArgs(Func, Kern); | 
|  | 948 | } | 
|  | 949 |  | 
| Tim Renouf | ed0b9af | 2019-03-13 18:55:50 +0000 | [diff] [blame] | 950 | Kernels.push_back(Kern); | 
| Scott Linder | f5b36e5 | 2018-12-12 19:39:27 +0000 | [diff] [blame] | 951 | } | 
|  | 952 |  | 
| Konstantin Zhuravlyov | a63b0f9 | 2017-10-11 22:18:53 +0000 | [diff] [blame] | 953 | } // end namespace HSAMD | 
| Konstantin Zhuravlyov | 7498cd6 | 2017-03-22 22:32:22 +0000 | [diff] [blame] | 954 | } // end namespace AMDGPU | 
|  | 955 | } // end namespace llvm |