diff --git a/llvm/lib/Target/DirectX/CMakeLists.txt b/llvm/lib/Target/DirectX/CMakeLists.txt --- a/llvm/lib/Target/DirectX/CMakeLists.txt +++ b/llvm/lib/Target/DirectX/CMakeLists.txt @@ -20,6 +20,7 @@ DirectXTargetMachine.cpp DXContainerGlobals.cpp DXILMetadata.cpp + DXILMetadataResourceAnalysis.cpp DXILOpBuilder.cpp DXILOpLowering.cpp DXILPrepare.cpp diff --git a/llvm/lib/Target/DirectX/DXILMetadataResourceAnalysis.h b/llvm/lib/Target/DirectX/DXILMetadataResourceAnalysis.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/DirectX/DXILMetadataResourceAnalysis.h @@ -0,0 +1,68 @@ +//===- DXILMetadataResourceAnalysis.h - DXIL Metadata Resource analysis--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file This file contains Analysis which collect DXIL resources from DXIL +/// metadata. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_DIRECTX_DXILMETADATARESOURCEANALYSIS_H +#define LLVM_LIB_TARGET_DIRECTX_DXILMETADATARESOURCEANALYSIS_H + +#include "DXILResource.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include + +namespace llvm { +/// Analysis pass that exposes the \c DXILResource for a module from dxil +/// metadata. +class DXILMetadataResourceAnalysis + : public AnalysisInfoMixin { + friend AnalysisInfoMixin; + static AnalysisKey Key; + +public: + typedef dxil::Resources Result; + dxil::Resources run(Module &M, ModuleAnalysisManager &AM); +}; + +/// Printer pass for the \c DXILMetadataResourceAnalysis results. +class DXILMetadataResourcePrinterPass + : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit DXILMetadataResourcePrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +/// The legacy pass manager's analysis pass to compute DXIL resource +/// information from DXIL metadata. +class DXILMetadataResourceWrapper : public ModulePass { + dxil::Resources Resources; + +public: + static char ID; // Pass identification, replacement for typeid + + DXILMetadataResourceWrapper(); + + dxil::Resources &getDXILResource() { return Resources; } + const dxil::Resources &getDXILResource() const { return Resources; } + + /// Calculate the DXILResource for the module. + bool runOnModule(Module &M) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + void print(raw_ostream &O, const Module *M = nullptr) const override; +}; +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/DirectX/DXILMetadataResourceAnalysis.cpp b/llvm/lib/Target/DirectX/DXILMetadataResourceAnalysis.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/DirectX/DXILMetadataResourceAnalysis.cpp @@ -0,0 +1,53 @@ +//===- DXILMetadataResourceAnalysis.cpp - DXIL Metadata Resource analysis--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file This file contains Analysis which collect DXIL resources from DXIL +/// metadata. +/// +//===----------------------------------------------------------------------===// + +#include "DXILMetadataResourceAnalysis.h" +#include "DirectX.h" +#include "llvm/IR/PassManager.h" + +using namespace llvm; + +#define DEBUG_TYPE "dxil-metadata-resource-analysis" + +dxil::Resources DXILMetadataResourceAnalysis::run(Module &M, + ModuleAnalysisManager &AM) { + dxil::Resources R; + R.collectFromDXILMetadata(M); + return R; +} + +AnalysisKey DXILMetadataResourceAnalysis::Key; + +PreservedAnalyses +DXILMetadataResourcePrinterPass::run(Module &M, ModuleAnalysisManager &AM) { + dxil::Resources Res = AM.getResult(M); + Res.print(OS); + return PreservedAnalyses::all(); +} + +char DXILMetadataResourceWrapper::ID = 0; +INITIALIZE_PASS_BEGIN(DXILMetadataResourceWrapper, DEBUG_TYPE, + "DXIL resource Information from metadata", true, true) +INITIALIZE_PASS_END(DXILMetadataResourceWrapper, DEBUG_TYPE, + "DXIL resource Information from metadata", true, true) + +bool DXILMetadataResourceWrapper::runOnModule(Module &M) { + Resources.collectFromDXILMetadata(M); + return false; +} + +DXILMetadataResourceWrapper::DXILMetadataResourceWrapper() : ModulePass(ID) {} + +void DXILMetadataResourceWrapper::print(raw_ostream &OS, const Module *) const { + Resources.print(OS); +} diff --git a/llvm/lib/Target/DirectX/DXILResource.h b/llvm/lib/Target/DirectX/DXILResource.h --- a/llvm/lib/Target/DirectX/DXILResource.h +++ b/llvm/lib/Target/DirectX/DXILResource.h @@ -23,6 +23,8 @@ namespace llvm { class Module; class GlobalVariable; +class MDTuple; +class MDOperand; namespace dxil { class CBufferDataLayout; @@ -36,6 +38,7 @@ uint32_t LowerBound; uint32_t RangeSize; ResourceBase(uint32_t I, hlsl::FrontendResource R); + ResourceBase(const MDTuple *ResMD); void write(LLVMContext &Ctx, MutableArrayRef Entries) const; @@ -89,6 +92,7 @@ }; MDNode *write(LLVMContext &Ctx) const; + void loadExtProps(const MDTuple *ExtTuple); }; }; @@ -103,6 +107,7 @@ public: UAVResource(uint32_t I, hlsl::FrontendResource R); + UAVResource(const MDTuple *ResMD); MDNode *write() const; void print(raw_ostream &O) const; @@ -112,6 +117,8 @@ uint32_t CBufferSizeInBytes = 0; // Cbuffer used size in bytes. public: ConstantBuffer(uint32_t I, hlsl::FrontendResource R); + ConstantBuffer(const MDTuple *ResMD); + void setSize(CBufferDataLayout &DL); MDNode *write() const; void print(raw_ostream &O) const; @@ -125,6 +132,7 @@ public: ResourceTable(StringRef Name) : MDName(Name) {} void collect(Module &M); + void collectFromDXILMetadata(const MDOperand &MDO); MDNode *write(Module &M) const; void print(raw_ostream &O) const; }; @@ -139,6 +147,7 @@ public: void collect(Module &M); + void collectFromDXILMetadata(Module &M); void write(Module &M) const; void print(raw_ostream &O) const; LLVM_DUMP_METHOD void dump() const; diff --git a/llvm/lib/Target/DirectX/DXILResource.cpp b/llvm/lib/Target/DirectX/DXILResource.cpp --- a/llvm/lib/Target/DirectX/DXILResource.cpp +++ b/llvm/lib/Target/DirectX/DXILResource.cpp @@ -34,6 +34,21 @@ } } +template +void ResourceTable::collectFromDXILMetadata(const MDOperand &MDO) { + const MDTuple *Tuple = dyn_cast_or_null(MDO.get()); + if (!Tuple) + return; + + for (unsigned i = 0; i < Tuple->getNumOperands(); i++) { + const MDTuple *ResMD = + dyn_cast_or_null(Tuple->getOperand(i).get()); + assert(ResMD != nullptr && ""); + assert(ResMD->getNumOperands() >= 6 && ""); + Data.emplace_back(T(ResMD)); + } +} + template <> void ResourceTable::collect(Module &M) { NamedMDNode *Entry = M.getNamedMetadata(MDName); if (!Entry || Entry->getNumOperands() == 0) @@ -56,6 +71,20 @@ CBuffers.collect(M); } +void Resources::collectFromDXILMetadata(Module &M) { + NamedMDNode *ResNamedMD = M.getNamedMetadata("dx.resources"); + if (!ResNamedMD) + return; + MDNode *ResTab = ResNamedMD->getOperand(0); + if (ResTab->getNumOperands() != 4) + return; + + UAVs.collectFromDXILMetadata( + ResTab->getOperand(static_cast(hlsl::ResourceClass::UAV))); + CBuffers.collectFromDXILMetadata( + ResTab->getOperand(static_cast(hlsl::ResourceClass::CBuffer))); +} + ResourceBase::ResourceBase(uint32_t I, FrontendResource R) : ID(I), GV(R.getGlobalVariable()), Name(""), Space(R.getSpace()), LowerBound(R.getResourceIndex()), RangeSize(1) { @@ -63,6 +92,21 @@ RangeSize = ArrTy->getNumElements(); } +ResourceBase::ResourceBase(const MDTuple *ResMD) { + ID = + mdconst::extract(ResMD->getOperand(0))->getZExtValue(); + Constant *GlobalSymbol = mdconst::extract( + ResMD->getOperand(1)); + GV = cast(GlobalSymbol); + Name = dyn_cast(ResMD->getOperand(2).get())->getString(); + Space = + mdconst::extract(ResMD->getOperand(3))->getZExtValue(); + LowerBound = + mdconst::extract(ResMD->getOperand(4))->getZExtValue(); + RangeSize = + mdconst::extract(ResMD->getOperand(5))->getZExtValue(); +} + StringRef ResourceBase::getComponentTypeName(ComponentType CompType) { switch (CompType) { case ComponentType::LastEntry: @@ -237,6 +281,19 @@ parseSourceType(R.getSourceType()); } +UAVResource::UAVResource(const MDTuple *ResMD) : ResourceBase(ResMD) { + // UAV-specific fields. + Shape = static_cast( + mdconst::extract(ResMD->getOperand(6))->getZExtValue()); + GloballyCoherent = + mdconst::extract(ResMD->getOperand(7))->getZExtValue(); + HasCounter = + mdconst::extract(ResMD->getOperand(8))->getZExtValue(); + IsROV = mdconst::extract(ResMD->getOperand(9))->getZExtValue(); + if (const MDTuple *ExtTuple = dyn_cast_or_null(ResMD->getOperand(10).get())) + ExtProps.loadExtProps(ExtTuple); +} + void UAVResource::print(raw_ostream &OS) const { OS << "; " << left_justify(Name, 31); @@ -300,6 +357,11 @@ ConstantBuffer::ConstantBuffer(uint32_t I, hlsl::FrontendResource R) : ResourceBase(I, R) {} +ConstantBuffer::ConstantBuffer(const MDTuple *ResMD) : ResourceBase(ResMD) { + CBufferSizeInBytes = + mdconst::extract(ResMD->getOperand(6))->getZExtValue(); +} + void ConstantBuffer::setSize(CBufferDataLayout &DL) { CBufferSizeInBytes = DL.getTypeAllocSizeInBytes(GV->getValueType()); } @@ -321,6 +383,23 @@ Res.print(OS); } +void ResourceBase::ExtendedProperties::loadExtProps(const MDTuple *ExtTuple) { + for (unsigned i = 0; i < ExtTuple->getNumOperands(); i += 2) { + Tags ExtTag = static_cast(mdconst::extract(ExtTuple->getOperand(0))->getZExtValue()); + const MDOperand &MDO = ExtTuple->getOperand(i + 1); + switch (ExtTag) { + case Tags::TypedBufferElementType: + ElementType = static_cast(mdconst::extract(MDO)->getZExtValue()); + break; + case Tags::StructuredBufferElementStride: + case Tags::SamplerFeedbackKind: + case Tags::Atomic64Use: + // FIXME: support all ext props. + assert(0 && "not supported ext props"); + break; + } + } +} MDNode *ResourceBase::ExtendedProperties::write(LLVMContext &Ctx) const { IRBuilder<> B(Ctx); SmallVector Entries; diff --git a/llvm/lib/Target/DirectX/DirectX.h b/llvm/lib/Target/DirectX/DirectX.h --- a/llvm/lib/Target/DirectX/DirectX.h +++ b/llvm/lib/Target/DirectX/DirectX.h @@ -40,9 +40,12 @@ /// Pass to emit metadata for DXIL. ModulePass *createDXILTranslateMetadataPass(); -/// Initializer for DXILTranslateMetadata. +/// Initializer for DXILResourceWrapper. void initializeDXILResourceWrapperPass(PassRegistry &); +/// Initializer for DXILMetadataResourceWrapper. +void initializeDXILMetadataResourceWrapperPass(PassRegistry &); + /// Pass to pretty print DXIL metadata. ModulePass *createDXILPrettyPrinterPass(raw_ostream &OS); diff --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp --- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp +++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "DirectXTargetMachine.h" +#include "DXILMetadataResourceAnalysis.h" #include "DXILResourceAnalysis.h" #include "DXILShaderFlags.h" #include "DXILWriter/DXILWriterPass.h" @@ -107,6 +108,10 @@ PM.addPass(DXILResourcePrinterPass(dbgs())); return true; } + if (PassName == "print-dxil-resource-from-dxil-metadata") { + PM.addPass(DXILMetadataResourcePrinterPass(dbgs())); + return true; + } if (PassName == "print-dx-shader-flags") { PM.addPass(dxil::ShaderFlagsAnalysisPrinter(dbgs())); return true; @@ -116,6 +121,7 @@ PB.registerAnalysisRegistrationCallback([](ModuleAnalysisManager &MAM) { MAM.registerPass([&] { return DXILResourceAnalysis(); }); + MAM.registerPass([&] { return DXILMetadataResourceAnalysis(); }); MAM.registerPass([&] { return dxil::ShaderFlagsAnalysis(); }); }); } diff --git a/llvm/test/CodeGen/DirectX/UAVMetadata.ll b/llvm/test/CodeGen/DirectX/UAVMetadata.ll --- a/llvm/test/CodeGen/DirectX/UAVMetadata.ll +++ b/llvm/test/CodeGen/DirectX/UAVMetadata.ll @@ -1,5 +1,7 @@ ; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s ; RUN: opt -S --passes="print-dxil-resource" < %s 2>&1 | FileCheck %s --check-prefix=PRINT +; RUN: opt -S -dxil-metadata-emit < %s | opt -S --passes="print-dxil-resource-from-dxil-metadata" 2>&1 | FileCheck %s --check-prefix=PRINT + ; RUN: llc %s --filetype=asm -o - < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,PRINT target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" diff --git a/llvm/test/CodeGen/DirectX/cbuf.ll b/llvm/test/CodeGen/DirectX/cbuf.ll --- a/llvm/test/CodeGen/DirectX/cbuf.ll +++ b/llvm/test/CodeGen/DirectX/cbuf.ll @@ -1,5 +1,6 @@ ; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s --check-prefix=DXILMD ; RUN: opt -S --passes="print-dxil-resource" < %s 2>&1 | FileCheck %s --check-prefix=PRINT +; RUN: opt -S -dxil-metadata-emit < %s | opt -S --passes="print-dxil-resource-from-dxil-metadata" 2>&1 | FileCheck %s --check-prefix=PRINT target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" target triple = "dxil-unknown-shadermodel6.7-library"