[llvm-branch-commits] [llvm] [DirectX] Split resource info into type and binding info. NFC (PR #119773)

Justin Bogner via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Dec 12 13:54:36 PST 2024


https://github.com/bogner created https://github.com/llvm/llvm-project/pull/119773

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

>From 7bf113df69b4e8e76ad050d7c6c75b8d5d3572a6 Mon Sep 17 00:00:00 2001
From: Justin Bogner <mail at justinbogner.com>
Date: Thu, 12 Dec 2024 13:43:22 -0800
Subject: [PATCH] [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            | 383 ++++++++++-------
 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        |  16 +-
 llvm/test/CodeGen/DirectX/llc-pipeline.ll     |   4 +-
 llvm/unittests/Analysis/DXILResourceTest.cpp  | 392 +++++++++---------
 19 files changed, 722 insertions(+), 544 deletions(-)

diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 0205356af54443..2f5dded46538ea 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -25,6 +25,8 @@ class MDTuple;
 class TargetExtType;
 class Value;
 
+class DXILResourceTypeMap;
+
 namespace dxil {
 
 /// The dx.RawBuffer target extension type
@@ -196,27 +198,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;
@@ -266,12 +249,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;
 
@@ -279,9 +261,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; }
 
@@ -303,44 +289,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<uint32_t, uint32_t> 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<uint32_t, uint32_t>
+  getAnnotateProps(Module &M, DXILResourceTypeMap &DRTM) const;
+  std::pair<uint32_t, uint32_t>
+  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<dxil::ResourceInfo> Infos;
+class DXILResourceTypeMap {
+  struct Info {
+    dxil::ResourceClass RC;
+    dxil::ResourceKind Kind;
+    bool GloballyCoherent;
+    bool HasCounter;
+  };
+  DenseMap<TargetExtType *, Info> 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<DXILResourceTypeAnalysis> {
+  friend AnalysisInfoMixin<DXILResourceTypeAnalysis>;
+
+  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<dxil::ResourceBindingInfo> Infos;
   DenseMap<CallInst *, unsigned> 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<dxil::ResourceInfo>::iterator;
-  using const_iterator = SmallVector<dxil::ResourceInfo>::const_iterator;
+  using iterator = SmallVector<dxil::ResourceBindingInfo>::iterator;
+  using const_iterator = SmallVector<dxil::ResourceBindingInfo>::const_iterator;
 
   iterator begin() { return Infos.begin(); }
   const_iterator begin() const { return Infos.begin(); }
@@ -399,47 +498,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<DXILResourceAnalysis> {
-  friend AnalysisInfoMixin<DXILResourceAnalysis>;
+class DXILResourceBindingAnalysis
+    : public AnalysisInfoMixin<DXILResourceBindingAnalysis> {
+  friend AnalysisInfoMixin<DXILResourceBindingAnalysis>;
 
   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<DXILResourcePrinterPass> {
+/// Printer pass for the \c DXILResourceBindingAnalysis results.
+class DXILResourceBindingPrinterPass
+    : public PassInfoMixin<DXILResourceBindingPrinterPass> {
   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<DXILResourceMap> Map;
+class DXILResourceBindingWrapperPass : public ModulePass {
+  std::unique_ptr<DXILBindingMap> 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;
@@ -449,7 +552,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 7d829cf5b9b015..1cb9013bc48cc5 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 54245ca0b70222..ac1970334de0cd 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 58723469f21ca8..bc2b8a57f83a7a 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 f96a9468d6bc54..e1942a0c4930cd 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<RawBufferExtType>(HandleTy)) {
     RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
     Kind = Ty->isStructured() ? ResourceKind::StructuredBuffer
@@ -209,21 +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 {
+bool ResourceTypeInfo::isCBuffer() const {
   return RC == ResourceClass::CBuffer;
 }
 
-bool ResourceInfo::isSampler() const {
+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:
@@ -252,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;
 }
@@ -293,24 +300,24 @@ 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");
   Type *Ty = cast<CBufferExtType>(HandleTy)->getResourceType();
   return DL.getTypeSizeInBits(Ty) / 8;
 }
 
-dxil::SamplerType ResourceInfo::getSamplerType() const {
+dxil::SamplerType ResourceTypeInfo::getSamplerType() const {
   assert(isSampler() && "Not a Sampler");
   return cast<SamplerExtType>(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<RawBufferExtType>(HandleTy)->getResourceType();
@@ -360,7 +367,7 @@ static std::pair<Type *, bool> 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);
@@ -371,17 +378,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<FeedbackTextureExtType>(HandleTy)->getFeedbackType();
 }
-
-uint32_t ResourceInfo::getMultiSampleCount() const {
+uint32_t ResourceTypeInfo::getMultiSampleCount() const {
   assert(isMultiSample() && "Not MultiSampled");
   return cast<MSTextureExtType>(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();
 
@@ -410,17 +485,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));
@@ -429,23 +504,23 @@ MDTuple *ResourceInfo::getAsMetadata(Module &M) const {
       // 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;
+          RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0;
       MDVals.push_back(getIntMD(SampleCount));
     }
 
     // Further properties are attached to a metadata list of tag-value pairs.
     SmallVector<Metadata *> 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));
   }
@@ -453,21 +528,29 @@ MDTuple *ResourceInfo::getAsMetadata(Module &M) const {
   return MDNode::get(Ctx, MDVals);
 }
 
-std::pair<uint32_t, uint32_t> ResourceInfo::getAnnotateProps(Module &M) const {
+std::pair<uint32_t, uint32_t>
+ResourceBindingInfo::getAnnotateProps(Module &M,
+                                      DXILResourceTypeMap &DRTM) const {
+  return getAnnotateProps(M, DRTM[getHandleTy()]);
+}
+
+std::pair<uint32_t, uint32_t>
+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.
@@ -480,17 +563,17 @@ std::pair<uint32_t, uint32_t> 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;
@@ -500,80 +583,36 @@ std::pair<uint32_t, uint32_t> 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<DXILResourceTypeAnalysis>();
+  return !PAC.preservedWhenStateless();
 }
 
 //===----------------------------------------------------------------------===//
 
-void DXILResourceMap::populate(Module &M) {
-  SmallVector<std::pair<CallInst *, ResourceInfo>> CIToInfo;
+void DXILBindingMap::populate(Module &M, DXILResourceTypeMap &DRTM) {
+  SmallVector<std::tuple<CallInst *, ResourceBindingInfo, ResourceTypeInfo>>
+      CIToInfos;
 
   for (Function &F : M.functions()) {
     if (!F.isDeclaration())
@@ -585,6 +624,7 @@ void DXILResourceMap::populate(Module &M) {
       continue;
     case Intrinsic::dx_handle_fromBinding: {
       auto *HandleTy = cast<TargetExtType>(F.getReturnType());
+      ResourceTypeInfo RTI = DRTM[HandleTy];
 
       for (User *U : F.users())
         if (CallInst *CI = dyn_cast<CallInst>(U)) {
@@ -595,10 +635,10 @@ void DXILResourceMap::populate(Module &M) {
               cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
           uint32_t Size =
               cast<ConstantInt>(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;
@@ -606,16 +646,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;
   }
 
@@ -624,27 +667,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";
   }
 
@@ -657,60 +702,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<DXILResourceTypeAnalysis>(M);
+  Data.populate(M, DRTM);
   return Data;
 }
 
-PreservedAnalyses DXILResourcePrinterPass::run(Module &M,
-                                               ModuleAnalysisManager &AM) {
-  DXILResourceMap &DBM = AM.getResult<DXILResourceAnalysis>(M);
+PreservedAnalyses
+DXILResourceBindingPrinterPass::run(Module &M, ModuleAnalysisManager &AM) {
+  DXILBindingMap &DBM = AM.getResult<DXILResourceBindingAnalysis>(M);
+  DXILResourceTypeMap &DRTM = AM.getResult<DXILResourceTypeAnalysis>(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<DXILResourceTypeWrapperPass>();
   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<DXILResourceTypeWrapperPass>().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 825f2f7f9a494a..ad7e6429a17417 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<dxil-metadata>", DXILMetadataAnalysisPrinterPass(errs()))
-MODULE_PASS("print<dxil-resource>", DXILResourcePrinterPass(errs()))
+MODULE_PASS("print<dxil-resource-binding>",
+            DXILResourceBindingPrinterPass(errs()))
 MODULE_PASS("print<inline-advisor>", InlineAdvisorAnalysisPrinterPass(errs()))
 MODULE_PASS("print<module-debuginfo>", ModuleDebugInfoPrinterPass(errs()))
 MODULE_PASS("print<reg-usage>", PhysicalRegisterUsageInfoPrinterPass(errs()))
diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index aaf994b23cf3c9..4c55a13b17f29b 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<ShaderFlagsAnalysisWrapper>();
     AU.addRequired<DXILMetadataAnalysisWrapperPass>();
-    AU.addRequired<DXILResourceWrapperPass>();
+    AU.addRequired<DXILResourceTypeWrapperPass>();
+    AU.addRequired<DXILResourceBindingWrapperPass>();
   }
 };
 
@@ -144,19 +145,23 @@ void DXContainerGlobals::addSignature(Module &M,
 }
 
 void DXContainerGlobals::addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV) {
-  const DXILResourceMap &ResMap =
-      getAnalysis<DXILResourceWrapperPass>().getResourceMap();
-
-  for (const dxil::ResourceInfo &ResInfo : ResMap) {
-    const dxil::ResourceInfo::ResourceBinding &Binding = ResInfo.getBinding();
+  const DXILBindingMap &DBM =
+      getAnalysis<DXILResourceBindingWrapperPass>().getBindingMap();
+  DXILResourceTypeMap &DRTM =
+      getAnalysis<DXILResourceTypeWrapperPass>().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<dxbc::PSV::ResourceKind>(ResInfo.getResourceKind());
+        static_cast<dxbc::PSV::ResourceKind>(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 0e6cf59e257508..1783e4a5463135 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<DXILResourceAnalysis>();
   return PA;
 }
 
@@ -284,10 +281,6 @@ bool DXILDataScalarizationLegacy::runOnModule(Module &M) {
   return findAndReplaceVectors(M);
 }
 
-void DXILDataScalarizationLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
-  AU.addPreserved<DXILResourceWrapperPass>();
-}
-
 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 79ebbe0925e5c3..91ac758150fb4c 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<DXILResourceWrapperPass>();
-}
-
 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 62d3a8a27cfced..aab1bc3f7a28e2 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 e4a3bc76eeacd2..6077af997212ea 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<DXILResourceAnalysis>();
   return PA;
 }
 
@@ -427,10 +424,6 @@ bool DXILFlattenArraysLegacy::runOnModule(Module &M) {
   return flattenArrays(M);
 }
 
-void DXILFlattenArraysLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
-  AU.addPreserved<DXILResourceWrapperPass>();
-}
-
 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 d2bfca1fada559..3c6ea4470fbdcc 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<DXILResourceWrapperPass>();
-}
-
 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 78efdcf194b6c6..c66b24442d4bd0 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<CallInst *> 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<Value *, 4> 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<CallInst *> 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<uint32_t, uint32_t> Props = RI.getAnnotateProps(*F.getParent());
+      std::pair<uint32_t, uint32_t> 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<Value *, 3> BindArgs{ResBind, IndexOp, CI->getArgOperand(4)};
       Expected<CallInst *> 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<DXILResourceAnalysis>(M);
+  DXILBindingMap &DBM = MAM.getResult<DXILResourceBindingAnalysis>(M);
+  DXILResourceTypeMap &DRTM = MAM.getResult<DXILResourceTypeAnalysis>(M);
 
-  bool MadeChanges = OpLowerer(M, DRM).lowerIntrinsics();
+  bool MadeChanges = OpLowerer(M, DBM, DRTM).lowerIntrinsics();
   if (!MadeChanges)
     return PreservedAnalyses::all();
   PreservedAnalyses PA;
-  PA.preserve<DXILResourceAnalysis>();
+  PA.preserve<DXILResourceBindingAnalysis>();
   return PA;
 }
 
@@ -751,18 +758,21 @@ namespace {
 class DXILOpLoweringLegacy : public ModulePass {
 public:
   bool runOnModule(Module &M) override {
-    DXILResourceMap &DRM =
-        getAnalysis<DXILResourceWrapperPass>().getResourceMap();
+    DXILBindingMap &DBM =
+        getAnalysis<DXILResourceBindingWrapperPass>().getBindingMap();
+    DXILResourceTypeMap &DRTM =
+        getAnalysis<DXILResourceTypeWrapperPass>().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<DXILResourceWrapperPass>();
-    AU.addPreserved<DXILResourceWrapperPass>();
+    AU.addRequired<DXILResourceTypeWrapperPass>();
+    AU.addRequired<DXILResourceBindingWrapperPass>();
+    AU.addPreserved<DXILResourceBindingWrapperPass>();
   }
 };
 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 6092cfb3948f0c..375e6ce7129245 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<ShaderFlagsAnalysisWrapper>();
     AU.addPreserved<DXILResourceMDWrapper>();
     AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
-    AU.addPreserved<DXILResourceWrapperPass>();
+    AU.addPreserved<DXILResourceBindingWrapperPass>();
   }
   static char ID; // Pass identification.
 };
diff --git a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp
index 4aa25b3996e3c1..ff690f2abe4901 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<const dxil::ResourceInfo &> {
-  explicit FormatResourceDimension(const dxil::ResourceInfo &RI)
-      : llvm::FormatAdapter<const dxil::ResourceInfo &>(RI) {}
+    : public llvm::FormatAdapter<const dxil::ResourceTypeInfo &> {
+  explicit FormatResourceDimension(const dxil::ResourceTypeInfo &RI)
+      : llvm::FormatAdapter<const dxil::ResourceTypeInfo &>(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<const dxil::ResourceInfo &> {
-  explicit FormatBindingID(const dxil::ResourceInfo &RI)
-      : llvm::FormatAdapter<const dxil::ResourceInfo &>(RI) {}
+    : public llvm::FormatAdapter<const dxil::ResourceBindingInfo &> {
+  dxil::ResourceClass RC;
+
+  explicit FormatBindingID(const dxil::ResourceBindingInfo &RBI,
+                           const dxil::ResourceTypeInfo &RTI)
+      : llvm::FormatAdapter<const dxil::ResourceBindingInfo &>(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<const dxil::ResourceInfo &> {
-  explicit FormatBindingLocation(const dxil::ResourceInfo &RI)
-      : llvm::FormatAdapter<const dxil::ResourceInfo &>(RI) {}
+    : public llvm::FormatAdapter<const dxil::ResourceBindingInfo &> {
+  dxil::ResourceClass RC;
+
+  explicit FormatBindingLocation(const dxil::ResourceBindingInfo &RBI,
+                                 const dxil::ResourceTypeInfo &RTI)
+      : llvm::FormatAdapter<const dxil::ResourceBindingInfo &>(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<const dxil::ResourceInfo &> {
-  explicit FormatBindingSize(const dxil::ResourceInfo &RI)
-      : llvm::FormatAdapter<const dxil::ResourceInfo &>(RI) {}
+    : public llvm::FormatAdapter<const dxil::ResourceBindingInfo &> {
+  explicit FormatBindingSize(const dxil::ResourceBindingInfo &RI)
+      : llvm::FormatAdapter<const dxil::ResourceBindingInfo &>(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<DXILResourceAnalysis>(M);
+  const DXILBindingMap &DBM = MAM.getResult<DXILResourceBindingAnalysis>(M);
+  DXILResourceTypeMap &DRTM = MAM.getResult<DXILResourceTypeAnalysis>(M);
   const dxil::Resources &MDResources = MAM.getResult<DXILResourceMDAnalysis>(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<DXILResourceWrapperPass>();
+    AU.addRequired<DXILResourceTypeWrapperPass>();
+    AU.addRequired<DXILResourceBindingWrapperPass>();
     AU.addRequired<DXILResourceMDWrapper>();
   }
 };
@@ -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<DXILResourceWrapperPass>().getResourceMap();
+  const DXILBindingMap &DBM =
+      getAnalysis<DXILResourceBindingWrapperPass>().getBindingMap();
+  DXILResourceTypeMap &DRTM =
+      getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
   dxil::Resources &Res = getAnalysis<DXILResourceMDWrapper>().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 baefadede6e3ab..9763fe6a8a3455 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<Metadata *> 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<DXILResourceAnalysis>(M);
+  DXILBindingMap &DBM = MAM.getResult<DXILResourceBindingAnalysis>(M);
+  DXILResourceTypeMap &DRTM = MAM.getResult<DXILResourceTypeAnalysis>(M);
   const dxil::Resources &MDResources = MAM.getResult<DXILResourceMDAnalysis>(M);
   const ModuleShaderFlags &ShaderFlags = MAM.getResult<ShaderFlagsAnalysis>(M);
   const dxil::ModuleMetadataInfo MMDI = MAM.getResult<DXILMetadataAnalysis>(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<DXILResourceWrapperPass>();
+    AU.addRequired<DXILResourceTypeWrapperPass>();
+    AU.addRequired<DXILResourceBindingWrapperPass>();
     AU.addRequired<DXILResourceMDWrapper>();
     AU.addRequired<ShaderFlagsAnalysisWrapper>();
     AU.addRequired<DXILMetadataAnalysisWrapperPass>();
-    AU.addPreserved<DXILResourceWrapperPass>();
+    AU.addPreserved<DXILResourceBindingWrapperPass>();
     AU.addPreserved<DXILResourceMDWrapper>();
     AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
   }
 
   bool runOnModule(Module &M) override {
-    const DXILResourceMap &DRM =
-        getAnalysis<DXILResourceWrapperPass>().getResourceMap();
+    DXILBindingMap &DBM =
+        getAnalysis<DXILResourceBindingWrapperPass>().getBindingMap();
+    DXILResourceTypeMap &DRTM =
+        getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
     const dxil::Resources &MDResources =
         getAnalysis<DXILResourceMDWrapper>().getDXILResource();
     const ModuleShaderFlags &ShaderFlags =
@@ -396,7 +403,7 @@ class DXILTranslateMetadataLegacy : public ModulePass {
     dxil::ModuleMetadataInfo MMDI =
         getAnalysis<DXILMetadataAnalysisWrapperPass>().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 b26a185423597d..313c8376483b91 100644
--- a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
+++ b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
@@ -1,15 +1,13 @@
-; RUN: opt -S -disable-output -passes="print<dxil-resource>" < %s 2>&1 | FileCheck %s
+; RUN: opt -S -disable-output -passes="print<dxil-resource-binding>" < %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]+]]:
-  ; CHECK:   Symbol: ptr undef
-  ; CHECK:   Name: ""
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 0
   ; CHECK:     Space: 1
@@ -24,8 +22,6 @@ define void @test_typedbuffer() {
       @llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
           i32 4, i32 2, i32 1, i32 0, i1 false)
   ; CHECK: Binding [[SRV1:[0-9]+]]:
-  ; CHECK:   Symbol: ptr undef
-  ; CHECK:   Name: ""
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 1
   ; CHECK:     Space: 4
@@ -41,8 +37,6 @@ define void @test_typedbuffer() {
       @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_0_0t(
           i32 5, i32 3, i32 24, i32 0, i1 false)
   ; CHECK: Binding [[SRV2:[0-9]+]]:
-  ; CHECK:   Symbol: ptr undef
-  ; CHECK:   Name: ""
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 2
   ; CHECK:     Space: 5
@@ -58,8 +52,6 @@ define void @test_typedbuffer() {
       @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0t(
           i32 2, i32 7, i32 1, i32 0, i1 false)
   ; CHECK: Binding [[UAV0:[0-9]+]]:
-  ; CHECK:   Symbol: ptr undef
-  ; CHECK:   Name: ""
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 0
   ; CHECK:     Space: 2
@@ -78,8 +70,6 @@ define void @test_typedbuffer() {
               @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0(
                   i32 3, i32 5, i32 1, i32 0, i1 false)
   ; CHECK: Binding [[UAV1:[0-9]+]]:
-  ; CHECK:   Symbol: ptr undef
-  ; CHECK:   Name: ""
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 1
   ; CHECK:     Space: 3
@@ -103,8 +93,6 @@ define void @test_typedbuffer() {
               @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0(
                   i32 4, i32 0, i32 10, i32 5, i1 false)
   ; CHECK: Binding [[UAV2:[0-9]+]]:
-  ; CHECK:   Symbol: ptr undef
-  ; CHECK:   Name: ""
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 2
   ; CHECK:     Space: 4
diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
index 40fa30778a1532..147898efc716fd 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 2122f1a91cfc96..784ea7702c0d5f 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<uint32_t, uint32_t> 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<uint32_t, uint32_t> 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,270 +160,272 @@ TEST(DXILResource, AnnotationsAndMetadata) {
   // StructuredBuffer<BufType0> 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<float3> 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<float4> 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<float, 8> 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<SAMPLER_FEEDBACK_MIN_MIP> 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<SAMPLER_FEEDBACK_MIP_REGION_USED> 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<int2> 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<float4> 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<ParticleMotion> 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<uint, 8> 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, {});
-  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, {}));
+  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));
 }



More information about the llvm-branch-commits mailing list