From 263e8b67ef6c3a6bd90cf3844557dc40ee43b263 Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Thu, 12 Dec 2024 13:43:22 -0800 Subject: [PATCH 1/3] [DirectX] Split resource info into type and binding info. NFC This splits the DXILResourceAnalysis pass into TypeAnalysis and BindingAnalysis passes. The type analysis pass is made immutable and populated lazily so that it can be used earlier in the pipeline without needing to carefully maintain the invariants of the binding analysis. Fixes #118400 --- llvm/include/llvm/Analysis/DXILResource.h | 219 +++++++--- llvm/include/llvm/InitializePasses.h | 3 +- llvm/include/llvm/LinkAllPasses.h | 3 +- llvm/lib/Analysis/Analysis.cpp | 3 +- llvm/lib/Analysis/DXILResource.cpp | 386 ++++++++++------- llvm/lib/Passes/PassRegistry.def | 6 +- .../lib/Target/DirectX/DXContainerGlobals.cpp | 28 +- .../Target/DirectX/DXILDataScalarization.cpp | 7 - .../Target/DirectX/DXILFinalizeLinkage.cpp | 5 - llvm/lib/Target/DirectX/DXILFinalizeLinkage.h | 1 - llvm/lib/Target/DirectX/DXILFlattenArrays.cpp | 7 - .../Target/DirectX/DXILIntrinsicExpansion.cpp | 6 - llvm/lib/Target/DirectX/DXILOpLowering.cpp | 55 ++- llvm/lib/Target/DirectX/DXILPrepare.cpp | 2 +- llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp | 79 ++-- .../Target/DirectX/DXILTranslateMetadata.cpp | 47 ++- .../DXILResource/buffer-frombinding.ll | 4 +- llvm/test/CodeGen/DirectX/llc-pipeline.ll | 4 +- llvm/unittests/Analysis/DXILResourceTest.cpp | 393 +++++++++--------- 19 files changed, 727 insertions(+), 531 deletions(-) diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h index b3bcd244094d0..acde2f4bf41a2 100644 --- a/llvm/include/llvm/Analysis/DXILResource.h +++ b/llvm/include/llvm/Analysis/DXILResource.h @@ -25,6 +25,8 @@ class LLVMContext; class MDTuple; class Value; +class DXILResourceTypeMap; + namespace dxil { /// The dx.RawBuffer target extension type @@ -197,27 +199,8 @@ class SamplerExtType : public TargetExtType { //===----------------------------------------------------------------------===// -class ResourceInfo { +class ResourceTypeInfo { public: - struct ResourceBinding { - uint32_t RecordID; - uint32_t Space; - uint32_t LowerBound; - uint32_t Size; - - bool operator==(const ResourceBinding &RHS) const { - return std::tie(RecordID, Space, LowerBound, Size) == - std::tie(RHS.RecordID, RHS.Space, RHS.LowerBound, RHS.Size); - } - bool operator!=(const ResourceBinding &RHS) const { - return !(*this == RHS); - } - bool operator<(const ResourceBinding &RHS) const { - return std::tie(RecordID, Space, LowerBound, Size) < - std::tie(RHS.RecordID, RHS.Space, RHS.LowerBound, RHS.Size); - } - }; - struct UAVInfo { bool GloballyCoherent; bool HasCounter; @@ -267,12 +250,11 @@ class ResourceInfo { }; private: - ResourceBinding Binding; TargetExtType *HandleTy; // GloballyCoherent and HasCounter aren't really part of the type and need to - // be determined by analysis, so they're just provided directly when we - // construct these. + // be determined by analysis, so they're just provided directly by the + // DXILResourceTypeMap when we construct these. bool GloballyCoherent; bool HasCounter; @@ -280,9 +262,13 @@ class ResourceInfo { dxil::ResourceKind Kind; public: - ResourceInfo(uint32_t RecordID, uint32_t Space, uint32_t LowerBound, - uint32_t Size, TargetExtType *HandleTy, - bool GloballyCoherent = false, bool HasCounter = false); + ResourceTypeInfo(TargetExtType *HandleTy, const dxil::ResourceClass RC, + const dxil::ResourceKind Kind, bool GloballyCoherent = false, + bool HasCounter = false); + ResourceTypeInfo(TargetExtType *HandleTy, bool GloballyCoherent = false, + bool HasCounter = false) + : ResourceTypeInfo(HandleTy, {}, dxil::ResourceKind::Invalid, + GloballyCoherent, HasCounter) {} TargetExtType *getHandleTy() const { return HandleTy; } @@ -304,44 +290,157 @@ class ResourceInfo { dxil::SamplerFeedbackType getFeedbackType() const; uint32_t getMultiSampleCount() const; - StringRef getName() const { - // TODO: Get the name from the symbol once we include one here. - return ""; - } dxil::ResourceClass getResourceClass() const { return RC; } dxil::ResourceKind getResourceKind() const { return Kind; } + bool operator==(const ResourceTypeInfo &RHS) const; + bool operator!=(const ResourceTypeInfo &RHS) const { return !(*this == RHS); } + bool operator<(const ResourceTypeInfo &RHS) const; + + void print(raw_ostream &OS, const DataLayout &DL) const; +}; + +//===----------------------------------------------------------------------===// + +class ResourceBindingInfo { +public: + struct ResourceBinding { + uint32_t RecordID; + uint32_t Space; + uint32_t LowerBound; + uint32_t Size; + + bool operator==(const ResourceBinding &RHS) const { + return std::tie(RecordID, Space, LowerBound, Size) == + std::tie(RHS.RecordID, RHS.Space, RHS.LowerBound, RHS.Size); + } + bool operator!=(const ResourceBinding &RHS) const { + return !(*this == RHS); + } + bool operator<(const ResourceBinding &RHS) const { + return std::tie(RecordID, Space, LowerBound, Size) < + std::tie(RHS.RecordID, RHS.Space, RHS.LowerBound, RHS.Size); + } + }; + +private: + ResourceBinding Binding; + TargetExtType *HandleTy; + +public: + ResourceBindingInfo(uint32_t RecordID, uint32_t Space, uint32_t LowerBound, + uint32_t Size, TargetExtType *HandleTy) + : Binding{RecordID, Space, LowerBound, Size}, HandleTy(HandleTy) {} + void setBindingID(unsigned ID) { Binding.RecordID = ID; } const ResourceBinding &getBinding() const { return Binding; } + TargetExtType *getHandleTy() const { return HandleTy; } + const StringRef getName() const { + // TODO: Get the name from the symbol once we include one here. + return ""; + } - MDTuple *getAsMetadata(Module &M) const; - std::pair getAnnotateProps(Module &M) const; + MDTuple *getAsMetadata(Module &M, DXILResourceTypeMap &DRTM) const; + MDTuple *getAsMetadata(Module &M, dxil::ResourceTypeInfo RTI) const; - bool operator==(const ResourceInfo &RHS) const; - bool operator!=(const ResourceInfo &RHS) const { return !(*this == RHS); } - bool operator<(const ResourceInfo &RHS) const; + std::pair + getAnnotateProps(Module &M, DXILResourceTypeMap &DRTM) const; + std::pair + getAnnotateProps(Module &M, dxil::ResourceTypeInfo RTI) const; - void print(raw_ostream &OS, const DataLayout &DL) const; + bool operator==(const ResourceBindingInfo &RHS) const { + return std::tie(Binding, HandleTy) == std::tie(RHS.Binding, RHS.HandleTy); + } + bool operator!=(const ResourceBindingInfo &RHS) const { + return !(*this == RHS); + } + bool operator<(const ResourceBindingInfo &RHS) const { + return Binding < RHS.Binding; + } + + void print(raw_ostream &OS, DXILResourceTypeMap &DRTM, + const DataLayout &DL) const; + void print(raw_ostream &OS, dxil::ResourceTypeInfo RTI, + const DataLayout &DL) const; }; } // namespace dxil //===----------------------------------------------------------------------===// -class DXILResourceMap { - SmallVector Infos; +class DXILResourceTypeMap { + struct Info { + dxil::ResourceClass RC; + dxil::ResourceKind Kind; + bool GloballyCoherent; + bool HasCounter; + }; + DenseMap Infos; + +public: + bool invalidate(Module &M, const PreservedAnalyses &PA, + ModuleAnalysisManager::Invalidator &Inv); + + dxil::ResourceTypeInfo operator[](TargetExtType *Ty) { + Info I = Infos[Ty]; + return dxil::ResourceTypeInfo(Ty, I.RC, I.Kind, I.GloballyCoherent, + I.HasCounter); + } + + void setGloballyCoherent(TargetExtType *Ty, bool GloballyCoherent) { + Infos[Ty].GloballyCoherent = GloballyCoherent; + } + + void setHasCounter(TargetExtType *Ty, bool HasCounter) { + Infos[Ty].HasCounter = HasCounter; + } +}; + +class DXILResourceTypeAnalysis + : public AnalysisInfoMixin { + friend AnalysisInfoMixin; + + static AnalysisKey Key; + +public: + using Result = DXILResourceTypeMap; + + DXILResourceTypeMap run(Module &M, ModuleAnalysisManager &AM) { + return Result(); + } +}; + +class DXILResourceTypeWrapperPass : public ImmutablePass { + DXILResourceTypeMap DRTM; + + virtual void anchor(); + +public: + static char ID; + DXILResourceTypeWrapperPass(); + + DXILResourceTypeMap &getResourceTypeMap() { return DRTM; } + const DXILResourceTypeMap &getResourceTypeMap() const { return DRTM; } +}; + +ModulePass *createDXILResourceTypeWrapperPassPass(); + +//===----------------------------------------------------------------------===// + +class DXILBindingMap { + SmallVector Infos; DenseMap CallMap; unsigned FirstUAV = 0; unsigned FirstCBuffer = 0; unsigned FirstSampler = 0; /// Populate the map given the resource binding calls in the given module. - void populate(Module &M); + void populate(Module &M, DXILResourceTypeMap &DRTM); public: - using iterator = SmallVector::iterator; - using const_iterator = SmallVector::const_iterator; + using iterator = SmallVector::iterator; + using const_iterator = SmallVector::const_iterator; iterator begin() { return Infos.begin(); } const_iterator begin() const { return Infos.begin(); } @@ -400,47 +499,51 @@ class DXILResourceMap { return make_range(sampler_begin(), sampler_end()); } - void print(raw_ostream &OS, const DataLayout &DL) const; + void print(raw_ostream &OS, DXILResourceTypeMap &DRTM, + const DataLayout &DL) const; - friend class DXILResourceAnalysis; - friend class DXILResourceWrapperPass; + friend class DXILResourceBindingAnalysis; + friend class DXILResourceBindingWrapperPass; }; -class DXILResourceAnalysis : public AnalysisInfoMixin { - friend AnalysisInfoMixin; +class DXILResourceBindingAnalysis + : public AnalysisInfoMixin { + friend AnalysisInfoMixin; static AnalysisKey Key; public: - using Result = DXILResourceMap; + using Result = DXILBindingMap; /// Gather resource info for the module \c M. - DXILResourceMap run(Module &M, ModuleAnalysisManager &AM); + DXILBindingMap run(Module &M, ModuleAnalysisManager &AM); }; -/// Printer pass for the \c DXILResourceAnalysis results. -class DXILResourcePrinterPass : public PassInfoMixin { +/// Printer pass for the \c DXILResourceBindingAnalysis results. +class DXILResourceBindingPrinterPass + : public PassInfoMixin { raw_ostream &OS; public: - explicit DXILResourcePrinterPass(raw_ostream &OS) : OS(OS) {} + explicit DXILResourceBindingPrinterPass(raw_ostream &OS) : OS(OS) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); static bool isRequired() { return true; } }; -class DXILResourceWrapperPass : public ModulePass { - std::unique_ptr Map; +class DXILResourceBindingWrapperPass : public ModulePass { + std::unique_ptr Map; + DXILResourceTypeMap *DRTM; public: static char ID; // Class identification, replacement for typeinfo - DXILResourceWrapperPass(); - ~DXILResourceWrapperPass() override; + DXILResourceBindingWrapperPass(); + ~DXILResourceBindingWrapperPass() override; - const DXILResourceMap &getResourceMap() const { return *Map; } - DXILResourceMap &getResourceMap() { return *Map; } + const DXILBindingMap &getBindingMap() const { return *Map; } + DXILBindingMap &getBindingMap() { return *Map; } void getAnalysisUsage(AnalysisUsage &AU) const override; bool runOnModule(Module &M) override; @@ -450,7 +553,7 @@ class DXILResourceWrapperPass : public ModulePass { void dump() const; }; -ModulePass *createDXILResourceWrapperPassPass(); +ModulePass *createDXILResourceBindingWrapperPassPass(); } // namespace llvm diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index 7d829cf5b9b01..1cb9013bc48cc 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -84,7 +84,8 @@ void initializeDAHPass(PassRegistry &); void initializeDCELegacyPassPass(PassRegistry &); void initializeDXILMetadataAnalysisWrapperPassPass(PassRegistry &); void initializeDXILMetadataAnalysisWrapperPrinterPass(PassRegistry &); -void initializeDXILResourceWrapperPassPass(PassRegistry &); +void initializeDXILResourceBindingWrapperPassPass(PassRegistry &); +void initializeDXILResourceTypeWrapperPassPass(PassRegistry &); void initializeDeadMachineInstructionElimPass(PassRegistry &); void initializeDebugifyMachineModulePass(PassRegistry &); void initializeDependenceAnalysisWrapperPassPass(PassRegistry &); diff --git a/llvm/include/llvm/LinkAllPasses.h b/llvm/include/llvm/LinkAllPasses.h index 54245ca0b7022..ac1970334de0c 100644 --- a/llvm/include/llvm/LinkAllPasses.h +++ b/llvm/include/llvm/LinkAllPasses.h @@ -70,7 +70,8 @@ struct ForcePassLinking { (void)llvm::createCallGraphViewerPass(); (void)llvm::createCFGSimplificationPass(); (void)llvm::createStructurizeCFGPass(); - (void)llvm::createDXILResourceWrapperPassPass(); + (void)llvm::createDXILResourceBindingWrapperPassPass(); + (void)llvm::createDXILResourceTypeWrapperPassPass(); (void)llvm::createDeadArgEliminationPass(); (void)llvm::createDeadCodeEliminationPass(); (void)llvm::createDependenceAnalysisWrapperPass(); diff --git a/llvm/lib/Analysis/Analysis.cpp b/llvm/lib/Analysis/Analysis.cpp index 58723469f21ca..bc2b8a57f83a7 100644 --- a/llvm/lib/Analysis/Analysis.cpp +++ b/llvm/lib/Analysis/Analysis.cpp @@ -25,7 +25,8 @@ void llvm::initializeAnalysis(PassRegistry &Registry) { initializeCallGraphDOTPrinterPass(Registry); initializeCallGraphViewerPass(Registry); initializeCycleInfoWrapperPassPass(Registry); - initializeDXILResourceWrapperPassPass(Registry); + initializeDXILResourceBindingWrapperPassPass(Registry); + initializeDXILResourceTypeWrapperPassPass(Registry); initializeDependenceAnalysisWrapperPassPass(Registry); initializeDominanceFrontierWrapperPassPass(Registry); initializeDomViewerWrapperPassPass(Registry); diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp index 3fa9d67488b0c..07b1617d7b359 100644 --- a/llvm/lib/Analysis/DXILResource.cpp +++ b/llvm/lib/Analysis/DXILResource.cpp @@ -177,12 +177,19 @@ static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned) { return ElementType::Invalid; } -ResourceInfo::ResourceInfo(uint32_t RecordID, uint32_t Space, - uint32_t LowerBound, uint32_t Size, - TargetExtType *HandleTy, bool GloballyCoherent, - bool HasCounter) - : Binding{RecordID, Space, LowerBound, Size}, HandleTy(HandleTy), - GloballyCoherent(GloballyCoherent), HasCounter(HasCounter) { +ResourceTypeInfo::ResourceTypeInfo(TargetExtType *HandleTy, + const dxil::ResourceClass RC_, + const dxil::ResourceKind Kind_, + bool GloballyCoherent, bool HasCounter) + : HandleTy(HandleTy), GloballyCoherent(GloballyCoherent), + HasCounter(HasCounter) { + // If we're provided a resource class and kind, trust them. + if (Kind_ != dxil::ResourceKind::Invalid) { + RC = RC_; + Kind = Kind_; + return; + } + if (auto *Ty = dyn_cast(HandleTy)) { RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV; Kind = Ty->isStructured() ? ResourceKind::StructuredBuffer @@ -209,17 +216,21 @@ ResourceInfo::ResourceInfo(uint32_t RecordID, uint32_t Space, llvm_unreachable("Unknown handle type"); } -bool ResourceInfo::isUAV() const { return RC == ResourceClass::UAV; } +bool ResourceTypeInfo::isUAV() const { return RC == ResourceClass::UAV; } -bool ResourceInfo::isCBuffer() const { return RC == ResourceClass::CBuffer; } +bool ResourceTypeInfo::isCBuffer() const { + return RC == ResourceClass::CBuffer; +} -bool ResourceInfo::isSampler() const { return RC == ResourceClass::Sampler; } +bool ResourceTypeInfo::isSampler() const { + return RC == ResourceClass::Sampler; +} -bool ResourceInfo::isStruct() const { +bool ResourceTypeInfo::isStruct() const { return Kind == ResourceKind::StructuredBuffer; } -bool ResourceInfo::isTyped() const { +bool ResourceTypeInfo::isTyped() const { switch (Kind) { case ResourceKind::Texture1D: case ResourceKind::Texture2D: @@ -248,12 +259,12 @@ bool ResourceInfo::isTyped() const { llvm_unreachable("Unhandled ResourceKind enum"); } -bool ResourceInfo::isFeedback() const { +bool ResourceTypeInfo::isFeedback() const { return Kind == ResourceKind::FeedbackTexture2D || Kind == ResourceKind::FeedbackTexture2DArray; } -bool ResourceInfo::isMultiSample() const { +bool ResourceTypeInfo::isMultiSample() const { return Kind == ResourceKind::Texture2DMS || Kind == ResourceKind::Texture2DMSArray; } @@ -289,22 +300,23 @@ static bool isROV(dxil::ResourceKind Kind, TargetExtType *Ty) { llvm_unreachable("Unhandled ResourceKind enum"); } -ResourceInfo::UAVInfo ResourceInfo::getUAV() const { +ResourceTypeInfo::UAVInfo ResourceTypeInfo::getUAV() const { assert(isUAV() && "Not a UAV"); return {GloballyCoherent, HasCounter, isROV(Kind, HandleTy)}; } -uint32_t ResourceInfo::getCBufferSize(const DataLayout &DL) const { +uint32_t ResourceTypeInfo::getCBufferSize(const DataLayout &DL) const { assert(isCBuffer() && "Not a CBuffer"); return cast(HandleTy)->getCBufferSize(); } -dxil::SamplerType ResourceInfo::getSamplerType() const { +dxil::SamplerType ResourceTypeInfo::getSamplerType() const { assert(isSampler() && "Not a Sampler"); return cast(HandleTy)->getSamplerType(); } -ResourceInfo::StructInfo ResourceInfo::getStruct(const DataLayout &DL) const { +ResourceTypeInfo::StructInfo +ResourceTypeInfo::getStruct(const DataLayout &DL) const { assert(isStruct() && "Not a Struct"); Type *ElTy = cast(HandleTy)->getResourceType(); @@ -354,7 +366,7 @@ static std::pair getTypedElementType(dxil::ResourceKind Kind, llvm_unreachable("Unhandled ResourceKind enum"); } -ResourceInfo::TypedInfo ResourceInfo::getTyped() const { +ResourceTypeInfo::TypedInfo ResourceTypeInfo::getTyped() const { assert(isTyped() && "Not typed"); auto [ElTy, IsSigned] = getTypedElementType(Kind, HandleTy); @@ -365,17 +377,85 @@ ResourceInfo::TypedInfo ResourceInfo::getTyped() const { return {ET, Count}; } -dxil::SamplerFeedbackType ResourceInfo::getFeedbackType() const { +dxil::SamplerFeedbackType ResourceTypeInfo::getFeedbackType() const { assert(isFeedback() && "Not Feedback"); return cast(HandleTy)->getFeedbackType(); } - -uint32_t ResourceInfo::getMultiSampleCount() const { +uint32_t ResourceTypeInfo::getMultiSampleCount() const { assert(isMultiSample() && "Not MultiSampled"); return cast(HandleTy)->getSampleCount(); } -MDTuple *ResourceInfo::getAsMetadata(Module &M) const { +bool ResourceTypeInfo::operator==(const ResourceTypeInfo &RHS) const { + return std::tie(HandleTy, GloballyCoherent, HasCounter) == + std::tie(RHS.HandleTy, RHS.GloballyCoherent, RHS.HasCounter); +} + +bool ResourceTypeInfo::operator<(const ResourceTypeInfo &RHS) const { + // An empty datalayout is sufficient for sorting purposes. + DataLayout DummyDL; + if (std::tie(RC, Kind) < std::tie(RHS.RC, RHS.Kind)) + return true; + if (isCBuffer() && RHS.isCBuffer() && + getCBufferSize(DummyDL) < RHS.getCBufferSize(DummyDL)) + return true; + if (isSampler() && RHS.isSampler() && getSamplerType() < RHS.getSamplerType()) + return true; + if (isUAV() && RHS.isUAV() && getUAV() < RHS.getUAV()) + return true; + if (isStruct() && RHS.isStruct() && + getStruct(DummyDL) < RHS.getStruct(DummyDL)) + return true; + if (isFeedback() && RHS.isFeedback() && + getFeedbackType() < RHS.getFeedbackType()) + return true; + if (isTyped() && RHS.isTyped() && getTyped() < RHS.getTyped()) + return true; + if (isMultiSample() && RHS.isMultiSample() && + getMultiSampleCount() < RHS.getMultiSampleCount()) + return true; + return false; +} + +void ResourceTypeInfo::print(raw_ostream &OS, const DataLayout &DL) const { + OS << " Class: " << getResourceClassName(RC) << "\n" + << " Kind: " << getResourceKindName(Kind) << "\n"; + + if (isCBuffer()) { + OS << " CBuffer size: " << getCBufferSize(DL) << "\n"; + } else if (isSampler()) { + OS << " Sampler Type: " << getSamplerTypeName(getSamplerType()) << "\n"; + } else { + if (isUAV()) { + UAVInfo UAVFlags = getUAV(); + OS << " Globally Coherent: " << UAVFlags.GloballyCoherent << "\n" + << " HasCounter: " << UAVFlags.HasCounter << "\n" + << " IsROV: " << UAVFlags.IsROV << "\n"; + } + if (isMultiSample()) + OS << " Sample Count: " << getMultiSampleCount() << "\n"; + + if (isStruct()) { + StructInfo Struct = getStruct(DL); + OS << " Buffer Stride: " << Struct.Stride << "\n"; + OS << " Alignment: " << Struct.AlignLog2 << "\n"; + } else if (isTyped()) { + TypedInfo Typed = getTyped(); + OS << " Element Type: " << getElementTypeName(Typed.ElementTy) << "\n" + << " Element Count: " << Typed.ElementCount << "\n"; + } else if (isFeedback()) + OS << " Feedback Type: " << getSamplerFeedbackTypeName(getFeedbackType()) + << "\n"; + } +} + +MDTuple *ResourceBindingInfo::getAsMetadata(Module &M, + DXILResourceTypeMap &DRTM) const { + return getAsMetadata(M, DRTM[getHandleTy()]); +} + +MDTuple *ResourceBindingInfo::getAsMetadata(Module &M, + dxil::ResourceTypeInfo RTI) const { LLVMContext &Ctx = M.getContext(); const DataLayout &DL = M.getDataLayout(); @@ -404,17 +484,17 @@ MDTuple *ResourceInfo::getAsMetadata(Module &M) const { MDVals.push_back(getIntMD(Binding.LowerBound)); MDVals.push_back(getIntMD(Binding.Size)); - if (isCBuffer()) { - MDVals.push_back(getIntMD(getCBufferSize(DL))); + if (RTI.isCBuffer()) { + MDVals.push_back(getIntMD(RTI.getCBufferSize(DL))); MDVals.push_back(nullptr); - } else if (isSampler()) { - MDVals.push_back(getIntMD(llvm::to_underlying(getSamplerType()))); + } else if (RTI.isSampler()) { + MDVals.push_back(getIntMD(llvm::to_underlying(RTI.getSamplerType()))); MDVals.push_back(nullptr); } else { - MDVals.push_back(getIntMD(llvm::to_underlying(getResourceKind()))); + MDVals.push_back(getIntMD(llvm::to_underlying(RTI.getResourceKind()))); - if (isUAV()) { - ResourceInfo::UAVInfo UAVFlags = getUAV(); + if (RTI.isUAV()) { + ResourceTypeInfo::UAVInfo UAVFlags = RTI.getUAV(); MDVals.push_back(getBoolMD(UAVFlags.GloballyCoherent)); MDVals.push_back(getBoolMD(UAVFlags.HasCounter)); MDVals.push_back(getBoolMD(UAVFlags.IsROV)); @@ -422,23 +502,24 @@ MDTuple *ResourceInfo::getAsMetadata(Module &M) const { // All SRVs include sample count in the metadata, but it's only meaningful // for multi-sampled textured. Also, UAVs can be multisampled in SM6.7+, // but this just isn't reflected in the metadata at all. - uint32_t SampleCount = isMultiSample() ? getMultiSampleCount() : 0; + uint32_t SampleCount = + RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0; MDVals.push_back(getIntMD(SampleCount)); } // Further properties are attached to a metadata list of tag-value pairs. SmallVector Tags; - if (isStruct()) { + if (RTI.isStruct()) { Tags.push_back( getIntMD(llvm::to_underlying(ExtPropTags::StructuredBufferStride))); - Tags.push_back(getIntMD(getStruct(DL).Stride)); - } else if (isTyped()) { + Tags.push_back(getIntMD(RTI.getStruct(DL).Stride)); + } else if (RTI.isTyped()) { Tags.push_back(getIntMD(llvm::to_underlying(ExtPropTags::ElementType))); - Tags.push_back(getIntMD(llvm::to_underlying(getTyped().ElementTy))); - } else if (isFeedback()) { + Tags.push_back(getIntMD(llvm::to_underlying(RTI.getTyped().ElementTy))); + } else if (RTI.isFeedback()) { Tags.push_back( getIntMD(llvm::to_underlying(ExtPropTags::SamplerFeedbackKind))); - Tags.push_back(getIntMD(llvm::to_underlying(getFeedbackType()))); + Tags.push_back(getIntMD(llvm::to_underlying(RTI.getFeedbackType()))); } MDVals.push_back(Tags.empty() ? nullptr : MDNode::get(Ctx, Tags)); } @@ -446,20 +527,29 @@ MDTuple *ResourceInfo::getAsMetadata(Module &M) const { return MDNode::get(Ctx, MDVals); } -std::pair ResourceInfo::getAnnotateProps(Module &M) const { +std::pair +ResourceBindingInfo::getAnnotateProps(Module &M, + DXILResourceTypeMap &DRTM) const { + return getAnnotateProps(M, DRTM[getHandleTy()]); +} + +std::pair +ResourceBindingInfo::getAnnotateProps(Module &M, + dxil::ResourceTypeInfo RTI) const { const DataLayout &DL = M.getDataLayout(); - uint32_t ResourceKind = llvm::to_underlying(getResourceKind()); - uint32_t AlignLog2 = isStruct() ? getStruct(DL).AlignLog2 : 0; - bool IsUAV = isUAV(); - ResourceInfo::UAVInfo UAVFlags = IsUAV ? getUAV() : ResourceInfo::UAVInfo{}; + uint32_t ResourceKind = llvm::to_underlying(RTI.getResourceKind()); + uint32_t AlignLog2 = RTI.isStruct() ? RTI.getStruct(DL).AlignLog2 : 0; + bool IsUAV = RTI.isUAV(); + ResourceTypeInfo::UAVInfo UAVFlags = + IsUAV ? RTI.getUAV() : ResourceTypeInfo::UAVInfo{}; bool IsROV = IsUAV && UAVFlags.IsROV; bool IsGloballyCoherent = IsUAV && UAVFlags.GloballyCoherent; uint8_t SamplerCmpOrHasCounter = 0; if (IsUAV) SamplerCmpOrHasCounter = UAVFlags.HasCounter; - else if (isSampler()) - SamplerCmpOrHasCounter = getSamplerType() == SamplerType::Comparison; + else if (RTI.isSampler()) + SamplerCmpOrHasCounter = RTI.getSamplerType() == SamplerType::Comparison; // TODO: Document this format. Currently the only reference is the // implementation of dxc's DxilResourceProperties struct. @@ -472,17 +562,17 @@ std::pair ResourceInfo::getAnnotateProps(Module &M) const { Word0 |= (SamplerCmpOrHasCounter & 1) << 15; uint32_t Word1 = 0; - if (isStruct()) - Word1 = getStruct(DL).Stride; - else if (isCBuffer()) - Word1 = getCBufferSize(DL); - else if (isFeedback()) - Word1 = llvm::to_underlying(getFeedbackType()); - else if (isTyped()) { - ResourceInfo::TypedInfo Typed = getTyped(); + if (RTI.isStruct()) + Word1 = RTI.getStruct(DL).Stride; + else if (RTI.isCBuffer()) + Word1 = RTI.getCBufferSize(DL); + else if (RTI.isFeedback()) + Word1 = llvm::to_underlying(RTI.getFeedbackType()); + else if (RTI.isTyped()) { + ResourceTypeInfo::TypedInfo Typed = RTI.getTyped(); uint32_t CompType = llvm::to_underlying(Typed.ElementTy); uint32_t CompCount = Typed.ElementCount; - uint32_t SampleCount = isMultiSample() ? getMultiSampleCount() : 0; + uint32_t SampleCount = RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0; Word1 |= (CompType & 0xFF) << 0; Word1 |= (CompCount & 0xFF) << 8; @@ -492,80 +582,36 @@ std::pair ResourceInfo::getAnnotateProps(Module &M) const { return {Word0, Word1}; } -bool ResourceInfo::operator==(const ResourceInfo &RHS) const { - return std::tie(Binding, HandleTy, GloballyCoherent, HasCounter) == - std::tie(RHS.Binding, RHS.HandleTy, RHS.GloballyCoherent, - RHS.HasCounter); +void ResourceBindingInfo::print(raw_ostream &OS, DXILResourceTypeMap &DRTM, + const DataLayout &DL) const { + print(OS, DRTM[getHandleTy()], DL); } -bool ResourceInfo::operator<(const ResourceInfo &RHS) const { - // An empty datalayout is sufficient for sorting purposes. - DataLayout DummyDL; - if (std::tie(Binding, RC, Kind) < std::tie(RHS.Binding, RHS.RC, RHS.Kind)) - return true; - if (isCBuffer() && RHS.isCBuffer() && - getCBufferSize(DummyDL) < RHS.getCBufferSize(DummyDL)) - return true; - if (isSampler() && RHS.isSampler() && getSamplerType() < RHS.getSamplerType()) - return true; - if (isUAV() && RHS.isUAV() && getUAV() < RHS.getUAV()) - return true; - if (isStruct() && RHS.isStruct() && - getStruct(DummyDL) < RHS.getStruct(DummyDL)) - return true; - if (isFeedback() && RHS.isFeedback() && - getFeedbackType() < RHS.getFeedbackType()) - return true; - if (isTyped() && RHS.isTyped() && getTyped() < RHS.getTyped()) - return true; - if (isMultiSample() && RHS.isMultiSample() && - getMultiSampleCount() < RHS.getMultiSampleCount()) - return true; - return false; -} - -void ResourceInfo::print(raw_ostream &OS, const DataLayout &DL) const { +void ResourceBindingInfo::print(raw_ostream &OS, dxil::ResourceTypeInfo RTI, + const DataLayout &DL) const { OS << " Binding:\n" << " Record ID: " << Binding.RecordID << "\n" << " Space: " << Binding.Space << "\n" << " Lower Bound: " << Binding.LowerBound << "\n" << " Size: " << Binding.Size << "\n"; - OS << " Class: " << getResourceClassName(RC) << "\n" - << " Kind: " << getResourceKindName(Kind) << "\n"; + RTI.print(OS, DL); +} - if (isCBuffer()) { - OS << " CBuffer size: " << getCBufferSize(DL) << "\n"; - } else if (isSampler()) { - OS << " Sampler Type: " << getSamplerTypeName(getSamplerType()) << "\n"; - } else { - if (isUAV()) { - UAVInfo UAVFlags = getUAV(); - OS << " Globally Coherent: " << UAVFlags.GloballyCoherent << "\n" - << " HasCounter: " << UAVFlags.HasCounter << "\n" - << " IsROV: " << UAVFlags.IsROV << "\n"; - } - if (isMultiSample()) - OS << " Sample Count: " << getMultiSampleCount() << "\n"; +//===----------------------------------------------------------------------===// - if (isStruct()) { - StructInfo Struct = getStruct(DL); - OS << " Buffer Stride: " << Struct.Stride << "\n"; - OS << " Alignment: " << Struct.AlignLog2 << "\n"; - } else if (isTyped()) { - TypedInfo Typed = getTyped(); - OS << " Element Type: " << getElementTypeName(Typed.ElementTy) << "\n" - << " Element Count: " << Typed.ElementCount << "\n"; - } else if (isFeedback()) - OS << " Feedback Type: " << getSamplerFeedbackTypeName(getFeedbackType()) - << "\n"; - } +bool DXILResourceTypeMap::invalidate(Module &M, const PreservedAnalyses &PA, + ModuleAnalysisManager::Invalidator &Inv) { + // Passes that introduce resource types must explicitly invalidate this pass. + auto PAC = PA.getChecker(); + return !PAC.preservedWhenStateless(); } //===----------------------------------------------------------------------===// -void DXILResourceMap::populate(Module &M) { - SmallVector> CIToInfo; +void DXILBindingMap::populate(Module &M, DXILResourceTypeMap &DRTM) { + SmallVector> + CIToInfos; for (Function &F : M.functions()) { if (!F.isDeclaration()) @@ -577,6 +623,7 @@ void DXILResourceMap::populate(Module &M) { continue; case Intrinsic::dx_handle_fromBinding: { auto *HandleTy = cast(F.getReturnType()); + ResourceTypeInfo RTI = DRTM[HandleTy]; for (User *U : F.users()) if (CallInst *CI = dyn_cast(U)) { @@ -587,10 +634,10 @@ void DXILResourceMap::populate(Module &M) { cast(CI->getArgOperand(1))->getZExtValue(); uint32_t Size = cast(CI->getArgOperand(2))->getZExtValue(); - ResourceInfo RI = - ResourceInfo{/*RecordID=*/0, Space, LowerBound, Size, HandleTy}; + ResourceBindingInfo RBI = ResourceBindingInfo{ + /*RecordID=*/0, Space, LowerBound, Size, HandleTy}; - CIToInfo.emplace_back(CI, RI); + CIToInfos.emplace_back(CI, RBI, RTI); } break; @@ -598,16 +645,19 @@ void DXILResourceMap::populate(Module &M) { } } - llvm::stable_sort(CIToInfo, [](auto &LHS, auto &RHS) { - // Sort by resource class first for grouping purposes, and then by the rest - // of the fields so that we can remove duplicates. - ResourceClass LRC = LHS.second.getResourceClass(); - ResourceClass RRC = RHS.second.getResourceClass(); - return std::tie(LRC, LHS.second) < std::tie(RRC, RHS.second); + llvm::stable_sort(CIToInfos, [](auto &LHS, auto &RHS) { + const auto &[LCI, LRBI, LRTI] = LHS; + const auto &[RCI, RRBI, RRTI] = RHS; + // Sort by resource class first for grouping purposes, and then by the + // binding and type so we can remove duplicates. + ResourceClass LRC = LRTI.getResourceClass(); + ResourceClass RRC = RRTI.getResourceClass(); + + return std::tie(LRC, LRBI, LRTI) < std::tie(RRC, RRBI, RRTI); }); - for (auto [CI, RI] : CIToInfo) { - if (Infos.empty() || RI != Infos.back()) - Infos.push_back(RI); + for (auto [CI, RBI, RTI] : CIToInfos) { + if (Infos.empty() || RBI != Infos.back()) + Infos.push_back(RBI); CallMap[CI] = Infos.size() - 1; } @@ -616,27 +666,29 @@ void DXILResourceMap::populate(Module &M) { FirstUAV = FirstCBuffer = FirstSampler = Size; uint32_t NextID = 0; for (unsigned I = 0, E = Size; I != E; ++I) { - ResourceInfo &RI = Infos[I]; - if (RI.isUAV() && FirstUAV == Size) { + ResourceBindingInfo &RBI = Infos[I]; + ResourceTypeInfo RTI = DRTM[RBI.getHandleTy()]; + if (RTI.isUAV() && FirstUAV == Size) { FirstUAV = I; NextID = 0; - } else if (RI.isCBuffer() && FirstCBuffer == Size) { + } else if (RTI.isCBuffer() && FirstCBuffer == Size) { FirstCBuffer = I; NextID = 0; - } else if (RI.isSampler() && FirstSampler == Size) { + } else if (RTI.isSampler() && FirstSampler == Size) { FirstSampler = I; NextID = 0; } // Adjust the resource binding to use the next ID. - RI.setBindingID(NextID++); + RBI.setBindingID(NextID++); } } -void DXILResourceMap::print(raw_ostream &OS, const DataLayout &DL) const { +void DXILBindingMap::print(raw_ostream &OS, DXILResourceTypeMap &DRTM, + const DataLayout &DL) const { for (unsigned I = 0, E = Infos.size(); I != E; ++I) { OS << "Binding " << I << ":\n"; - Infos[I].print(OS, DL); + Infos[I].print(OS, DRTM, DL); OS << "\n"; } @@ -649,60 +701,82 @@ void DXILResourceMap::print(raw_ostream &OS, const DataLayout &DL) const { //===----------------------------------------------------------------------===// -AnalysisKey DXILResourceAnalysis::Key; +AnalysisKey DXILResourceTypeAnalysis::Key; +AnalysisKey DXILResourceBindingAnalysis::Key; -DXILResourceMap DXILResourceAnalysis::run(Module &M, - ModuleAnalysisManager &AM) { - DXILResourceMap Data; - Data.populate(M); +DXILBindingMap DXILResourceBindingAnalysis::run(Module &M, + ModuleAnalysisManager &AM) { + DXILBindingMap Data; + DXILResourceTypeMap &DRTM = AM.getResult(M); + Data.populate(M, DRTM); return Data; } -PreservedAnalyses DXILResourcePrinterPass::run(Module &M, - ModuleAnalysisManager &AM) { - DXILResourceMap &DBM = AM.getResult(M); +PreservedAnalyses +DXILResourceBindingPrinterPass::run(Module &M, ModuleAnalysisManager &AM) { + DXILBindingMap &DBM = AM.getResult(M); + DXILResourceTypeMap &DRTM = AM.getResult(M); - DBM.print(OS, M.getDataLayout()); + DBM.print(OS, DRTM, M.getDataLayout()); return PreservedAnalyses::all(); } -DXILResourceWrapperPass::DXILResourceWrapperPass() : ModulePass(ID) { - initializeDXILResourceWrapperPassPass(*PassRegistry::getPassRegistry()); +void DXILResourceTypeWrapperPass::anchor() {} + +DXILResourceTypeWrapperPass::DXILResourceTypeWrapperPass() : ImmutablePass(ID) { + initializeDXILResourceTypeWrapperPassPass(*PassRegistry::getPassRegistry()); +} + +INITIALIZE_PASS(DXILResourceTypeWrapperPass, "dxil-resource-type", + "DXIL Resource Type Analysis", false, true) +char DXILResourceTypeWrapperPass::ID = 0; + +ModulePass *llvm::createDXILResourceTypeWrapperPassPass() { + return new DXILResourceTypeWrapperPass(); +} + +DXILResourceBindingWrapperPass::DXILResourceBindingWrapperPass() + : ModulePass(ID) { + initializeDXILResourceBindingWrapperPassPass( + *PassRegistry::getPassRegistry()); } -DXILResourceWrapperPass::~DXILResourceWrapperPass() = default; +DXILResourceBindingWrapperPass::~DXILResourceBindingWrapperPass() = default; -void DXILResourceWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { +void DXILResourceBindingWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredTransitive(); AU.setPreservesAll(); } -bool DXILResourceWrapperPass::runOnModule(Module &M) { - Map.reset(new DXILResourceMap()); +bool DXILResourceBindingWrapperPass::runOnModule(Module &M) { + Map.reset(new DXILBindingMap()); - Map->populate(M); + DRTM = &getAnalysis().getResourceTypeMap(); + Map->populate(M, *DRTM); return false; } -void DXILResourceWrapperPass::releaseMemory() { Map.reset(); } +void DXILResourceBindingWrapperPass::releaseMemory() { Map.reset(); } -void DXILResourceWrapperPass::print(raw_ostream &OS, const Module *M) const { +void DXILResourceBindingWrapperPass::print(raw_ostream &OS, + const Module *M) const { if (!Map) { OS << "No resource map has been built!\n"; return; } - Map->print(OS, M->getDataLayout()); + Map->print(OS, *DRTM, M->getDataLayout()); } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD -void DXILResourceWrapperPass::dump() const { print(dbgs(), nullptr); } +void DXILResourceBindingWrapperPass::dump() const { print(dbgs(), nullptr); } #endif -INITIALIZE_PASS(DXILResourceWrapperPass, "dxil-resource-binding", - "DXIL Resource analysis", false, true) -char DXILResourceWrapperPass::ID = 0; +INITIALIZE_PASS(DXILResourceBindingWrapperPass, "dxil-resource-binding", + "DXIL Resource Binding Analysis", false, true) +char DXILResourceBindingWrapperPass::ID = 0; -ModulePass *llvm::createDXILResourceWrapperPassPass() { - return new DXILResourceWrapperPass(); +ModulePass *llvm::createDXILResourceBindingWrapperPassPass() { + return new DXILResourceBindingWrapperPass(); } diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index b7fc7d2ac7fee..557be14ccff3b 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -22,7 +22,8 @@ MODULE_ANALYSIS("callgraph", CallGraphAnalysis()) MODULE_ANALYSIS("collector-metadata", CollectorMetadataAnalysis()) MODULE_ANALYSIS("ctx-prof-analysis", CtxProfAnalysis()) MODULE_ANALYSIS("dxil-metadata", DXILMetadataAnalysis()) -MODULE_ANALYSIS("dxil-resource", DXILResourceAnalysis()) +MODULE_ANALYSIS("dxil-resource-binding", DXILResourceBindingAnalysis()) +MODULE_ANALYSIS("dxil-resource-type", DXILResourceTypeAnalysis()) MODULE_ANALYSIS("inline-advisor", InlineAdvisorAnalysis()) MODULE_ANALYSIS("ir-similarity", IRSimilarityAnalysis()) MODULE_ANALYSIS("last-run-tracking", LastRunTrackingAnalysis()) @@ -127,7 +128,8 @@ MODULE_PASS("print-must-be-executed-contexts", MODULE_PASS("print-profile-summary", ProfileSummaryPrinterPass(errs())) MODULE_PASS("print-stack-safety", StackSafetyGlobalPrinterPass(errs())) MODULE_PASS("print", DXILMetadataAnalysisPrinterPass(errs())) -MODULE_PASS("print", DXILResourcePrinterPass(errs())) +MODULE_PASS("print", + DXILResourceBindingPrinterPass(errs())) MODULE_PASS("print", InlineAdvisorAnalysisPrinterPass(errs())) MODULE_PASS("print", ModuleDebugInfoPrinterPass(errs())) MODULE_PASS("print", PhysicalRegisterUsageInfoPrinterPass(errs())) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index aaf994b23cf3c..4c55a13b17f29 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -61,7 +61,8 @@ class DXContainerGlobals : public llvm::ModulePass { AU.setPreservesAll(); AU.addRequired(); AU.addRequired(); - AU.addRequired(); + AU.addRequired(); + AU.addRequired(); } }; @@ -144,19 +145,23 @@ void DXContainerGlobals::addSignature(Module &M, } void DXContainerGlobals::addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV) { - const DXILResourceMap &ResMap = - getAnalysis().getResourceMap(); - - for (const dxil::ResourceInfo &ResInfo : ResMap) { - const dxil::ResourceInfo::ResourceBinding &Binding = ResInfo.getBinding(); + const DXILBindingMap &DBM = + getAnalysis().getBindingMap(); + DXILResourceTypeMap &DRTM = + getAnalysis().getResourceTypeMap(); + + for (const dxil::ResourceBindingInfo &RBI : DBM) { + const dxil::ResourceBindingInfo::ResourceBinding &Binding = + RBI.getBinding(); dxbc::PSV::v2::ResourceBindInfo BindInfo; BindInfo.LowerBound = Binding.LowerBound; BindInfo.UpperBound = Binding.LowerBound + Binding.Size - 1; BindInfo.Space = Binding.Space; + dxil::ResourceTypeInfo TypeInfo = DRTM[RBI.getHandleTy()]; dxbc::PSV::ResourceType ResType = dxbc::PSV::ResourceType::Invalid; - bool IsUAV = ResInfo.getResourceClass() == dxil::ResourceClass::UAV; - switch (ResInfo.getResourceKind()) { + bool IsUAV = TypeInfo.getResourceClass() == dxil::ResourceClass::UAV; + switch (TypeInfo.getResourceKind()) { case dxil::ResourceKind::Sampler: ResType = dxbc::PSV::ResourceType::Sampler; break; @@ -166,7 +171,7 @@ void DXContainerGlobals::addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV) { case dxil::ResourceKind::StructuredBuffer: ResType = IsUAV ? dxbc::PSV::ResourceType::UAVStructured : dxbc::PSV::ResourceType::SRVStructured; - if (IsUAV && ResInfo.getUAV().HasCounter) + if (IsUAV && TypeInfo.getUAV().HasCounter) ResType = dxbc::PSV::ResourceType::UAVStructuredWithCounter; break; case dxil::ResourceKind::RTAccelerationStructure: @@ -184,7 +189,7 @@ void DXContainerGlobals::addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV) { BindInfo.Type = ResType; BindInfo.Kind = - static_cast(ResInfo.getResourceKind()); + static_cast(TypeInfo.getResourceKind()); // TODO: Add support for dxbc::PSV::ResourceFlag::UsedByAtomic64, tracking // with https://github.com/llvm/llvm-project/issues/104392 BindInfo.Flags.Flags = 0u; @@ -240,7 +245,8 @@ INITIALIZE_PASS_BEGIN(DXContainerGlobals, "dxil-globals", "DXContainer Global Emitter", false, true) INITIALIZE_PASS_DEPENDENCY(ShaderFlagsAnalysisWrapper) INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass) -INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass) +INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass) INITIALIZE_PASS_END(DXContainerGlobals, "dxil-globals", "DXContainer Global Emitter", false, true) diff --git a/llvm/lib/Target/DirectX/DXILDataScalarization.cpp b/llvm/lib/Target/DirectX/DXILDataScalarization.cpp index 0e6cf59e25750..1783e4a546313 100644 --- a/llvm/lib/Target/DirectX/DXILDataScalarization.cpp +++ b/llvm/lib/Target/DirectX/DXILDataScalarization.cpp @@ -10,7 +10,6 @@ #include "DirectX.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Analysis/DXILResource.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstVisitor.h" @@ -33,7 +32,6 @@ class DXILDataScalarizationLegacy : public ModulePass { bool runOnModule(Module &M) override; DXILDataScalarizationLegacy() : ModulePass(ID) {} - void getAnalysisUsage(AnalysisUsage &AU) const override; static char ID; // Pass identification. }; @@ -276,7 +274,6 @@ PreservedAnalyses DXILDataScalarization::run(Module &M, if (!MadeChanges) return PreservedAnalyses::all(); PreservedAnalyses PA; - PA.preserve(); return PA; } @@ -284,10 +281,6 @@ bool DXILDataScalarizationLegacy::runOnModule(Module &M) { return findAndReplaceVectors(M); } -void DXILDataScalarizationLegacy::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addPreserved(); -} - char DXILDataScalarizationLegacy::ID = 0; INITIALIZE_PASS_BEGIN(DXILDataScalarizationLegacy, DEBUG_TYPE, diff --git a/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp b/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp index 79ebbe0925e5c..91ac758150fb4 100644 --- a/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp +++ b/llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp @@ -8,7 +8,6 @@ #include "DXILFinalizeLinkage.h" #include "DirectX.h" -#include "llvm/Analysis/DXILResource.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Metadata.h" @@ -51,10 +50,6 @@ bool DXILFinalizeLinkageLegacy::runOnModule(Module &M) { return finalizeLinkage(M); } -void DXILFinalizeLinkageLegacy::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addPreserved(); -} - char DXILFinalizeLinkageLegacy::ID = 0; INITIALIZE_PASS_BEGIN(DXILFinalizeLinkageLegacy, DEBUG_TYPE, diff --git a/llvm/lib/Target/DirectX/DXILFinalizeLinkage.h b/llvm/lib/Target/DirectX/DXILFinalizeLinkage.h index 62d3a8a27cfce..aab1bc3f7a28e 100644 --- a/llvm/lib/Target/DirectX/DXILFinalizeLinkage.h +++ b/llvm/lib/Target/DirectX/DXILFinalizeLinkage.h @@ -32,7 +32,6 @@ class DXILFinalizeLinkageLegacy : public ModulePass { DXILFinalizeLinkageLegacy() : ModulePass(ID) {} bool runOnModule(Module &M) override; - void getAnalysisUsage(AnalysisUsage &AU) const override; static char ID; // Pass identification. }; } // namespace llvm diff --git a/llvm/lib/Target/DirectX/DXILFlattenArrays.cpp b/llvm/lib/Target/DirectX/DXILFlattenArrays.cpp index e4a3bc76eeacd..6077af997212e 100644 --- a/llvm/lib/Target/DirectX/DXILFlattenArrays.cpp +++ b/llvm/lib/Target/DirectX/DXILFlattenArrays.cpp @@ -14,7 +14,6 @@ #include "DirectX.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Analysis/DXILResource.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" @@ -38,7 +37,6 @@ class DXILFlattenArraysLegacy : public ModulePass { bool runOnModule(Module &M) override; DXILFlattenArraysLegacy() : ModulePass(ID) {} - void getAnalysisUsage(AnalysisUsage &AU) const override; static char ID; // Pass identification. }; @@ -419,7 +417,6 @@ PreservedAnalyses DXILFlattenArrays::run(Module &M, ModuleAnalysisManager &) { if (!MadeChanges) return PreservedAnalyses::all(); PreservedAnalyses PA; - PA.preserve(); return PA; } @@ -427,10 +424,6 @@ bool DXILFlattenArraysLegacy::runOnModule(Module &M) { return flattenArrays(M); } -void DXILFlattenArraysLegacy::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addPreserved(); -} - char DXILFlattenArraysLegacy::ID = 0; INITIALIZE_PASS_BEGIN(DXILFlattenArraysLegacy, DEBUG_TYPE, diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp index d2bfca1fada55..3c6ea4470fbdc 100644 --- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp @@ -14,7 +14,6 @@ #include "DirectX.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Analysis/DXILResource.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstrTypes.h" @@ -39,7 +38,6 @@ class DXILIntrinsicExpansionLegacy : public ModulePass { bool runOnModule(Module &M) override; DXILIntrinsicExpansionLegacy() : ModulePass(ID) {} - void getAnalysisUsage(AnalysisUsage &AU) const override; static char ID; // Pass identification. }; @@ -617,10 +615,6 @@ bool DXILIntrinsicExpansionLegacy::runOnModule(Module &M) { return expansionIntrinsics(M); } -void DXILIntrinsicExpansionLegacy::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addPreserved(); -} - char DXILIntrinsicExpansionLegacy::ID = 0; INITIALIZE_PASS_BEGIN(DXILIntrinsicExpansionLegacy, DEBUG_TYPE, diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 78efdcf194b6c..c66b24442d4bd 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -77,11 +77,13 @@ namespace { class OpLowerer { Module &M; DXILOpBuilder OpBuilder; - DXILResourceMap &DRM; + DXILBindingMap &DBM; + DXILResourceTypeMap &DRTM; SmallVector CleanupCasts; public: - OpLowerer(Module &M, DXILResourceMap &DRM) : M(M), OpBuilder(M), DRM(DRM) {} + OpLowerer(Module &M, DXILBindingMap &DBM, DXILResourceTypeMap &DRTM) + : M(M), OpBuilder(M), DBM(DBM), DRTM(DRTM) {} /// Replace every call to \c F using \c ReplaceCall, and then erase \c F. If /// there is an error replacing a call, we emit a diagnostic and return true. @@ -257,10 +259,12 @@ class OpLowerer { return replaceFunction(F, [&](CallInst *CI) -> Error { IRB.SetInsertPoint(CI); - auto *It = DRM.find(CI); - assert(It != DRM.end() && "Resource not in map?"); - dxil::ResourceInfo &RI = *It; + auto *It = DBM.find(CI); + assert(It != DBM.end() && "Resource not in map?"); + dxil::ResourceBindingInfo &RI = *It; + const auto &Binding = RI.getBinding(); + dxil::ResourceClass RC = DRTM[RI.getHandleTy()].getResourceClass(); Value *IndexOp = CI->getArgOperand(3); if (Binding.LowerBound != 0) @@ -268,7 +272,7 @@ class OpLowerer { ConstantInt::get(Int32Ty, Binding.LowerBound)); std::array Args{ - ConstantInt::get(Int8Ty, llvm::to_underlying(RI.getResourceClass())), + ConstantInt::get(Int8Ty, llvm::to_underlying(RC)), ConstantInt::get(Int32Ty, Binding.RecordID), IndexOp, CI->getArgOperand(4)}; Expected OpCall = @@ -293,18 +297,20 @@ class OpLowerer { return replaceFunction(F, [&](CallInst *CI) -> Error { IRB.SetInsertPoint(CI); - auto *It = DRM.find(CI); - assert(It != DRM.end() && "Resource not in map?"); - dxil::ResourceInfo &RI = *It; + auto *It = DBM.find(CI); + assert(It != DBM.end() && "Resource not in map?"); + dxil::ResourceBindingInfo &RI = *It; const auto &Binding = RI.getBinding(); + dxil::ResourceClass RC = DRTM[RI.getHandleTy()].getResourceClass(); Value *IndexOp = CI->getArgOperand(3); if (Binding.LowerBound != 0) IndexOp = IRB.CreateAdd(IndexOp, ConstantInt::get(Int32Ty, Binding.LowerBound)); - std::pair Props = RI.getAnnotateProps(*F.getParent()); + std::pair Props = + RI.getAnnotateProps(*F.getParent(), DRTM); // For `CreateHandleFromBinding` we need the upper bound rather than the // size, so we need to be careful about the difference for "unbounded". @@ -312,8 +318,8 @@ class OpLowerer { uint32_t UpperBound = Binding.Size == Unbounded ? Unbounded : Binding.LowerBound + Binding.Size - 1; - Constant *ResBind = OpBuilder.getResBind( - Binding.LowerBound, UpperBound, Binding.Space, RI.getResourceClass()); + Constant *ResBind = OpBuilder.getResBind(Binding.LowerBound, UpperBound, + Binding.Space, RC); std::array BindArgs{ResBind, IndexOp, CI->getArgOperand(4)}; Expected OpBind = OpBuilder.tryCreateOp( OpCode::CreateHandleFromBinding, BindArgs, CI->getName()); @@ -340,7 +346,7 @@ class OpLowerer { } /// Lower `dx.handle.fromBinding` intrinsics depending on the shader model and - /// taking into account binding information from DXILResourceAnalysis. + /// taking into account binding information from DXILResourceBindingAnalysis. bool lowerHandleFromBinding(Function &F) { Triple TT(Triple(M.getTargetTriple())); if (TT.getDXILVersion() < VersionTuple(1, 6)) @@ -737,13 +743,14 @@ class OpLowerer { } // namespace PreservedAnalyses DXILOpLowering::run(Module &M, ModuleAnalysisManager &MAM) { - DXILResourceMap &DRM = MAM.getResult(M); + DXILBindingMap &DBM = MAM.getResult(M); + DXILResourceTypeMap &DRTM = MAM.getResult(M); - bool MadeChanges = OpLowerer(M, DRM).lowerIntrinsics(); + bool MadeChanges = OpLowerer(M, DBM, DRTM).lowerIntrinsics(); if (!MadeChanges) return PreservedAnalyses::all(); PreservedAnalyses PA; - PA.preserve(); + PA.preserve(); return PA; } @@ -751,18 +758,21 @@ namespace { class DXILOpLoweringLegacy : public ModulePass { public: bool runOnModule(Module &M) override { - DXILResourceMap &DRM = - getAnalysis().getResourceMap(); + DXILBindingMap &DBM = + getAnalysis().getBindingMap(); + DXILResourceTypeMap &DRTM = + getAnalysis().getResourceTypeMap(); - return OpLowerer(M, DRM).lowerIntrinsics(); + return OpLowerer(M, DBM, DRTM).lowerIntrinsics(); } StringRef getPassName() const override { return "DXIL Op Lowering"; } DXILOpLoweringLegacy() : ModulePass(ID) {} static char ID; // Pass identification. void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { - AU.addRequired(); - AU.addPreserved(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); } }; char DXILOpLoweringLegacy::ID = 0; @@ -770,7 +780,8 @@ char DXILOpLoweringLegacy::ID = 0; INITIALIZE_PASS_BEGIN(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering", false, false) -INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass) +INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass) INITIALIZE_PASS_END(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering", false, false) diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp index 6092cfb3948f0..375e6ce712924 100644 --- a/llvm/lib/Target/DirectX/DXILPrepare.cpp +++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp @@ -251,7 +251,7 @@ class DXILPrepareModule : public ModulePass { AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); - AU.addPreserved(); + AU.addPreserved(); } static char ID; // Pass identification. }; diff --git a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp index 4aa25b3996e3c..ff690f2abe490 100644 --- a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp +++ b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp @@ -48,7 +48,7 @@ static StringRef getRCPrefix(dxil::ResourceClass RC) { llvm_unreachable("covered switch"); } -static StringRef getFormatName(const dxil::ResourceInfo &RI) { +static StringRef getFormatName(const dxil::ResourceTypeInfo &RI) { if (RI.isTyped()) { switch (RI.getTyped().ElementTy) { case dxil::ElementType::I1: @@ -139,9 +139,9 @@ static StringRef getTextureDimName(dxil::ResourceKind RK) { namespace { struct FormatResourceDimension - : public llvm::FormatAdapter { - explicit FormatResourceDimension(const dxil::ResourceInfo &RI) - : llvm::FormatAdapter(RI) {} + : public llvm::FormatAdapter { + explicit FormatResourceDimension(const dxil::ResourceTypeInfo &RI) + : llvm::FormatAdapter(RI) {} void format(llvm::raw_ostream &OS, StringRef Style) override { dxil::ResourceKind RK = Item.getResourceKind(); @@ -172,33 +172,40 @@ struct FormatResourceDimension }; struct FormatBindingID - : public llvm::FormatAdapter { - explicit FormatBindingID(const dxil::ResourceInfo &RI) - : llvm::FormatAdapter(RI) {} + : public llvm::FormatAdapter { + dxil::ResourceClass RC; + + explicit FormatBindingID(const dxil::ResourceBindingInfo &RBI, + const dxil::ResourceTypeInfo &RTI) + : llvm::FormatAdapter(RBI), + RC(RTI.getResourceClass()) {} void format(llvm::raw_ostream &OS, StringRef Style) override { - OS << getRCPrefix(Item.getResourceClass()).upper() - << Item.getBinding().RecordID; + OS << getRCPrefix(RC).upper() << Item.getBinding().RecordID; } }; struct FormatBindingLocation - : public llvm::FormatAdapter { - explicit FormatBindingLocation(const dxil::ResourceInfo &RI) - : llvm::FormatAdapter(RI) {} + : public llvm::FormatAdapter { + dxil::ResourceClass RC; + + explicit FormatBindingLocation(const dxil::ResourceBindingInfo &RBI, + const dxil::ResourceTypeInfo &RTI) + : llvm::FormatAdapter(RBI), + RC(RTI.getResourceClass()) {} void format(llvm::raw_ostream &OS, StringRef Style) override { const auto &Binding = Item.getBinding(); - OS << getRCPrefix(Item.getResourceClass()) << Binding.LowerBound; + OS << getRCPrefix(RC) << Binding.LowerBound; if (Binding.Space) OS << ",space" << Binding.Space; } }; struct FormatBindingSize - : public llvm::FormatAdapter { - explicit FormatBindingSize(const dxil::ResourceInfo &RI) - : llvm::FormatAdapter(RI) {} + : public llvm::FormatAdapter { + explicit FormatBindingSize(const dxil::ResourceBindingInfo &RI) + : llvm::FormatAdapter(RI) {} void format(llvm::raw_ostream &OS, StringRef Style) override { uint32_t Size = Item.getBinding().Size; @@ -211,7 +218,8 @@ struct FormatBindingSize } // namespace -static void prettyPrintResources(raw_ostream &OS, const DXILResourceMap &DRM, +static void prettyPrintResources(raw_ostream &OS, const DXILBindingMap &DBM, + DXILResourceTypeMap &DRTM, const dxil::Resources &MDResources) { // Column widths are arbitrary but match the widths DXC uses. OS << ";\n; Resource Bindings:\n;\n"; @@ -222,20 +230,22 @@ static void prettyPrintResources(raw_ostream &OS, const DXILResourceMap &DRM, "", "", "", "", ""); // TODO: Do we want to sort these by binding or something like that? - for (const dxil::ResourceInfo &RI : DRM) { - dxil::ResourceClass RC = RI.getResourceClass(); + for (const dxil::ResourceBindingInfo &RBI : DBM) { + const dxil::ResourceTypeInfo &RTI = DRTM[RBI.getHandleTy()]; + + dxil::ResourceClass RC = RTI.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 Name(RBI.getName()); StringRef Type(getRCName(RC)); - StringRef Format(getFormatName(RI)); - FormatResourceDimension Dim(RI); - FormatBindingID ID(RI); - FormatBindingLocation Bind(RI); - FormatBindingSize Count(RI); + StringRef Format(getFormatName(RTI)); + FormatResourceDimension Dim(RTI); + FormatBindingID ID(RBI, RTI); + FormatBindingLocation Bind(RBI, RTI); + FormatBindingSize Count(RBI); OS << formatv("; {0,-30} {1,10} {2,7} {3,11} {4,7} {5,14} {6,9}\n", Name, Type, Format, Dim, ID, Bind, Count); } @@ -250,9 +260,10 @@ static void prettyPrintResources(raw_ostream &OS, const DXILResourceMap &DRM, PreservedAnalyses DXILPrettyPrinterPass::run(Module &M, ModuleAnalysisManager &MAM) { - const DXILResourceMap &DRM = MAM.getResult(M); + const DXILBindingMap &DBM = MAM.getResult(M); + DXILResourceTypeMap &DRTM = MAM.getResult(M); const dxil::Resources &MDResources = MAM.getResult(M); - prettyPrintResources(OS, DRM, MDResources); + prettyPrintResources(OS, DBM, DRTM, MDResources); return PreservedAnalyses::all(); } @@ -277,7 +288,8 @@ class DXILPrettyPrinterLegacy : public llvm::ModulePass { bool runOnModule(Module &M) override; void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); - AU.addRequired(); + AU.addRequired(); + AU.addRequired(); AU.addRequired(); } }; @@ -286,16 +298,19 @@ 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(DXILResourceTypeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass) 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().getResourceMap(); + const DXILBindingMap &DBM = + getAnalysis().getBindingMap(); + DXILResourceTypeMap &DRTM = + getAnalysis().getResourceTypeMap(); dxil::Resources &Res = getAnalysis().getDXILResource(); - prettyPrintResources(OS, DRM, Res); + prettyPrintResources(OS, DBM, DRTM, Res); return false; } diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp index baefadede6e3a..9763fe6a8a345 100644 --- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp @@ -72,25 +72,26 @@ enum class EntryPropsTag { } // namespace -static NamedMDNode *emitResourceMetadata(Module &M, const DXILResourceMap &DRM, +static NamedMDNode *emitResourceMetadata(Module &M, DXILBindingMap &DBM, + DXILResourceTypeMap &DRTM, const dxil::Resources &MDResources) { LLVMContext &Context = M.getContext(); SmallVector SRVs, UAVs, CBufs, Smps; - for (const ResourceInfo &RI : DRM.srvs()) - SRVs.push_back(RI.getAsMetadata(M)); - for (const ResourceInfo &RI : DRM.uavs()) - UAVs.push_back(RI.getAsMetadata(M)); - for (const ResourceInfo &RI : DRM.cbuffers()) - CBufs.push_back(RI.getAsMetadata(M)); - for (const ResourceInfo &RI : DRM.samplers()) - Smps.push_back(RI.getAsMetadata(M)); + for (const ResourceBindingInfo &RI : DBM.srvs()) + SRVs.push_back(RI.getAsMetadata(M, DRTM)); + for (const ResourceBindingInfo &RI : DBM.uavs()) + UAVs.push_back(RI.getAsMetadata(M, DRTM)); + for (const ResourceBindingInfo &RI : DBM.cbuffers()) + CBufs.push_back(RI.getAsMetadata(M, DRTM)); + for (const ResourceBindingInfo &RI : DBM.samplers()) + Smps.push_back(RI.getAsMetadata(M, DRTM)); Metadata *SRVMD = SRVs.empty() ? nullptr : MDNode::get(Context, SRVs); Metadata *UAVMD = UAVs.empty() ? nullptr : MDNode::get(Context, UAVs); Metadata *CBufMD = CBufs.empty() ? nullptr : MDNode::get(Context, CBufs); Metadata *SmpMD = Smps.empty() ? nullptr : MDNode::get(Context, Smps); - bool HasResources = !DRM.empty(); + bool HasResources = !DBM.empty(); if (MDResources.hasUAVs()) { assert(!UAVMD && "Old and new UAV representations can't coexist"); @@ -295,7 +296,8 @@ static MDTuple *emitTopLevelLibraryNode(Module &M, MDNode *RMD, return constructEntryMetadata(nullptr, nullptr, RMD, Properties, Ctx); } -static void translateMetadata(Module &M, const DXILResourceMap &DRM, +static void translateMetadata(Module &M, DXILBindingMap &DBM, + DXILResourceTypeMap &DRTM, const Resources &MDResources, const ModuleShaderFlags &ShaderFlags, const ModuleMetadataInfo &MMDI) { @@ -306,7 +308,8 @@ static void translateMetadata(Module &M, const DXILResourceMap &DRM, emitValidatorVersionMD(M, MMDI); emitShaderModelVersionMD(M, MMDI); emitDXILVersionTupleMD(M, MMDI); - NamedMDNode *NamedResourceMD = emitResourceMetadata(M, DRM, MDResources); + NamedMDNode *NamedResourceMD = + emitResourceMetadata(M, DBM, DRTM, MDResources); auto *ResourceMD = (NamedResourceMD != nullptr) ? NamedResourceMD->getOperand(0) : nullptr; // FIXME: Add support to construct Signatures @@ -358,12 +361,13 @@ static void translateMetadata(Module &M, const DXILResourceMap &DRM, PreservedAnalyses DXILTranslateMetadata::run(Module &M, ModuleAnalysisManager &MAM) { - const DXILResourceMap &DRM = MAM.getResult(M); + DXILBindingMap &DBM = MAM.getResult(M); + DXILResourceTypeMap &DRTM = MAM.getResult(M); const dxil::Resources &MDResources = MAM.getResult(M); const ModuleShaderFlags &ShaderFlags = MAM.getResult(M); const dxil::ModuleMetadataInfo MMDI = MAM.getResult(M); - translateMetadata(M, DRM, MDResources, ShaderFlags, MMDI); + translateMetadata(M, DBM, DRTM, MDResources, ShaderFlags, MMDI); return PreservedAnalyses::all(); } @@ -377,18 +381,21 @@ class DXILTranslateMetadataLegacy : public ModulePass { StringRef getPassName() const override { return "DXIL Translate Metadata"; } void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired(); + AU.addRequired(); + AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addRequired(); - AU.addPreserved(); + AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); } bool runOnModule(Module &M) override { - const DXILResourceMap &DRM = - getAnalysis().getResourceMap(); + DXILBindingMap &DBM = + getAnalysis().getBindingMap(); + DXILResourceTypeMap &DRTM = + getAnalysis().getResourceTypeMap(); const dxil::Resources &MDResources = getAnalysis().getDXILResource(); const ModuleShaderFlags &ShaderFlags = @@ -396,7 +403,7 @@ class DXILTranslateMetadataLegacy : public ModulePass { dxil::ModuleMetadataInfo MMDI = getAnalysis().getModuleMetadata(); - translateMetadata(M, DRM, MDResources, ShaderFlags, MMDI); + translateMetadata(M, DBM, DRTM, MDResources, ShaderFlags, MMDI); return true; } }; @@ -411,7 +418,7 @@ ModulePass *llvm::createDXILTranslateMetadataLegacyPass() { INITIALIZE_PASS_BEGIN(DXILTranslateMetadataLegacy, "dxil-translate-metadata", "DXIL Translate Metadata", false, false) -INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass) +INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass) INITIALIZE_PASS_DEPENDENCY(DXILResourceMDWrapper) INITIALIZE_PASS_DEPENDENCY(ShaderFlagsAnalysisWrapper) INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass) diff --git a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll index 5c8b6998c76aa..313c8376483b9 100644 --- a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll +++ b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll @@ -1,10 +1,10 @@ -; RUN: opt -S -disable-output -passes="print" < %s 2>&1 | FileCheck %s +; RUN: opt -S -disable-output -passes="print" < %s 2>&1 | FileCheck %s @G = external constant <4 x float>, align 4 define void @test_typedbuffer() { ; ByteAddressBuffer Buf : register(t8, space1) - %srv0 = call target("dx.RawBuffer", i8, 0, 0) + %srv0 = call target("dx.RawBuffer", void, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t( i32 1, i32 8, i32 1, i32 0, i1 false) ; CHECK: Binding [[SRV0:[0-9]+]]: diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll index 40fa30778a153..147898efc716f 100644 --- a/llvm/test/CodeGen/DirectX/llc-pipeline.ll +++ b/llvm/test/CodeGen/DirectX/llc-pipeline.ll @@ -6,6 +6,7 @@ ; CHECK-LABEL: Pass Arguments: ; CHECK-NEXT: Target Library Information ; CHECK-NEXT: Target Transform Information +; CHECK-NEXT: DXIL Resource Type Analysis ; CHECK-NEXT: ModulePass Manager ; CHECK-NEXT: DXIL Finalize Linkage ; CHECK-NEXT: DXIL Intrinsic Expansion @@ -14,7 +15,7 @@ ; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Dominator Tree Construction ; CHECK-NEXT: Scalarize vector operations -; CHECK-NEXT: DXIL Resource analysis +; CHECK-NEXT: DXIL Resource Binding Analysis ; CHECK-NEXT: DXIL Op Lowering ; CHECK-NEXT: DXIL resource Information ; CHECK-NEXT: DXIL Shader Flag Analysis @@ -23,4 +24,3 @@ ; CHECK-NEXT: DXIL Prepare Module ; CHECK-NEXT: DXIL Metadata Pretty Printer ; CHECK-NEXT: Print Module IR - diff --git a/llvm/unittests/Analysis/DXILResourceTest.cpp b/llvm/unittests/Analysis/DXILResourceTest.cpp index 776c914b89a04..1a824e355bb31 100644 --- a/llvm/unittests/Analysis/DXILResourceTest.cpp +++ b/llvm/unittests/Analysis/DXILResourceTest.cpp @@ -123,36 +123,36 @@ TEST(DXILResource, AnnotationsAndMetadata) { Value *DummyGV = UndefValue::get(PointerType::getUnqual(Context)); // ByteAddressBuffer Buffer; - auto *HandleTy = llvm::TargetExtType::get(Context, "dx.RawBuffer", Int8Ty, - {/*IsWriteable=*/0, /*IsROV=*/0}); - ResourceInfo RI( - /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::SRV); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::RawBuffer); - - std::pair Props = RI.getAnnotateProps(M); + ResourceTypeInfo RTI(llvm::TargetExtType::get( + Context, "dx.RawBuffer", Int8Ty, {/*IsWriteable=*/0, /*IsROV=*/0})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::SRV); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::RawBuffer); + + ResourceBindingInfo RBI( + /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, + RTI.getHandleTy()); + std::pair Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x0000000bU); EXPECT_EQ(Props.second, 0U); - MDTuple *MD = RI.getAsMetadata(M); + MDTuple *MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 11, 0, nullptr)); // RWByteAddressBuffer BufferOut : register(u3, space2); - HandleTy = llvm::TargetExtType::get(Context, "dx.RawBuffer", Int8Ty, - {/*IsWriteable=*/1, /*IsROV=*/0}); - RI = ResourceInfo( - /*RecordID=*/1, /*Space=*/2, /*LowerBound=*/3, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::UAV); - EXPECT_EQ(RI.getUAV().GloballyCoherent, false); - EXPECT_EQ(RI.getUAV().HasCounter, false); - EXPECT_EQ(RI.getUAV().IsROV, false); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::RawBuffer); - - Props = RI.getAnnotateProps(M); + RTI = ResourceTypeInfo(llvm::TargetExtType::get( + Context, "dx.RawBuffer", Int8Ty, {/*IsWriteable=*/1, /*IsROV=*/0})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV); + EXPECT_EQ(RTI.getUAV().GloballyCoherent, false); + EXPECT_EQ(RTI.getUAV().HasCounter, false); + EXPECT_EQ(RTI.getUAV().IsROV, false); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::RawBuffer); + + RBI = ResourceBindingInfo( + /*RecordID=*/1, /*Space=*/2, /*LowerBound=*/3, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x0000100bU); EXPECT_EQ(Props.second, 0U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(1, DummyGV, "", 2, 3, 1, 11, false, false, false, nullptr)); @@ -160,271 +160,272 @@ TEST(DXILResource, AnnotationsAndMetadata) { // StructuredBuffer Buffer0 : register(t0); StructType *BufType0 = StructType::create(Context, {Int32Ty, FloatTy, DoubleTy}, "BufType0"); - HandleTy = llvm::TargetExtType::get(Context, "dx.RawBuffer", BufType0, - {/*IsWriteable=*/0, /*IsROV=*/0}); - RI = ResourceInfo( - /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::SRV); - ASSERT_EQ(RI.isStruct(), true); - EXPECT_EQ(RI.getStruct(DL).Stride, 16u); - EXPECT_EQ(RI.getStruct(DL).AlignLog2, Log2(Align(8))); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::StructuredBuffer); - - Props = RI.getAnnotateProps(M); + RTI = ResourceTypeInfo(llvm::TargetExtType::get( + Context, "dx.RawBuffer", BufType0, {/*IsWriteable=*/0, /*IsROV=*/0})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::SRV); + ASSERT_EQ(RTI.isStruct(), true); + EXPECT_EQ(RTI.getStruct(DL).Stride, 16u); + EXPECT_EQ(RTI.getStruct(DL).AlignLog2, Log2(Align(8))); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::StructuredBuffer); + + RBI = ResourceBindingInfo( + /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x0000030cU); EXPECT_EQ(Props.second, 0x00000010U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 12, 0, TestMD.get(1, 16))); // StructuredBuffer Buffer1 : register(t1); - HandleTy = llvm::TargetExtType::get(Context, "dx.RawBuffer", Floatx3Ty, - {/*IsWriteable=*/0, /*IsROV=*/0}); - RI = ResourceInfo( - /*RecordID=*/1, /*Space=*/0, /*LowerBound=*/1, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::SRV); - ASSERT_EQ(RI.isStruct(), true); - EXPECT_EQ(RI.getStruct(DL).Stride, 12u); - EXPECT_EQ(RI.getStruct(DL).AlignLog2, 0u); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::StructuredBuffer); - - Props = RI.getAnnotateProps(M); + RTI = ResourceTypeInfo(llvm::TargetExtType::get( + Context, "dx.RawBuffer", Floatx3Ty, {/*IsWriteable=*/0, /*IsROV=*/0})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::SRV); + ASSERT_EQ(RTI.isStruct(), true); + EXPECT_EQ(RTI.getStruct(DL).Stride, 12u); + EXPECT_EQ(RTI.getStruct(DL).AlignLog2, 0u); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::StructuredBuffer); + + RBI = ResourceBindingInfo( + /*RecordID=*/1, /*Space=*/0, /*LowerBound=*/1, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x0000000cU); EXPECT_EQ(Props.second, 0x0000000cU); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(1, DummyGV, "", 0, 1, 1, 12, 0, TestMD.get(1, 12))); // Texture2D ColorMapTexture : register(t2); - HandleTy = + RTI = ResourceTypeInfo( llvm::TargetExtType::get(Context, "dx.Texture", Floatx4Ty, {/*IsWriteable=*/0, /*IsROV=*/0, /*IsSigned=*/0, - llvm::to_underlying(ResourceKind::Texture2D)}); - RI = ResourceInfo( - /*RecordID=*/2, /*Space=*/0, /*LowerBound=*/2, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::SRV); - ASSERT_EQ(RI.isTyped(), true); - EXPECT_EQ(RI.getTyped().ElementTy, ElementType::F32); - EXPECT_EQ(RI.getTyped().ElementCount, 4u); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::Texture2D); - - Props = RI.getAnnotateProps(M); + llvm::to_underlying(ResourceKind::Texture2D)})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::SRV); + ASSERT_EQ(RTI.isTyped(), true); + EXPECT_EQ(RTI.getTyped().ElementTy, ElementType::F32); + EXPECT_EQ(RTI.getTyped().ElementCount, 4u); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Texture2D); + + RBI = ResourceBindingInfo( + /*RecordID=*/2, /*Space=*/0, /*LowerBound=*/2, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x00000002U); EXPECT_EQ(Props.second, 0x00000409U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(2, DummyGV, "", 0, 2, 1, 2, 0, TestMD.get(0, 9))); // Texture2DMS DepthBuffer : register(t0); - HandleTy = llvm::TargetExtType::get( + RTI = ResourceTypeInfo(llvm::TargetExtType::get( Context, "dx.MSTexture", FloatTy, {/*IsWriteable=*/0, /*SampleCount=*/8, - /*IsSigned=*/0, llvm::to_underlying(ResourceKind::Texture2DMS)}); - RI = ResourceInfo( - /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::SRV); - ASSERT_EQ(RI.isTyped(), true); - EXPECT_EQ(RI.getTyped().ElementTy, ElementType::F32); - EXPECT_EQ(RI.getTyped().ElementCount, 1u); - ASSERT_EQ(RI.isMultiSample(), true); - EXPECT_EQ(RI.getMultiSampleCount(), 8u); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::Texture2DMS); - - Props = RI.getAnnotateProps(M); + /*IsSigned=*/0, llvm::to_underlying(ResourceKind::Texture2DMS)})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::SRV); + ASSERT_EQ(RTI.isTyped(), true); + EXPECT_EQ(RTI.getTyped().ElementTy, ElementType::F32); + EXPECT_EQ(RTI.getTyped().ElementCount, 1u); + ASSERT_EQ(RTI.isMultiSample(), true); + EXPECT_EQ(RTI.getMultiSampleCount(), 8u); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Texture2DMS); + + RBI = ResourceBindingInfo( + /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x00000003U); EXPECT_EQ(Props.second, 0x00080109U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 3, 8, TestMD.get(0, 9))); // FeedbackTexture2D feedbackMinMip; - HandleTy = llvm::TargetExtType::get( + RTI = ResourceTypeInfo(llvm::TargetExtType::get( Context, "dx.FeedbackTexture", {}, {llvm::to_underlying(SamplerFeedbackType::MinMip), - llvm::to_underlying(ResourceKind::FeedbackTexture2D)}); - RI = ResourceInfo( - /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::UAV); - ASSERT_EQ(RI.isFeedback(), true); - EXPECT_EQ(RI.getFeedbackType(), SamplerFeedbackType::MinMip); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::FeedbackTexture2D); - - Props = RI.getAnnotateProps(M); + llvm::to_underlying(ResourceKind::FeedbackTexture2D)})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV); + ASSERT_EQ(RTI.isFeedback(), true); + EXPECT_EQ(RTI.getFeedbackType(), SamplerFeedbackType::MinMip); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::FeedbackTexture2D); + + RBI = ResourceBindingInfo( + /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x00001011U); EXPECT_EQ(Props.second, 0U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 17, false, false, false, TestMD.get(2, 0))); // FeedbackTexture2DArray feedbackMipRegion; - HandleTy = llvm::TargetExtType::get( + RTI = ResourceTypeInfo(llvm::TargetExtType::get( Context, "dx.FeedbackTexture", {}, {llvm::to_underlying(SamplerFeedbackType::MipRegionUsed), - llvm::to_underlying(ResourceKind::FeedbackTexture2DArray)}); - RI = ResourceInfo( - /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::UAV); - ASSERT_EQ(RI.isFeedback(), true); - EXPECT_EQ(RI.getFeedbackType(), SamplerFeedbackType::MipRegionUsed); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::FeedbackTexture2DArray); - - Props = RI.getAnnotateProps(M); + llvm::to_underlying(ResourceKind::FeedbackTexture2DArray)})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV); + ASSERT_EQ(RTI.isFeedback(), true); + EXPECT_EQ(RTI.getFeedbackType(), SamplerFeedbackType::MipRegionUsed); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::FeedbackTexture2DArray); + + RBI = ResourceBindingInfo( + /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x00001012U); EXPECT_EQ(Props.second, 0x00000001U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 18, false, false, false, TestMD.get(2, 1))); // globallycoherent RWTexture2D OutputTexture : register(u0, space2); - HandleTy = + RTI = ResourceTypeInfo( llvm::TargetExtType::get(Context, "dx.Texture", Int32x2Ty, {/*IsWriteable=*/1, /*IsROV=*/0, /*IsSigned=*/1, - llvm::to_underlying(ResourceKind::Texture2D)}); - - RI = ResourceInfo( - /*RecordID=*/0, /*Space=*/2, /*LowerBound=*/0, /*Size=*/1, HandleTy, + llvm::to_underlying(ResourceKind::Texture2D)}), /*GloballyCoherent=*/true, /*HasCounter=*/false); - EXPECT_EQ(RI.getResourceClass(), ResourceClass::UAV); - EXPECT_EQ(RI.getUAV().GloballyCoherent, true); - EXPECT_EQ(RI.getUAV().HasCounter, false); - EXPECT_EQ(RI.getUAV().IsROV, false); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::Texture2D); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV); + EXPECT_EQ(RTI.getUAV().GloballyCoherent, true); + EXPECT_EQ(RTI.getUAV().HasCounter, false); + EXPECT_EQ(RTI.getUAV().IsROV, false); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Texture2D); - Props = RI.getAnnotateProps(M); + RBI = ResourceBindingInfo( + /*RecordID=*/0, /*Space=*/2, /*LowerBound=*/0, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x00005002U); EXPECT_EQ(Props.second, 0x00000204U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 2, 0, 1, 2, true, false, false, TestMD.get(0, 4))); // RasterizerOrderedBuffer ROB; - HandleTy = llvm::TargetExtType::get( + RTI = ResourceTypeInfo(llvm::TargetExtType::get( Context, "dx.TypedBuffer", Floatx4Ty, - {/*IsWriteable=*/1, /*IsROV=*/1, /*IsSigned=*/0}); - RI = ResourceInfo( - /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::UAV); - EXPECT_EQ(RI.getUAV().GloballyCoherent, false); - EXPECT_EQ(RI.getUAV().HasCounter, false); - EXPECT_EQ(RI.getUAV().IsROV, true); - ASSERT_EQ(RI.isTyped(), true); - EXPECT_EQ(RI.getTyped().ElementTy, ElementType::F32); - EXPECT_EQ(RI.getTyped().ElementCount, 4u); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::TypedBuffer); - - Props = RI.getAnnotateProps(M); + {/*IsWriteable=*/1, /*IsROV=*/1, /*IsSigned=*/0})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV); + EXPECT_EQ(RTI.getUAV().GloballyCoherent, false); + EXPECT_EQ(RTI.getUAV().HasCounter, false); + EXPECT_EQ(RTI.getUAV().IsROV, true); + ASSERT_EQ(RTI.isTyped(), true); + EXPECT_EQ(RTI.getTyped().ElementTy, ElementType::F32); + EXPECT_EQ(RTI.getTyped().ElementCount, 4u); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::TypedBuffer); + + RBI = ResourceBindingInfo( + /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x0000300aU); EXPECT_EQ(Props.second, 0x00000409U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 10, false, false, true, TestMD.get(0, 9))); // RWStructuredBuffer g_OutputBuffer : register(u2); StructType *BufType1 = StructType::create( Context, {Floatx3Ty, FloatTy, Int32Ty}, "ParticleMotion"); - HandleTy = llvm::TargetExtType::get(Context, "dx.RawBuffer", BufType1, - {/*IsWriteable=*/1, /*IsROV=*/0}); - RI = ResourceInfo( - /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/2, /*Size=*/1, HandleTy, + RTI = ResourceTypeInfo( + llvm::TargetExtType::get(Context, "dx.RawBuffer", BufType1, + {/*IsWriteable=*/1, /*IsROV=*/0}), /*GloballyCoherent=*/false, /*HasCounter=*/true); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::UAV); - EXPECT_EQ(RI.getUAV().GloballyCoherent, false); - EXPECT_EQ(RI.getUAV().HasCounter, true); - EXPECT_EQ(RI.getUAV().IsROV, false); - ASSERT_EQ(RI.isStruct(), true); - EXPECT_EQ(RI.getStruct(DL).Stride, 20u); - EXPECT_EQ(RI.getStruct(DL).AlignLog2, Log2(Align(4))); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::StructuredBuffer); - - Props = RI.getAnnotateProps(M); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV); + EXPECT_EQ(RTI.getUAV().GloballyCoherent, false); + EXPECT_EQ(RTI.getUAV().HasCounter, true); + EXPECT_EQ(RTI.getUAV().IsROV, false); + ASSERT_EQ(RTI.isStruct(), true); + EXPECT_EQ(RTI.getStruct(DL).Stride, 20u); + EXPECT_EQ(RTI.getStruct(DL).AlignLog2, Log2(Align(4))); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::StructuredBuffer); + + RBI = ResourceBindingInfo( + /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/2, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x0000920cU); EXPECT_EQ(Props.second, 0x00000014U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 2, 1, 12, false, true, false, TestMD.get(1, 20))); // RWTexture2DMSArray g_rw_t2dmsa; - HandleTy = llvm::TargetExtType::get( + RTI = ResourceTypeInfo(llvm::TargetExtType::get( Context, "dx.MSTexture", Int32Ty, {/*IsWriteable=*/1, /*SampleCount=*/8, /*IsSigned=*/0, - llvm::to_underlying(ResourceKind::Texture2DMSArray)}); - RI = ResourceInfo( - /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::UAV); - EXPECT_EQ(RI.getUAV().GloballyCoherent, false); - EXPECT_EQ(RI.getUAV().HasCounter, false); - EXPECT_EQ(RI.getUAV().IsROV, false); - ASSERT_EQ(RI.isTyped(), true); - EXPECT_EQ(RI.getTyped().ElementTy, ElementType::U32); - EXPECT_EQ(RI.getTyped().ElementCount, 1u); - ASSERT_EQ(RI.isMultiSample(), true); - EXPECT_EQ(RI.getMultiSampleCount(), 8u); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::Texture2DMSArray); - - Props = RI.getAnnotateProps(M); + llvm::to_underlying(ResourceKind::Texture2DMSArray)})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV); + EXPECT_EQ(RTI.getUAV().GloballyCoherent, false); + EXPECT_EQ(RTI.getUAV().HasCounter, false); + EXPECT_EQ(RTI.getUAV().IsROV, false); + ASSERT_EQ(RTI.isTyped(), true); + EXPECT_EQ(RTI.getTyped().ElementTy, ElementType::U32); + EXPECT_EQ(RTI.getTyped().ElementCount, 1u); + ASSERT_EQ(RTI.isMultiSample(), true); + EXPECT_EQ(RTI.getMultiSampleCount(), 8u); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Texture2DMSArray); + + RBI = ResourceBindingInfo( + /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x00001008U); EXPECT_EQ(Props.second, 0x00080105U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 8, false, false, false, TestMD.get(0, 5))); // cbuffer cb0 { float4 g_X; float4 g_Y; } StructType *CBufType0 = StructType::create(Context, {Floatx4Ty, Floatx4Ty}, "cb0"); - HandleTy = - llvm::TargetExtType::get(Context, "dx.CBuffer", CBufType0, {/*Size=*/32}); - RI = ResourceInfo( - /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::CBuffer); - EXPECT_EQ(RI.getCBufferSize(DL), 32u); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::CBuffer); - - Props = RI.getAnnotateProps(M); + RTI = ResourceTypeInfo(llvm::TargetExtType::get(Context, "dx.CBuffer", + CBufType0, {/*Size=*/32})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::CBuffer); + EXPECT_EQ(RTI.getCBufferSize(DL), 32u); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::CBuffer); + + RBI = ResourceBindingInfo( + /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x0000000dU); EXPECT_EQ(Props.second, 0x00000020U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 32, nullptr)); // SamplerState ColorMapSampler : register(s0); - HandleTy = llvm::TargetExtType::get( + RTI = ResourceTypeInfo(llvm::TargetExtType::get( Context, "dx.Sampler", {}, - {llvm::to_underlying(dxil::SamplerType::Default)}); - RI = ResourceInfo( - /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::Sampler); - EXPECT_EQ(RI.getSamplerType(), dxil::SamplerType::Default); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::Sampler); - - Props = RI.getAnnotateProps(M); + {llvm::to_underlying(dxil::SamplerType::Default)})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::Sampler); + EXPECT_EQ(RTI.getSamplerType(), dxil::SamplerType::Default); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Sampler); + + RBI = ResourceBindingInfo( + /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x0000000eU); EXPECT_EQ(Props.second, 0U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 0, nullptr)); - HandleTy = llvm::TargetExtType::get( + RTI = ResourceTypeInfo(llvm::TargetExtType::get( Context, "dx.Sampler", {}, - {llvm::to_underlying(dxil::SamplerType::Comparison)}); - RI = ResourceInfo( - /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, HandleTy); - - EXPECT_EQ(RI.getResourceClass(), ResourceClass::Sampler); - EXPECT_EQ(RI.getSamplerType(), dxil::SamplerType::Comparison); - EXPECT_EQ(RI.getResourceKind(), ResourceKind::Sampler); - - Props = RI.getAnnotateProps(M); + {llvm::to_underlying(dxil::SamplerType::Comparison)})); + EXPECT_EQ(RTI.getResourceClass(), ResourceClass::Sampler); + EXPECT_EQ(RTI.getSamplerType(), dxil::SamplerType::Comparison); + EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Sampler); + + RBI = ResourceBindingInfo( + /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1, + RTI.getHandleTy()); + Props = RBI.getAnnotateProps(M, RTI); EXPECT_EQ(Props.first, 0x0000800eU); EXPECT_EQ(Props.second, 0U); - MD = RI.getAsMetadata(M); + MD = RBI.getAsMetadata(M, RTI); EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 1, nullptr)); } From 305a0f5ea75bd56b1ef8666f3bb60a048751e9aa Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Mon, 16 Dec 2024 14:14:20 -0700 Subject: [PATCH 2/3] fixup: add comment --- llvm/include/llvm/Analysis/DXILResource.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h index acde2f4bf41a2..606ca554c32ca 100644 --- a/llvm/include/llvm/Analysis/DXILResource.h +++ b/llvm/include/llvm/Analysis/DXILResource.h @@ -407,6 +407,8 @@ class DXILResourceTypeAnalysis using Result = DXILResourceTypeMap; DXILResourceTypeMap run(Module &M, ModuleAnalysisManager &AM) { + // Running the pass just generates an empty map, which will be filled when + // users of the pass query the results. return Result(); } }; From f8f9d092da1f70cad58490337fb99b0be1e87705 Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Tue, 17 Dec 2024 13:59:42 -0700 Subject: [PATCH 3/3] fixup: Store ResourceBindingInfo directly rather than a smaller type --- llvm/include/llvm/Analysis/DXILResource.h | 40 ++++++------------- llvm/lib/Analysis/DXILResource.cpp | 29 ++++---------- .../lib/Target/DirectX/DXContainerGlobals.cpp | 2 +- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 5 ++- .../Target/DirectX/DXILTranslateMetadata.cpp | 8 ++-- 5 files changed, 28 insertions(+), 56 deletions(-) diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h index 606ca554c32ca..64ff94406a75f 100644 --- a/llvm/include/llvm/Analysis/DXILResource.h +++ b/llvm/include/llvm/Analysis/DXILResource.h @@ -293,6 +293,9 @@ class ResourceTypeInfo { dxil::ResourceClass getResourceClass() const { return RC; } dxil::ResourceKind getResourceKind() const { return Kind; } + void setGloballyCoherent(bool V) { GloballyCoherent = V; } + void setHasCounter(bool V) { HasCounter = V; } + bool operator==(const ResourceTypeInfo &RHS) const; bool operator!=(const ResourceTypeInfo &RHS) const { return !(*this == RHS); } bool operator<(const ResourceTypeInfo &RHS) const; @@ -341,13 +344,10 @@ class ResourceBindingInfo { return ""; } - MDTuple *getAsMetadata(Module &M, DXILResourceTypeMap &DRTM) const; - MDTuple *getAsMetadata(Module &M, dxil::ResourceTypeInfo RTI) const; + MDTuple *getAsMetadata(Module &M, dxil::ResourceTypeInfo &RTI) const; std::pair - getAnnotateProps(Module &M, DXILResourceTypeMap &DRTM) const; - std::pair - getAnnotateProps(Module &M, dxil::ResourceTypeInfo RTI) const; + getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const; bool operator==(const ResourceBindingInfo &RHS) const { return std::tie(Binding, HandleTy) == std::tie(RHS.Binding, RHS.HandleTy); @@ -359,9 +359,7 @@ class ResourceBindingInfo { return Binding < RHS.Binding; } - void print(raw_ostream &OS, DXILResourceTypeMap &DRTM, - const DataLayout &DL) const; - void print(raw_ostream &OS, dxil::ResourceTypeInfo RTI, + void print(raw_ostream &OS, dxil::ResourceTypeInfo &RTI, const DataLayout &DL) const; }; @@ -370,30 +368,18 @@ class ResourceBindingInfo { //===----------------------------------------------------------------------===// class DXILResourceTypeMap { - struct Info { - dxil::ResourceClass RC; - dxil::ResourceKind Kind; - bool GloballyCoherent; - bool HasCounter; - }; - DenseMap Infos; + DenseMap Infos; public: bool invalidate(Module &M, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &Inv); - dxil::ResourceTypeInfo operator[](TargetExtType *Ty) { - Info I = Infos[Ty]; - return dxil::ResourceTypeInfo(Ty, I.RC, I.Kind, I.GloballyCoherent, - I.HasCounter); - } - - void setGloballyCoherent(TargetExtType *Ty, bool GloballyCoherent) { - Infos[Ty].GloballyCoherent = GloballyCoherent; - } - - void setHasCounter(TargetExtType *Ty, bool HasCounter) { - Infos[Ty].HasCounter = HasCounter; + dxil::ResourceTypeInfo &operator[](TargetExtType *Ty) { + auto It = Infos.find(Ty); + if (It != Infos.end()) + return It->second; + auto [NewIt, Inserted] = Infos.try_emplace(Ty, Ty); + return NewIt->second; } }; diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp index 07b1617d7b359..ed1d6ce966e28 100644 --- a/llvm/lib/Analysis/DXILResource.cpp +++ b/llvm/lib/Analysis/DXILResource.cpp @@ -450,12 +450,7 @@ void ResourceTypeInfo::print(raw_ostream &OS, const DataLayout &DL) const { } MDTuple *ResourceBindingInfo::getAsMetadata(Module &M, - DXILResourceTypeMap &DRTM) const { - return getAsMetadata(M, DRTM[getHandleTy()]); -} - -MDTuple *ResourceBindingInfo::getAsMetadata(Module &M, - dxil::ResourceTypeInfo RTI) const { + dxil::ResourceTypeInfo &RTI) const { LLVMContext &Ctx = M.getContext(); const DataLayout &DL = M.getDataLayout(); @@ -529,13 +524,7 @@ MDTuple *ResourceBindingInfo::getAsMetadata(Module &M, std::pair ResourceBindingInfo::getAnnotateProps(Module &M, - DXILResourceTypeMap &DRTM) const { - return getAnnotateProps(M, DRTM[getHandleTy()]); -} - -std::pair -ResourceBindingInfo::getAnnotateProps(Module &M, - dxil::ResourceTypeInfo RTI) const { + dxil::ResourceTypeInfo &RTI) const { const DataLayout &DL = M.getDataLayout(); uint32_t ResourceKind = llvm::to_underlying(RTI.getResourceKind()); @@ -582,12 +571,7 @@ ResourceBindingInfo::getAnnotateProps(Module &M, return {Word0, Word1}; } -void ResourceBindingInfo::print(raw_ostream &OS, DXILResourceTypeMap &DRTM, - const DataLayout &DL) const { - print(OS, DRTM[getHandleTy()], DL); -} - -void ResourceBindingInfo::print(raw_ostream &OS, dxil::ResourceTypeInfo RTI, +void ResourceBindingInfo::print(raw_ostream &OS, dxil::ResourceTypeInfo &RTI, const DataLayout &DL) const { OS << " Binding:\n" << " Record ID: " << Binding.RecordID << "\n" @@ -623,7 +607,7 @@ void DXILBindingMap::populate(Module &M, DXILResourceTypeMap &DRTM) { continue; case Intrinsic::dx_handle_fromBinding: { auto *HandleTy = cast(F.getReturnType()); - ResourceTypeInfo RTI = DRTM[HandleTy]; + ResourceTypeInfo &RTI = DRTM[HandleTy]; for (User *U : F.users()) if (CallInst *CI = dyn_cast(U)) { @@ -667,7 +651,7 @@ void DXILBindingMap::populate(Module &M, DXILResourceTypeMap &DRTM) { uint32_t NextID = 0; for (unsigned I = 0, E = Size; I != E; ++I) { ResourceBindingInfo &RBI = Infos[I]; - ResourceTypeInfo RTI = DRTM[RBI.getHandleTy()]; + ResourceTypeInfo &RTI = DRTM[RBI.getHandleTy()]; if (RTI.isUAV() && FirstUAV == Size) { FirstUAV = I; NextID = 0; @@ -688,7 +672,8 @@ void DXILBindingMap::print(raw_ostream &OS, DXILResourceTypeMap &DRTM, const DataLayout &DL) const { for (unsigned I = 0, E = Infos.size(); I != E; ++I) { OS << "Binding " << I << ":\n"; - Infos[I].print(OS, DRTM, DL); + const dxil::ResourceBindingInfo &RBI = Infos[I]; + RBI.print(OS, DRTM[RBI.getHandleTy()], DL); OS << "\n"; } diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 4c55a13b17f29..7a0bd6a7c8869 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -158,7 +158,7 @@ void DXContainerGlobals::addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV) { BindInfo.UpperBound = Binding.LowerBound + Binding.Size - 1; BindInfo.Space = Binding.Space; - dxil::ResourceTypeInfo TypeInfo = DRTM[RBI.getHandleTy()]; + dxil::ResourceTypeInfo &TypeInfo = DRTM[RBI.getHandleTy()]; dxbc::PSV::ResourceType ResType = dxbc::PSV::ResourceType::Invalid; bool IsUAV = TypeInfo.getResourceClass() == dxil::ResourceClass::UAV; switch (TypeInfo.getResourceKind()) { diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index c66b24442d4bd..d28e895f009ed 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -302,7 +302,8 @@ class OpLowerer { dxil::ResourceBindingInfo &RI = *It; const auto &Binding = RI.getBinding(); - dxil::ResourceClass RC = DRTM[RI.getHandleTy()].getResourceClass(); + dxil::ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()]; + dxil::ResourceClass RC = RTI.getResourceClass(); Value *IndexOp = CI->getArgOperand(3); if (Binding.LowerBound != 0) @@ -310,7 +311,7 @@ class OpLowerer { ConstantInt::get(Int32Ty, Binding.LowerBound)); std::pair Props = - RI.getAnnotateProps(*F.getParent(), DRTM); + RI.getAnnotateProps(*F.getParent(), RTI); // For `CreateHandleFromBinding` we need the upper bound rather than the // size, so we need to be careful about the difference for "unbounded". diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp index 9763fe6a8a345..10d72901b3d03 100644 --- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp @@ -79,13 +79,13 @@ static NamedMDNode *emitResourceMetadata(Module &M, DXILBindingMap &DBM, SmallVector SRVs, UAVs, CBufs, Smps; for (const ResourceBindingInfo &RI : DBM.srvs()) - SRVs.push_back(RI.getAsMetadata(M, DRTM)); + SRVs.push_back(RI.getAsMetadata(M, DRTM[RI.getHandleTy()])); for (const ResourceBindingInfo &RI : DBM.uavs()) - UAVs.push_back(RI.getAsMetadata(M, DRTM)); + UAVs.push_back(RI.getAsMetadata(M, DRTM[RI.getHandleTy()])); for (const ResourceBindingInfo &RI : DBM.cbuffers()) - CBufs.push_back(RI.getAsMetadata(M, DRTM)); + CBufs.push_back(RI.getAsMetadata(M, DRTM[RI.getHandleTy()])); for (const ResourceBindingInfo &RI : DBM.samplers()) - Smps.push_back(RI.getAsMetadata(M, DRTM)); + Smps.push_back(RI.getAsMetadata(M, DRTM[RI.getHandleTy()])); Metadata *SRVMD = SRVs.empty() ? nullptr : MDNode::get(Context, SRVs); Metadata *UAVMD = UAVs.empty() ? nullptr : MDNode::get(Context, UAVs);