LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU/MCTargetDesc - AMDGPUCodeObjectMetadataStreamer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 250 261 95.8 %
Date: 2017-09-14 15:23:50 Functions: 23 23 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===--- AMDGPUCodeObjectMetadataStreamer.cpp -------------------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : /// \file
      11             : /// \brief AMDGPU Code Object Metadata Streamer.
      12             : ///
      13             : //
      14             : //===----------------------------------------------------------------------===//
      15             : 
      16             : #include "AMDGPUCodeObjectMetadataStreamer.h"
      17             : #include "AMDGPU.h"
      18             : #include "llvm/ADT/StringSwitch.h"
      19             : #include "llvm/IR/Constants.h"
      20             : #include "llvm/IR/Module.h"
      21             : #include "llvm/Support/raw_ostream.h"
      22             : 
      23             : namespace llvm {
      24             : 
      25       72306 : static cl::opt<bool> DumpCodeObjectMetadata(
      26             :     "amdgpu-dump-comd",
      27      144612 :     cl::desc("Dump AMDGPU Code Object Metadata"));
      28       72306 : static cl::opt<bool> VerifyCodeObjectMetadata(
      29             :     "amdgpu-verify-comd",
      30      144612 :     cl::desc("Verify AMDGPU Code Object Metadata"));
      31             : 
      32             : namespace AMDGPU {
      33             : namespace CodeObject {
      34             : 
      35           6 : void MetadataStreamer::dump(StringRef YamlString) const {
      36          12 :   errs() << "AMDGPU Code Object Metadata:\n" << YamlString << '\n';
      37           6 : }
      38             : 
      39           6 : void MetadataStreamer::verify(StringRef YamlString) const {
      40           6 :   errs() << "AMDGPU Code Object Metadata Parser Test: ";
      41             : 
      42          12 :   CodeObject::Metadata FromYamlString;
      43          12 :   if (Metadata::fromYamlString(YamlString, FromYamlString)) {
      44           0 :     errs() << "FAIL\n";
      45           0 :     return;
      46             :   }
      47             : 
      48          12 :   std::string ToYamlString;
      49           6 :   if (Metadata::toYamlString(FromYamlString, ToYamlString)) {
      50           0 :     errs() << "FAIL\n";
      51             :     return;
      52             :   }
      53             : 
      54          24 :   errs() << (YamlString == ToYamlString ? "PASS" : "FAIL") << '\n';
      55           6 :   if (YamlString != ToYamlString) {
      56           0 :     errs() << "Original input: " << YamlString << '\n'
      57           0 :            << "Produced output: " << ToYamlString << '\n';
      58             :   }
      59             : }
      60             : 
      61        3257 : AccessQualifier MetadataStreamer::getAccessQualifier(StringRef AccQual) const {
      62        3257 :   if (AccQual.empty())
      63             :     return AccessQualifier::Unknown;
      64             : 
      65         278 :   return StringSwitch<AccessQualifier>(AccQual)
      66         834 :              .Case("read_only",  AccessQualifier::ReadOnly)
      67         834 :              .Case("write_only", AccessQualifier::WriteOnly)
      68         834 :              .Case("read_write", AccessQualifier::ReadWrite)
      69         556 :              .Default(AccessQualifier::Default);
      70             : }
      71             : 
      72        2006 : AddressSpaceQualifier MetadataStreamer::getAddressSpaceQualifer(
      73             :     unsigned AddressSpace) const {
      74        2006 :   if (AddressSpace == AMDGPUASI.PRIVATE_ADDRESS)
      75             :     return AddressSpaceQualifier::Private;
      76        1972 :   if (AddressSpace == AMDGPUASI.GLOBAL_ADDRESS)
      77             :     return AddressSpaceQualifier::Global;
      78         476 :   if (AddressSpace == AMDGPUASI.CONSTANT_ADDRESS)
      79             :     return AddressSpaceQualifier::Constant;
      80         313 :   if (AddressSpace == AMDGPUASI.LOCAL_ADDRESS)
      81             :     return AddressSpaceQualifier::Local;
      82         203 :   if (AddressSpace == AMDGPUASI.FLAT_ADDRESS)
      83             :     return AddressSpaceQualifier::Generic;
      84           0 :   if (AddressSpace == AMDGPUASI.REGION_ADDRESS)
      85             :     return AddressSpaceQualifier::Region;
      86             : 
      87           0 :   llvm_unreachable("Unknown address space qualifier");
      88             : }
      89             : 
      90        2480 : ValueKind MetadataStreamer::getValueKind(Type *Ty, StringRef TypeQual,
      91             :                                          StringRef BaseTypeName) const {
      92        2480 :   if (TypeQual.find("pipe") != StringRef::npos)
      93             :     return ValueKind::Pipe;
      94             : 
      95        2474 :   return StringSwitch<ValueKind>(BaseTypeName)
      96        7422 :              .Case("image1d_t", ValueKind::Image)
      97        7422 :              .Case("image1d_array_t", ValueKind::Image)
      98        7422 :              .Case("image1d_buffer_t", ValueKind::Image)
      99        7422 :              .Case("image2d_t", ValueKind::Image)
     100        7422 :              .Case("image2d_array_t", ValueKind::Image)
     101        7422 :              .Case("image2d_array_depth_t", ValueKind::Image)
     102        7422 :              .Case("image2d_array_msaa_t", ValueKind::Image)
     103        7422 :              .Case("image2d_array_msaa_depth_t", ValueKind::Image)
     104        7422 :              .Case("image2d_depth_t", ValueKind::Image)
     105        7422 :              .Case("image2d_msaa_t", ValueKind::Image)
     106        7422 :              .Case("image2d_msaa_depth_t", ValueKind::Image)
     107        7422 :              .Case("image3d_t", ValueKind::Image)
     108        7422 :              .Case("sampler_t", ValueKind::Sampler)
     109        7422 :              .Case("queue_t", ValueKind::Queue)
     110        7422 :              .Default(isa<PointerType>(Ty) ?
     111        3628 :                           (Ty->getPointerAddressSpace() ==
     112        1814 :                            AMDGPUASI.LOCAL_ADDRESS ?
     113             :                            ValueKind::DynamicSharedPointer :
     114             :                            ValueKind::GlobalBuffer) :
     115        2474 :                       ValueKind::ByValue);
     116             : }
     117             : 
     118        3257 : ValueType MetadataStreamer::getValueType(Type *Ty, StringRef TypeName) const {
     119        6143 :   switch (Ty->getTypeID()) {
     120        2615 :   case Type::IntegerTyID: {
     121        5230 :     auto Signed = !TypeName.startswith("u");
     122        2615 :     switch (Ty->getIntegerBitWidth()) {
     123         430 :     case 8:
     124         430 :       return Signed ? ValueType::I8 : ValueType::U8;
     125         165 :     case 16:
     126         165 :       return Signed ? ValueType::I16 : ValueType::U16;
     127        1252 :     case 32:
     128        1252 :       return Signed ? ValueType::I32 : ValueType::U32;
     129         752 :     case 64:
     130         752 :       return Signed ? ValueType::I64 : ValueType::U64;
     131             :     default:
     132             :       return ValueType::Struct;
     133             :     }
     134             :   }
     135             :   case Type::HalfTyID:
     136             :     return ValueType::F16;
     137          94 :   case Type::FloatTyID:
     138          94 :     return ValueType::F32;
     139          59 :   case Type::DoubleTyID:
     140          59 :     return ValueType::F64;
     141        2021 :   case Type::PointerTyID:
     142        4042 :     return getValueType(Ty->getPointerElementType(), TypeName);
     143         865 :   case Type::VectorTyID:
     144        1730 :     return getValueType(Ty->getVectorElementType(), TypeName);
     145         108 :   default:
     146         108 :     return ValueType::Struct;
     147             :   }
     148             : }
     149             : 
     150          66 : std::string MetadataStreamer::getTypeName(Type *Ty, bool Signed) const {
     151          66 :   switch (Ty->getTypeID()) {
     152          36 :   case Type::IntegerTyID: {
     153          36 :     if (!Signed)
     154          30 :       return (Twine('u') + getTypeName(Ty, true)).str();
     155             : 
     156          30 :     auto BitWidth = Ty->getIntegerBitWidth();
     157          30 :     switch (BitWidth) {
     158             :     case 8:
     159          12 :       return "char";
     160             :     case 16:
     161          12 :       return "short";
     162             :     case 32:
     163          24 :       return "int";
     164             :     case 64:
     165          12 :       return "long";
     166           0 :     default:
     167           0 :       return (Twine('i') + Twine(BitWidth)).str();
     168             :     }
     169             :   }
     170             :   case Type::HalfTyID:
     171          12 :     return "half";
     172             :   case Type::FloatTyID:
     173          12 :     return "float";
     174             :   case Type::DoubleTyID:
     175          12 :     return "double";
     176           6 :   case Type::VectorTyID: {
     177           6 :     auto VecTy = cast<VectorType>(Ty);
     178           6 :     auto ElTy = VecTy->getElementType();
     179          12 :     auto NumElements = VecTy->getVectorNumElements();
     180          24 :     return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
     181             :   }
     182             :   default:
     183          12 :     return "unknown";
     184             :   }
     185             : }
     186             : 
     187          12 : std::vector<uint32_t> MetadataStreamer::getWorkGroupDimensions(
     188             :     MDNode *Node) const {
     189          12 :   std::vector<uint32_t> Dims;
     190          12 :   if (Node->getNumOperands() != 3)
     191             :     return Dims;
     192             : 
     193          48 :   for (auto &Op : Node->operands())
     194         108 :     Dims.push_back(mdconst::extract<ConstantInt>(Op)->getZExtValue());
     195             :   return Dims;
     196             : }
     197             : 
     198         240 : void MetadataStreamer::emitVersion() {
     199         240 :   auto &Version = CodeObjectMetadata.mVersion;
     200             : 
     201         240 :   Version.push_back(MetadataVersionMajor);
     202         240 :   Version.push_back(MetadataVersionMinor);
     203         240 : }
     204             : 
     205         240 : void MetadataStreamer::emitPrintf(const Module &Mod) {
     206         240 :   auto &Printf = CodeObjectMetadata.mPrintf;
     207             : 
     208         240 :   auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
     209         240 :   if (!Node)
     210             :     return;
     211             : 
     212          18 :   for (auto Op : Node->operands())
     213          12 :     if (Op->getNumOperands())
     214          60 :       Printf.push_back(cast<MDString>(Op->getOperand(0))->getString());
     215             : }
     216             : 
     217        1661 : void MetadataStreamer::emitKernelLanguage(const Function &Func) {
     218        3322 :   auto &Kernel = CodeObjectMetadata.mKernels.back();
     219             : 
     220             :   // TODO: What about other languages?
     221        3322 :   auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
     222        1661 :   if (!Node || !Node->getNumOperands())
     223             :     return;
     224         197 :   auto Op0 = Node->getOperand(0);
     225         197 :   if (Op0->getNumOperands() <= 1)
     226             :     return;
     227             : 
     228         394 :   Kernel.mLanguage = "OpenCL C";
     229         591 :   Kernel.mLanguageVersion.push_back(
     230         591 :       mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue());
     231         591 :   Kernel.mLanguageVersion.push_back(
     232         591 :       mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue());
     233             : }
     234             : 
     235        1661 : void MetadataStreamer::emitKernelAttrs(const Function &Func) {
     236        3322 :   auto &Attrs = CodeObjectMetadata.mKernels.back().mAttrs;
     237             : 
     238        3322 :   if (auto Node = Func.getMetadata("reqd_work_group_size"))
     239          18 :     Attrs.mReqdWorkGroupSize = getWorkGroupDimensions(Node);
     240        3322 :   if (auto Node = Func.getMetadata("work_group_size_hint"))
     241          18 :     Attrs.mWorkGroupSizeHint = getWorkGroupDimensions(Node);
     242        3322 :   if (auto Node = Func.getMetadata("vec_type_hint")) {
     243         270 :     Attrs.mVecTypeHint = getTypeName(
     244             :         cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
     245         216 :         mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue());
     246             :   }
     247        1661 : }
     248             : 
     249        1661 : void MetadataStreamer::emitKernelArgs(const Function &Func) {
     250        4141 :   for (auto &Arg : Func.args())
     251        2480 :     emitKernelArg(Arg);
     252             : 
     253             :   // TODO: What about other languages?
     254        3322 :   if (!Func.getParent()->getNamedMetadata("opencl.ocl.version"))
     255             :     return;
     256             : 
     257         197 :   auto &DL = Func.getParent()->getDataLayout();
     258         197 :   auto Int64Ty = Type::getInt64Ty(Func.getContext());
     259             : 
     260         985 :   emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetX);
     261         985 :   emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetY);
     262         985 :   emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetZ);
     263             : 
     264         394 :   if (!Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
     265             :     return;
     266             : 
     267         186 :   auto Int8PtrTy = Type::getInt8PtrTy(Func.getContext(),
     268         186 :                                       AMDGPUASI.GLOBAL_ADDRESS);
     269         930 :   emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenPrintfBuffer);
     270             : }
     271             : 
     272        2480 : void MetadataStreamer::emitKernelArg(const Argument &Arg) {
     273        2480 :   auto Func = Arg.getParent();
     274        2480 :   auto ArgNo = Arg.getArgNo();
     275             :   const MDNode *Node;
     276             : 
     277        2480 :   StringRef TypeQual;
     278        4960 :   Node = Func->getMetadata("kernel_arg_type_qual");
     279        2480 :   if (Node && ArgNo < Node->getNumOperands())
     280         552 :     TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
     281             : 
     282        2480 :   StringRef BaseTypeName;
     283        4960 :   Node = Func->getMetadata("kernel_arg_base_type");
     284        2480 :   if (Node && ArgNo < Node->getNumOperands())
     285         624 :     BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
     286             : 
     287        2480 :   StringRef AccQual;
     288        4990 :   if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
     289          30 :       Arg.hasNoAliasAttr()) {
     290           3 :     AccQual = "read_only";
     291             :   } else {
     292        4954 :     Node = Func->getMetadata("kernel_arg_access_qual");
     293        2752 :     if (Node && ArgNo < Node->getNumOperands())
     294         550 :       AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
     295             :   }
     296             : 
     297        2480 :   StringRef Name;
     298        4960 :   Node = Func->getMetadata("kernel_arg_name");
     299        2480 :   if (Node && ArgNo < Node->getNumOperands())
     300           0 :     Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
     301             : 
     302        2480 :   StringRef TypeName;
     303        4960 :   Node = Func->getMetadata("kernel_arg_type");
     304        2480 :   if (Node && ArgNo < Node->getNumOperands())
     305         624 :     TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
     306             : 
     307        2480 :   emitKernelArg(Func->getParent()->getDataLayout(), Arg.getType(),
     308             :                 getValueKind(Arg.getType(), TypeQual, BaseTypeName), TypeQual,
     309             :                 BaseTypeName, AccQual, Name, TypeName);
     310        2480 : }
     311             : 
     312        3257 : void MetadataStreamer::emitKernelArg(const DataLayout &DL, Type *Ty,
     313             :                                      ValueKind ValueKind, StringRef TypeQual,
     314             :                                      StringRef BaseTypeName, StringRef AccQual,
     315             :                                      StringRef Name, StringRef TypeName) {
     316       13028 :   CodeObjectMetadata.mKernels.back().mArgs.push_back(Kernel::Arg::Metadata());
     317        9771 :   auto &Arg = CodeObjectMetadata.mKernels.back().mArgs.back();
     318             : 
     319        3257 :   Arg.mSize = DL.getTypeAllocSize(Ty);
     320        3257 :   Arg.mAlign = DL.getABITypeAlignment(Ty);
     321        3257 :   Arg.mValueKind = ValueKind;
     322        3257 :   Arg.mValueType = getValueType(Ty, BaseTypeName);
     323             : 
     324        2006 :   if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
     325        2006 :     auto ElTy = PtrTy->getElementType();
     326        2006 :     if (PtrTy->getAddressSpace() == AMDGPUASI.LOCAL_ADDRESS && ElTy->isSized())
     327         110 :       Arg.mPointeeAlign = DL.getABITypeAlignment(ElTy);
     328             :   }
     329             : 
     330        3257 :   Arg.mAccQual = getAccessQualifier(AccQual);
     331             : 
     332        2006 :   if (auto PtrTy = dyn_cast<PointerType>(Ty))
     333        2006 :     Arg.mAddrSpaceQual = getAddressSpaceQualifer(PtrTy->getAddressSpace());
     334             : 
     335        6514 :   SmallVector<StringRef, 1> SplitTypeQuals;
     336        3257 :   TypeQual.split(SplitTypeQuals, " ", -1, false);
     337        9797 :   for (StringRef Key : SplitTypeQuals) {
     338          26 :     auto P = StringSwitch<bool*>(Key)
     339          78 :                  .Case("const",    &Arg.mIsConst)
     340          78 :                  .Case("pipe",     &Arg.mIsPipe)
     341          78 :                  .Case("restrict", &Arg.mIsRestrict)
     342          78 :                  .Case("volatile", &Arg.mIsVolatile)
     343          52 :                  .Default(nullptr);
     344          26 :     if (P)
     345          26 :       *P = true;
     346             :   }
     347             : 
     348        6514 :   Arg.mName = Name;
     349        6514 :   Arg.mTypeName = TypeName;
     350        3257 : }
     351             : 
     352        1661 : void MetadataStreamer::emitKernelCodeProps(
     353             :     const amd_kernel_code_t &KernelCode) {
     354        3322 :   auto &CodeProps = CodeObjectMetadata.mKernels.back().mCodeProps;
     355             : 
     356        1661 :   CodeProps.mKernargSegmentSize = KernelCode.kernarg_segment_byte_size;
     357        1661 :   CodeProps.mWorkgroupGroupSegmentSize =
     358        1661 :       KernelCode.workgroup_group_segment_byte_size;
     359        1661 :   CodeProps.mWorkitemPrivateSegmentSize =
     360        1661 :       KernelCode.workitem_private_segment_byte_size;
     361        1661 :   CodeProps.mWavefrontNumSGPRs = KernelCode.wavefront_sgpr_count;
     362        1661 :   CodeProps.mWorkitemNumVGPRs = KernelCode.workitem_vgpr_count;
     363        1661 :   CodeProps.mKernargSegmentAlign = KernelCode.kernarg_segment_alignment;
     364        1661 :   CodeProps.mGroupSegmentAlign = KernelCode.group_segment_alignment;
     365        1661 :   CodeProps.mPrivateSegmentAlign = KernelCode.private_segment_alignment;
     366        1661 :   CodeProps.mWavefrontSize = KernelCode.wavefront_size;
     367        1661 : }
     368             : 
     369        1661 : void MetadataStreamer::emitKernelDebugProps(
     370             :     const amd_kernel_code_t &KernelCode) {
     371        1661 :   if (!(KernelCode.code_properties & AMD_CODE_PROPERTY_IS_DEBUG_SUPPORTED))
     372             :     return;
     373             : 
     374           6 :   auto &DebugProps = CodeObjectMetadata.mKernels.back().mDebugProps;
     375             : 
     376             :   // FIXME: Need to pass down debugger ABI version through features. This is ok
     377             :   // for now because we only have one version.
     378           6 :   DebugProps.mDebuggerABIVersion.push_back(1);
     379           6 :   DebugProps.mDebuggerABIVersion.push_back(0);
     380           3 :   DebugProps.mReservedNumVGPRs = KernelCode.reserved_vgpr_count;
     381           3 :   DebugProps.mReservedFirstVGPR = KernelCode.reserved_vgpr_first;
     382           3 :   DebugProps.mPrivateSegmentBufferSGPR =
     383           3 :       KernelCode.debug_private_segment_buffer_sgpr;
     384           3 :   DebugProps.mWavefrontPrivateSegmentOffsetSGPR =
     385           3 :       KernelCode.debug_wavefront_private_segment_offset_sgpr;
     386             : }
     387             : 
     388         240 : void MetadataStreamer::begin(const Module &Mod) {
     389         240 :   AMDGPUASI = getAMDGPUAS(Mod);
     390         240 :   emitVersion();
     391         240 :   emitPrintf(Mod);
     392         240 : }
     393             : 
     394        1664 : void MetadataStreamer::emitKernel(const Function &Func,
     395             :                                   const amd_kernel_code_t &KernelCode) {
     396        1664 :   if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL)
     397             :     return;
     398             : 
     399        3322 :   CodeObjectMetadata.mKernels.push_back(Kernel::Metadata());
     400        3322 :   auto &Kernel = CodeObjectMetadata.mKernels.back();
     401             : 
     402        4983 :   Kernel.mName = Func.getName();
     403        1661 :   emitKernelLanguage(Func);
     404        1661 :   emitKernelAttrs(Func);
     405        1661 :   emitKernelArgs(Func);
     406        1661 :   emitKernelCodeProps(KernelCode);
     407        1661 :   emitKernelDebugProps(KernelCode);
     408             : }
     409             : 
     410         496 : ErrorOr<std::string> MetadataStreamer::toYamlString() {
     411         992 :   std::string YamlString;
     412         496 :   if (auto Error = Metadata::toYamlString(CodeObjectMetadata, YamlString))
     413           0 :     return Error;
     414             : 
     415         496 :   if (DumpCodeObjectMetadata)
     416           6 :     dump(YamlString);
     417         496 :   if (VerifyCodeObjectMetadata)
     418           6 :     verify(YamlString);
     419             : 
     420             :   return YamlString;
     421             : }
     422             : 
     423         262 : ErrorOr<std::string> MetadataStreamer::toYamlString(StringRef YamlString) {
     424         786 :   if (auto Error = Metadata::fromYamlString(YamlString, CodeObjectMetadata))
     425           6 :     return Error;
     426             : 
     427         256 :   return toYamlString();
     428             : }
     429             : 
     430             : } // end namespace CodeObject
     431             : } // end namespace AMDGPU
     432      216918 : } // end namespace llvm

Generated by: LCOV version 1.13