llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-llvm-analysis Author: Justin Bogner (bogner) <details> <summary>Changes</summary> Handle target extension type resources when printing resources to textual IR. --- Full diff: https://github.com/llvm/llvm-project/pull/104448.diff 5 Files Affected: - (modified) llvm/include/llvm/Analysis/DXILResource.h (+15-1) - (modified) llvm/lib/Target/DirectX/DXILOpLowering.cpp (+2-2) - (modified) llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp (+222-5) - (modified) llvm/test/CodeGen/DirectX/CreateHandle.ll (+9) - (modified) llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll (+9) ``````````diff diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h index 2ed508b28a908..faee9f5dac1b4 100644 --- a/llvm/include/llvm/Analysis/DXILResource.h +++ b/llvm/include/llvm/Analysis/DXILResource.h @@ -142,12 +142,17 @@ class ResourceInfo { Binding.LowerBound = LowerBound; Binding.Size = Size; } + const ResourceBinding &getBinding() const { return Binding; } void setUAV(bool GloballyCoherent, bool HasCounter, bool IsROV) { assert(isUAV() && "Not a UAV"); UAVFlags.GloballyCoherent = GloballyCoherent; UAVFlags.HasCounter = HasCounter; UAVFlags.IsROV = IsROV; } + const UAVInfo &getUAV() const { + assert(isUAV() && "Not a UAV"); + return UAVFlags; + } void setCBuffer(uint32_t Size) { assert(isCBuffer() && "Not a CBuffer"); CBufferSize = Size; @@ -163,6 +168,10 @@ class ResourceInfo { Typed.ElementTy = ElementTy; Typed.ElementCount = ElementCount; } + const TypedInfo &getTyped() const { + assert(isTyped() && "Not typed"); + return Typed; + } void setFeedback(dxil::SamplerFeedbackType Type) { assert(isFeedback() && "Not Feedback"); Feedback.Type = Type; @@ -171,8 +180,14 @@ class ResourceInfo { assert(isMultiSample() && "Not MultiSampled"); MultiSample.Count = Count; } + const MSInfo &getMultiSample() const { + assert(isMultiSample() && "Not MultiSampled"); + return MultiSample; + } + StringRef getName() const { return Name; } dxil::ResourceClass getResourceClass() const { return RC; } + dxil::ResourceKind getResourceKind() const { return Kind; } bool operator==(const ResourceInfo &RHS) const; @@ -222,7 +237,6 @@ class ResourceInfo { MDTuple *getAsMetadata(LLVMContext &Ctx) const; - ResourceBinding getBinding() const { return Binding; } std::pair<uint32_t, uint32_t> getAnnotateProps() const; void print(raw_ostream &OS) const; diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index f34302cc95065..e7c36ead1cc34 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -175,7 +175,7 @@ class OpLowerer { IRB.SetInsertPoint(CI); dxil::ResourceInfo &RI = DRM[CI]; - dxil::ResourceInfo::ResourceBinding Binding = RI.getBinding(); + const auto &Binding = RI.getBinding(); std::array<Value *, 4> Args{ ConstantInt::get(Int8Ty, llvm::to_underlying(RI.getResourceClass())), @@ -201,7 +201,7 @@ class OpLowerer { IRB.SetInsertPoint(CI); dxil::ResourceInfo &RI = DRM[CI]; - dxil::ResourceInfo::ResourceBinding Binding = RI.getBinding(); + const auto &Binding = RI.getBinding(); std::pair<uint32_t, uint32_t> Props = RI.getAnnotateProps(); Constant *ResBind = OpBuilder.getResBind( diff --git a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp index c57631cc4c8b6..76a40dbfc5845 100644 --- a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp +++ b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp @@ -10,23 +10,235 @@ #include "DXILResourceAnalysis.h" #include "DirectX.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/DXILResource.h" #include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" #include "llvm/Pass.h" +#include "llvm/Support/FormatAdapters.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; -static void prettyPrintResources(raw_ostream &OS, +static constexpr StringRef getRCName(dxil::ResourceClass RC) { + switch (RC) { + case dxil::ResourceClass::SRV: + return "SRV"; + case dxil::ResourceClass::UAV: + return "UAV"; + case dxil::ResourceClass::CBuffer: + return "cbuffer"; + case dxil::ResourceClass::Sampler: + return "sampler"; + } + llvm_unreachable("covered switch"); +} + +static constexpr StringRef getRCPrefix(dxil::ResourceClass RC) { + switch (RC) { + case dxil::ResourceClass::SRV: + return "t"; + case dxil::ResourceClass::UAV: + return "u"; + case dxil::ResourceClass::CBuffer: + return "cb"; + case dxil::ResourceClass::Sampler: + return "s"; + } +} + +static constexpr StringRef getFormatName(const dxil::ResourceInfo &RI) { + if (RI.isTyped()) { + switch (RI.getTyped().ElementTy) { + case dxil::ElementType::I1: + return "i1"; + case dxil::ElementType::I16: + return "i16"; + case dxil::ElementType::U16: + return "u16"; + case dxil::ElementType::I32: + return "i32"; + case dxil::ElementType::U32: + return "u32"; + case dxil::ElementType::I64: + return "i64"; + case dxil::ElementType::U64: + return "u64"; + case dxil::ElementType::F16: + return "f16"; + case dxil::ElementType::F32: + return "f32"; + case dxil::ElementType::F64: + return "f64"; + case dxil::ElementType::SNormF16: + return "snorm_f16"; + case dxil::ElementType::UNormF16: + return "unorm_f16"; + case dxil::ElementType::SNormF32: + return "snorm_f32"; + case dxil::ElementType::UNormF32: + return "unorm_f32"; + case dxil::ElementType::SNormF64: + return "snorm_f64"; + case dxil::ElementType::UNormF64: + return "unorm_f64"; + case dxil::ElementType::PackedS8x32: + return "p32i8"; + case dxil::ElementType::PackedU8x32: + return "p32u8"; + case dxil::ElementType::Invalid: + llvm_unreachable("Invalid ElementType"); + } + llvm_unreachable("Unhandled ElementType"); + } else if (RI.isStruct()) + return "struct"; + else if (RI.isCBuffer() || RI.isSampler()) + return "NA"; + return "byte"; +} + +static constexpr StringRef getTextureDimName(dxil::ResourceKind RK) { + switch (RK) { + case dxil::ResourceKind::Texture1D: + return "1d"; + case dxil::ResourceKind::Texture2D: + return "2d"; + case dxil::ResourceKind::Texture3D: + return "3d"; + case dxil::ResourceKind::TextureCube: + return "cube"; + case dxil::ResourceKind::Texture1DArray: + return "1darray"; + case dxil::ResourceKind::Texture2DArray: + return "2darray"; + case dxil::ResourceKind::TextureCubeArray: + return "cubearray"; + case dxil::ResourceKind::TBuffer: + return "tbuffer"; + case dxil::ResourceKind::FeedbackTexture2D: + return "fbtex2d"; + case dxil::ResourceKind::FeedbackTexture2DArray: + return "fbtex2darray"; + case dxil::ResourceKind::Texture2DMS: + return "2dMS"; + case dxil::ResourceKind::Texture2DMSArray: + return "2darrayMS"; + case dxil::ResourceKind::Invalid: + case dxil::ResourceKind::NumEntries: + case dxil::ResourceKind::CBuffer: + case dxil::ResourceKind::RawBuffer: + case dxil::ResourceKind::Sampler: + case dxil::ResourceKind::StructuredBuffer: + case dxil::ResourceKind::TypedBuffer: + case dxil::ResourceKind::RTAccelerationStructure: + llvm_unreachable("Invalid ResourceKind for texture"); + } + llvm_unreachable("Unhandled ResourceKind"); +} + +namespace { +struct FormatResourceDimension + : public llvm::FormatAdapter<const dxil::ResourceInfo &> { + explicit FormatResourceDimension(const dxil::ResourceInfo &RI) + : llvm::FormatAdapter<const dxil::ResourceInfo &>(RI) {} + + void format(llvm::raw_ostream &OS, StringRef Style) override { + dxil::ResourceKind RK = Item.getResourceKind(); + switch (RK) { + default: { + OS << getTextureDimName(RK); + if (Item.isMultiSample()) + OS << Item.getMultiSample().Count; + break;; + } + case dxil::ResourceKind::RawBuffer: + case dxil::ResourceKind::StructuredBuffer: + if (!Item.isUAV()) + OS << "r/o"; + else if (Item.getUAV().HasCounter) + OS << "r/w+cnt"; + else + OS << "r/w"; + break; + case dxil::ResourceKind::TypedBuffer: + OS << "buf"; + break; + case dxil::ResourceKind::RTAccelerationStructure: + // TODO: dxc would print "ras" here. Can/should this happen? + llvm_unreachable("RTAccelerationStructure printing is not implemented"); + } + } +}; + +struct FormatBindingID + : public llvm::FormatAdapter<const dxil::ResourceInfo &> { + explicit FormatBindingID(const dxil::ResourceInfo &RI) + : llvm::FormatAdapter<const dxil::ResourceInfo &>(RI) {} + + void format(llvm::raw_ostream &OS, StringRef Style) override { + OS << getRCPrefix(Item.getResourceClass()).upper() + << Item.getBinding().RecordID; + } +}; + +struct FormatBindingLocation + : public llvm::FormatAdapter<const dxil::ResourceInfo &> { + explicit FormatBindingLocation(const dxil::ResourceInfo &RI) + : llvm::FormatAdapter<const dxil::ResourceInfo &>(RI) {} + + void format(llvm::raw_ostream &OS, StringRef Style) override { + const auto &Binding = Item.getBinding(); + OS << getRCPrefix(Item.getResourceClass()) << Binding.LowerBound; + if (Binding.Space) + OS << ",space" << Binding.Space; + } +}; + +struct FormatBindingSize + : public llvm::FormatAdapter<const dxil::ResourceInfo &> { + explicit FormatBindingSize(const dxil::ResourceInfo &RI) + : llvm::FormatAdapter<const dxil::ResourceInfo &>(RI) {} + + void format(llvm::raw_ostream &OS, StringRef Style) override { + uint32_t Size = Item.getBinding().Size; + if (Size == std::numeric_limits<uint32_t>::max()) + OS << "unbounded"; + else + OS << Size; + } +}; + +} // namespace + +static void prettyPrintResources(raw_ostream &OS, const DXILResourceMap &DRM, const dxil::Resources &MDResources) { // Column widths are arbitrary but match the widths DXC uses. OS << ";\n; Resource Bindings:\n;\n"; - OS << formatv("; {0,-30} {1,10} {2,7} {3,11} {4,7} {5,14} {6,16}\n", + OS << formatv("; {0,-30} {1,10} {2,7} {3,11} {4,7} {5,14} {6,9}\n", "Name", "Type", "Format", "Dim", "ID", "HLSL Bind", "Count"); OS << formatv( - "; {0,-+30} {1,-+10} {2,-+7} {3,-+11} {4,-+7} {5,-+14} {6,-+16}\n", "", + "; {0,-+30} {1,-+10} {2,-+7} {3,-+11} {4,-+7} {5,-+14} {6,-+9}\n", "", "", "", "", "", "", ""); + // TODO: Do we want to sort these by binding or something like that? + for (auto [_, RI] : DRM) { + dxil::ResourceClass RC = RI.getResourceClass(); + assert((RC != dxil::ResourceClass::CBuffer || !MDResources.hasCBuffers()) && + "Old and new cbuffer representations can't coexist"); + assert((RC != dxil::ResourceClass::UAV || !MDResources.hasUAVs()) && + "Old and new UAV representations can't coexist"); + + StringRef Name(RI.getName()); + StringRef Type(getRCName(RC)); + StringRef Format(getFormatName(RI)); + FormatResourceDimension Dim(RI); + FormatBindingID ID(RI); + FormatBindingLocation Bind(RI); + FormatBindingSize Count(RI); + OS << formatv("; {0,-30} {1,10} {2,7} {3,11} {4,7} {5,14} {6,9}\n", + Name, Type, Format, Dim, ID, Bind, Count); + } + if (MDResources.hasCBuffers()) MDResources.printCBuffers(OS); if (MDResources.hasUAVs()) @@ -37,8 +249,9 @@ static void prettyPrintResources(raw_ostream &OS, PreservedAnalyses DXILPrettyPrinterPass::run(Module &M, ModuleAnalysisManager &MAM) { + const DXILResourceMap &DRM = MAM.getResult<DXILResourceAnalysis>(M); const dxil::Resources &MDResources = MAM.getResult<DXILResourceMDAnalysis>(M); - prettyPrintResources(OS, MDResources); + prettyPrintResources(OS, DRM, MDResources); return PreservedAnalyses::all(); } @@ -63,6 +276,7 @@ class DXILPrettyPrinterLegacy : public llvm::ModulePass { bool runOnModule(Module &M) override; void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); + AU.addRequired<DXILResourceWrapperPass>(); AU.addRequired<DXILResourceMDWrapper>(); } }; @@ -71,13 +285,16 @@ class DXILPrettyPrinterLegacy : public llvm::ModulePass { char DXILPrettyPrinterLegacy::ID = 0; INITIALIZE_PASS_BEGIN(DXILPrettyPrinterLegacy, "dxil-pretty-printer", "DXIL Metadata Pretty Printer", true, true) +INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass) INITIALIZE_PASS_DEPENDENCY(DXILResourceMDWrapper) INITIALIZE_PASS_END(DXILPrettyPrinterLegacy, "dxil-pretty-printer", "DXIL Metadata Pretty Printer", true, true) bool DXILPrettyPrinterLegacy::runOnModule(Module &M) { + const DXILResourceMap &DRM = + getAnalysis<DXILResourceWrapperPass>().getResourceMap(); dxil::Resources &Res = getAnalysis<DXILResourceMDWrapper>().getDXILResource(); - prettyPrintResources(OS, Res); + prettyPrintResources(OS, DRM, Res); return false; } diff --git a/llvm/test/CodeGen/DirectX/CreateHandle.ll b/llvm/test/CodeGen/DirectX/CreateHandle.ll index f0d1c8da5a425..cbb7359642c27 100644 --- a/llvm/test/CodeGen/DirectX/CreateHandle.ll +++ b/llvm/test/CodeGen/DirectX/CreateHandle.ll @@ -1,4 +1,13 @@ ; RUN: opt -S -passes=dxil-op-lower,dxil-translate-metadata %s | FileCheck %s +; RUN: opt -S -passes=dxil-pretty-printer %s 2>&1 >/dev/null | FileCheck --check-prefix=CHECK-PRETTY %s + +; CHECK-PRETTY: Type Format Dim ID HLSL Bind Count +; CHECK-PRETTY: ---------- ------- ----------- ------- -------------- --------- +; CHECK-PRETTY: UAV f32 buf U0 u5,space3 1 +; CHECK-PRETTY: UAV i32 buf U1 u7,space2 1 +; CHECK-PRETTY: SRV u32 buf T0 t3,space5 24 +; CHECK-PRETTY: SRV struct r/o T1 t2,space4 1 +; CHECK-PRETTY: SRV byte r/o T2 t8,space1 1 target triple = "dxil-pc-shadermodel6.0-compute" diff --git a/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll b/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll index 345459a60c5ab..aea251a3612ef 100644 --- a/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll +++ b/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll @@ -1,4 +1,13 @@ ; RUN: opt -S -passes=dxil-op-lower,dxil-translate-metadata %s | FileCheck %s +; RUN: opt -S -passes=dxil-pretty-printer %s 2>&1 >/dev/null | FileCheck --check-prefix=CHECK-PRETTY %s + +; CHECK-PRETTY: Type Format Dim ID HLSL Bind Count +; CHECK-PRETTY: ---------- ------- ----------- ------- -------------- --------- +; CHECK-PRETTY: UAV f32 buf U0 u5,space3 1 +; CHECK-PRETTY: UAV i32 buf U1 u7,space2 1 +; CHECK-PRETTY: SRV u32 buf T0 t3,space5 24 +; CHECK-PRETTY: SRV struct r/o T1 t2,space4 1 +; CHECK-PRETTY: SRV byte r/o T2 t8,space1 1 target triple = "dxil-pc-shadermodel6.6-compute" `````````` </details> https://github.com/llvm/llvm-project/pull/104448 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits