[llvm] [DXIL][Analysis] Uniquify duplicate resources in DXILResourceAnalysis (PR #105602)
Justin Bogner via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 23 10:20:40 PDT 2024
https://github.com/bogner updated https://github.com/llvm/llvm-project/pull/105602
>From a78456b8bce36978efeb23e2219ff8f6a1599d5f Mon Sep 17 00:00:00 2001
From: Justin Bogner <mail at justinbogner.com>
Date: Wed, 21 Aug 2024 18:02:56 -0700
Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
=?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.5-bogner
---
llvm/include/llvm/Analysis/DXILResource.h | 101 +++++++++-
llvm/lib/Analysis/DXILResource.cpp | 172 +++++++++++-------
.../DXILResource/buffer-frombinding.ll | 164 +++++++++--------
3 files changed, 290 insertions(+), 147 deletions(-)
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 14cf03c9a3acee..58db0a93f2f351 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -25,6 +25,7 @@ class Value;
namespace dxil {
class ResourceInfo {
+public:
struct ResourceBinding {
uint32_t RecordID;
uint32_t Space;
@@ -38,6 +39,10 @@ class ResourceInfo {
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 {
@@ -50,6 +55,10 @@ class ResourceInfo {
std::tie(RHS.GloballyCoherent, RHS.HasCounter, RHS.IsROV);
}
bool operator!=(const UAVInfo &RHS) const { return !(*this == RHS); }
+ bool operator<(const UAVInfo &RHS) const {
+ return std::tie(GloballyCoherent, HasCounter, IsROV) <
+ std::tie(RHS.GloballyCoherent, RHS.HasCounter, RHS.IsROV);
+ }
};
struct StructInfo {
@@ -64,6 +73,9 @@ class ResourceInfo {
return std::tie(Stride, AlignLog2) == std::tie(RHS.Stride, RHS.AlignLog2);
}
bool operator!=(const StructInfo &RHS) const { return !(*this == RHS); }
+ bool operator<(const StructInfo &RHS) const {
+ return std::tie(Stride, AlignLog2) < std::tie(RHS.Stride, RHS.AlignLog2);
+ }
};
struct TypedInfo {
@@ -75,6 +87,10 @@ class ResourceInfo {
std::tie(RHS.ElementTy, RHS.ElementCount);
}
bool operator!=(const TypedInfo &RHS) const { return !(*this == RHS); }
+ bool operator<(const TypedInfo &RHS) const {
+ return std::tie(ElementTy, ElementCount) <
+ std::tie(RHS.ElementTy, RHS.ElementCount);
+ }
};
struct MSInfo {
@@ -82,6 +98,7 @@ class ResourceInfo {
bool operator==(const MSInfo &RHS) const { return Count == RHS.Count; }
bool operator!=(const MSInfo &RHS) const { return !(*this == RHS); }
+ bool operator<(const MSInfo &RHS) const { return Count < RHS.Count; }
};
struct FeedbackInfo {
@@ -89,8 +106,10 @@ class ResourceInfo {
bool operator==(const FeedbackInfo &RHS) const { return Type == RHS.Type; }
bool operator!=(const FeedbackInfo &RHS) const { return !(*this == RHS); }
+ bool operator<(const FeedbackInfo &RHS) const { return Type < RHS.Type; }
};
+private:
// Universal properties.
Value *Symbol;
StringRef Name;
@@ -138,6 +157,7 @@ class ResourceInfo {
Binding.LowerBound = LowerBound;
Binding.Size = Size;
}
+ const ResourceBinding &getBinding() const { return Binding; }
void setUAV(bool GloballyCoherent, bool HasCounter, bool IsROV) {
assert(isUAV() && "Not a UAV");
UAVFlags.GloballyCoherent = GloballyCoherent;
@@ -168,7 +188,11 @@ class ResourceInfo {
MultiSample.Count = Count;
}
+ dxil::ResourceClass getResourceClass() const { return RC; }
+
bool operator==(const ResourceInfo &RHS) const;
+ bool operator!=(const ResourceInfo &RHS) const { return !(*this == RHS); }
+ bool operator<(const ResourceInfo &RHS) const;
static ResourceInfo SRV(Value *Symbol, StringRef Name,
dxil::ElementType ElementTy, uint32_t ElementCount,
@@ -216,7 +240,6 @@ class ResourceInfo {
MDTuple *getAsMetadata(LLVMContext &Ctx) const;
- ResourceBinding getBinding() const { return Binding; }
std::pair<uint32_t, uint32_t> getAnnotateProps() const;
void print(raw_ostream &OS) const;
@@ -224,7 +247,81 @@ class ResourceInfo {
} // namespace dxil
-using DXILResourceMap = MapVector<CallInst *, dxil::ResourceInfo>;
+class DXILResourceMap {
+ SmallVector<dxil::ResourceInfo> Resources;
+ DenseMap<CallInst *, unsigned> CallMap;
+ unsigned FirstUAV = 0;
+ unsigned FirstCBuffer = 0;
+ unsigned FirstSampler = 0;
+
+public:
+ using iterator = SmallVector<dxil::ResourceInfo>::iterator;
+ using const_iterator = SmallVector<dxil::ResourceInfo>::const_iterator;
+
+ DXILResourceMap(
+ SmallVectorImpl<std::pair<CallInst *, dxil::ResourceInfo>> &&CIToRI);
+
+ iterator begin() { return Resources.begin(); }
+ const_iterator begin() const { return Resources.begin(); }
+ iterator end() { return Resources.end(); }
+ const_iterator end() const { return Resources.end(); }
+
+ bool empty() const { return Resources.empty(); }
+
+ iterator find(const CallInst *Key) {
+ auto Pos = CallMap.find(Key);
+ return Pos == CallMap.end() ? Resources.end()
+ : (Resources.begin() + Pos->second);
+ }
+
+ const_iterator find(const CallInst *Key) const {
+ auto Pos = CallMap.find(Key);
+ return Pos == CallMap.end() ? Resources.end()
+ : (Resources.begin() + Pos->second);
+ }
+
+ iterator srv_begin() { return begin(); }
+ const_iterator srv_begin() const { return begin(); }
+ iterator srv_end() { return begin() + FirstUAV; }
+ const_iterator srv_end() const { return begin() + FirstUAV; }
+ iterator_range<iterator> srvs() { return make_range(srv_begin(), srv_end()); }
+ iterator_range<const_iterator> srvs() const {
+ return make_range(srv_begin(), srv_end());
+ }
+
+ iterator uav_begin() { return begin() + FirstUAV; }
+ const_iterator uav_begin() const { return begin() + FirstUAV; }
+ iterator uav_end() { return begin() + FirstCBuffer; }
+ const_iterator uav_end() const { return begin() + FirstCBuffer; }
+ iterator_range<iterator> uavs() { return make_range(uav_begin(), uav_end()); }
+ iterator_range<const_iterator> uavs() const {
+ return make_range(uav_begin(), uav_end());
+ }
+
+ iterator cbuffer_begin() { return begin() + FirstCBuffer; }
+ const_iterator cbuffer_begin() const { return begin() + FirstCBuffer; }
+ iterator cbuffer_end() { return begin() + FirstSampler; }
+ const_iterator cbuffer_end() const { return begin() + FirstSampler; }
+ iterator_range<iterator> cbuffers() {
+ return make_range(cbuffer_begin(), cbuffer_end());
+ }
+ iterator_range<const_iterator> cbuffers() const {
+ return make_range(cbuffer_begin(), cbuffer_end());
+ }
+
+ iterator sampler_begin() { return begin() + FirstSampler; }
+ const_iterator sampler_begin() const { return begin() + FirstSampler; }
+ iterator sampler_end() { return end(); }
+ const_iterator sampler_end() const { return end(); }
+ iterator_range<iterator> samplers() {
+ return make_range(sampler_begin(), sampler_end());
+ }
+ iterator_range<const_iterator> samplers() const {
+ return make_range(sampler_begin(), sampler_end());
+ }
+
+ void print(raw_ostream &OS) const;
+};
class DXILResourceAnalysis : public AnalysisInfoMixin<DXILResourceAnalysis> {
friend AnalysisInfoMixin<DXILResourceAnalysis>;
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 1b5b051c9db29e..110a59331f15be 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -335,27 +335,45 @@ bool ResourceInfo::operator==(const ResourceInfo &RHS) const {
if (std::tie(Symbol, Name, Binding, RC, Kind) !=
std::tie(RHS.Symbol, RHS.Name, RHS.Binding, RHS.RC, RHS.Kind))
return false;
- if (isCBuffer())
- return CBufferSize == RHS.CBufferSize;
- if (isSampler())
- return SamplerTy == RHS.SamplerTy;
- if (isUAV() && UAVFlags != RHS.UAVFlags)
+ if (isCBuffer() && RHS.isCBuffer() && CBufferSize != RHS.CBufferSize)
return false;
-
- if (isStruct())
- return Struct == RHS.Struct;
- if (isFeedback())
- return Feedback == RHS.Feedback;
- if (isTyped() && Typed != RHS.Typed)
+ if (isSampler() && RHS.isSampler() && SamplerTy != RHS.SamplerTy)
+ return false;
+ if (isUAV() && RHS.isUAV() && UAVFlags != RHS.UAVFlags)
+ return false;
+ if (isStruct() && RHS.isStruct() && Struct != RHS.Struct)
+ return false;
+ if (isFeedback() && RHS.isFeedback() && Feedback != RHS.Feedback)
+ return false;
+ if (isTyped() && RHS.isTyped() && Typed != RHS.Typed)
+ return false;
+ if (isMultiSample() && RHS.isMultiSample() && MultiSample != RHS.MultiSample)
return false;
-
- if (isMultiSample())
- return MultiSample == RHS.MultiSample;
-
- assert((Kind == ResourceKind::RawBuffer) && "Unhandled resource kind");
return true;
}
+bool ResourceInfo::operator<(const ResourceInfo &RHS) const {
+ // Skip the symbol to avoid non-determinism, and the name to keep a consistent
+ // ordering even when we strip reflection data.
+ if (std::tie(Binding, RC, Kind) < std::tie(RHS.Binding, RHS.RC, RHS.Kind))
+ return true;
+ if (isCBuffer() && RHS.isCBuffer() && CBufferSize < RHS.CBufferSize)
+ return true;
+ if (isSampler() && RHS.isSampler() && SamplerTy < RHS.SamplerTy)
+ return true;
+ if (isUAV() && RHS.isUAV() && UAVFlags < RHS.UAVFlags)
+ return true;
+ if (isStruct() && RHS.isStruct() && Struct < RHS.Struct)
+ return true;
+ if (isFeedback() && RHS.isFeedback() && Feedback < RHS.Feedback)
+ return true;
+ if (isTyped() && RHS.isTyped() && Typed < RHS.Typed)
+ return true;
+ if (isMultiSample() && RHS.isMultiSample() && MultiSample < RHS.MultiSample)
+ return true;
+ return false;
+}
+
MDTuple *ResourceInfo::getAsMetadata(LLVMContext &Ctx) const {
SmallVector<Metadata *, 11> MDVals;
@@ -534,18 +552,10 @@ namespace {
class ResourceMapper {
Module &M;
LLVMContext &Context;
- DXILResourceMap &Resources;
-
- // In DXC, Record ID is unique per resource type. Match that.
- uint32_t NextUAV = 0;
- uint32_t NextSRV = 0;
- uint32_t NextCBuf = 0;
- uint32_t NextSmp = 0;
+ SmallVector<std::pair<CallInst *, dxil::ResourceInfo>> Resources;
public:
- ResourceMapper(Module &M,
- MapVector<CallInst *, dxil::ResourceInfo> &Resources)
- : M(M), Context(M.getContext()), Resources(Resources) {}
+ ResourceMapper(Module &M) : M(M), Context(M.getContext()) {}
void diagnoseHandle(CallInst *CI, const Twine &Msg,
DiagnosticSeverity Severity = DS_Error) {
@@ -585,13 +595,11 @@ class ResourceMapper {
// TODO: We don't actually keep track of the name right now...
StringRef Name = "";
- auto [It, Success] = Resources.try_emplace(CI, RC, Kind, Symbol, Name);
- assert(Success && "Mapping the same CallInst again?");
- (void)Success;
- // We grab a pointer into the map's storage, which isn't generally safe.
- // Since we're just using this to fill in the info the map won't mutate and
- // the pointer stays valid for as long as we need it to.
- ResourceInfo *RI = &(It->second);
+ // Note that we return a pointer into the vector's storage. This is okay as
+ // long as we don't add more elements until we're done with the pointer.
+ auto &Pair =
+ Resources.emplace_back(CI, ResourceInfo{RC, Kind, Symbol, Name});
+ ResourceInfo *RI = &Pair.second;
if (RI->isUAV())
// TODO: We need analysis for GloballyCoherent and HasCounter
@@ -658,27 +666,18 @@ class ResourceMapper {
if (!RI)
return nullptr;
- uint32_t NextID;
- if (RI->isCBuffer())
- NextID = NextCBuf++;
- else if (RI->isSampler())
- NextID = NextSmp++;
- else if (RI->isUAV())
- NextID = NextUAV++;
- else
- NextID = NextSRV++;
-
uint32_t Space = cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
uint32_t LowerBound =
cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
uint32_t Size = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
- RI->bind(NextID, Space, LowerBound, Size);
+ // We use a binding ID of zero for now - these will be filled in later.
+ RI->bind(0U, Space, LowerBound, Size);
return RI;
}
- void mapResources() {
+ DXILResourceMap mapResources() {
for (Function &F : M.functions()) {
if (!F.isDeclaration())
continue;
@@ -697,11 +696,67 @@ class ResourceMapper {
break;
}
}
+
+ return DXILResourceMap(std::move(Resources));
}
};
} // namespace
+DXILResourceMap::DXILResourceMap(
+ SmallVectorImpl<std::pair<CallInst *, dxil::ResourceInfo>> &&CIToRI) {
+ if (CIToRI.empty())
+ return;
+
+ llvm::stable_sort(CIToRI, [](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);
+ });
+ for (auto [CI, RI] : CIToRI) {
+ if (Resources.empty() || RI != Resources.back())
+ Resources.push_back(RI);
+ CallMap[CI] = Resources.size() - 1;
+ }
+
+ unsigned Size = Resources.size();
+ FirstUAV = FirstCBuffer = FirstSampler = Size;
+ uint32_t NextID = 0;
+ for (unsigned I = 0, E = Size; I != E; ++I) {
+ ResourceInfo &RI = Resources[I];
+ if (RI.isUAV() && FirstUAV == Size) {
+ FirstUAV = I;
+ NextID = 0;
+ } else if (RI.isCBuffer() && FirstCBuffer == Size) {
+ FirstCBuffer = I;
+ NextID = 0;
+ } if (RI.isSampler() && FirstSampler == Size) {
+ FirstSampler = I;
+ NextID = 0;
+ }
+
+ // Adjust the resource binding to use the next ID.
+ const ResourceInfo::ResourceBinding &Binding = RI.getBinding();
+ RI.bind(NextID++, Binding.Space, Binding.LowerBound, Binding.Size);
+ }
+}
+
+void DXILResourceMap::print(raw_ostream &OS) const {
+ for (unsigned I = 0, E = Resources.size(); I != E; ++I) {
+ OS << "Binding " << I << ":\n";
+ Resources[I].print(OS);
+ OS << "\n";
+ }
+
+ for (const auto &[CI, Index] : CallMap) {
+ OS << "Call bound to " << Index << ":";
+ CI->print(OS);
+ OS << "\n";
+ }
+}
+
//===----------------------------------------------------------------------===//
// DXILResourceAnalysis and DXILResourcePrinterPass
@@ -710,24 +765,14 @@ AnalysisKey DXILResourceAnalysis::Key;
DXILResourceMap DXILResourceAnalysis::run(Module &M,
ModuleAnalysisManager &AM) {
- DXILResourceMap Data;
- ResourceMapper(M, Data).mapResources();
+ DXILResourceMap Data = ResourceMapper(M).mapResources();
return Data;
}
PreservedAnalyses DXILResourcePrinterPass::run(Module &M,
ModuleAnalysisManager &AM) {
- DXILResourceMap &Data =
- AM.getResult<DXILResourceAnalysis>(M);
-
- for (const auto &[Handle, Info] : Data) {
- OS << "Binding for ";
- Handle->print(OS);
- OS << "\n";
- Info.print(OS);
- OS << "\n";
- }
-
+ DXILResourceMap &DRM = AM.getResult<DXILResourceAnalysis>(M);
+ DRM.print(OS);
return PreservedAnalyses::all();
}
@@ -745,8 +790,7 @@ void DXILResourceWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
}
bool DXILResourceWrapperPass::runOnModule(Module &M) {
- ResourceMap.reset(new DXILResourceMap());
- ResourceMapper(M, *ResourceMap).mapResources();
+ ResourceMap.reset(new DXILResourceMap(ResourceMapper(M).mapResources()));
return false;
}
@@ -757,13 +801,7 @@ void DXILResourceWrapperPass::print(raw_ostream &OS, const Module *) const {
OS << "No resource map has been built!\n";
return;
}
- for (const auto &[Handle, Info] : *ResourceMap) {
- OS << "Binding for ";
- Handle->print(OS);
- OS << "\n";
- Info.print(OS);
- OS << "\n";
- }
+ ResourceMap->print(OS);
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
diff --git a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
index 65802c6d1ff87a..b26a185423597d 100644
--- a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
+++ b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
@@ -3,55 +3,48 @@
@G = external constant <4 x float>, align 4
define void @test_typedbuffer() {
- ; RWBuffer<float4> Buf : register(u5, space3)
- %typed0 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
- @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0(
- i32 3, i32 5, i32 1, i32 0, i1 false)
- ; CHECK: Binding for %typed0
+ ; ByteAddressBuffer Buf : register(t8, space1)
+ %srv0 = call target("dx.RawBuffer", i8, 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: 3
- ; CHECK: Lower Bound: 5
+ ; CHECK: Space: 1
+ ; CHECK: Lower Bound: 8
; CHECK: Size: 1
- ; CHECK: Class: UAV
- ; CHECK: Kind: TypedBuffer
- ; CHECK: Globally Coherent: 0
- ; CHECK: HasCounter: 0
- ; CHECK: IsROV: 0
- ; CHECK: Element Type: f32
- ; CHECK: Element Count: 4
+ ; CHECK: Class: SRV
+ ; CHECK: Kind: RawBuffer
- ; RWBuffer<int> Buf : register(u7, space2)
- %typed1 = call target("dx.TypedBuffer", i32, 1, 0, 1)
- @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0t(
- i32 2, i32 7, i32 1, i32 0, i1 false)
- ; CHECK: Binding for %typed1
+ ; struct S { float4 a; uint4 b; };
+ ; StructuredBuffer<S> Buf : register(t2, space4)
+ %srv1 = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0)
+ @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: 2
- ; CHECK: Lower Bound: 7
+ ; CHECK: Space: 4
+ ; CHECK: Lower Bound: 2
; CHECK: Size: 1
- ; CHECK: Class: UAV
- ; CHECK: Kind: TypedBuffer
- ; CHECK: Globally Coherent: 0
- ; CHECK: HasCounter: 0
- ; CHECK: IsROV: 0
- ; CHECK: Element Type: i32
- ; CHECK: Element Count: 1
+ ; CHECK: Class: SRV
+ ; CHECK: Kind: StructuredBuffer
+ ; CHECK: Buffer Stride: 32
+ ; CHECK: Alignment: 4
; Buffer<uint4> Buf[24] : register(t3, space5)
- %typed2 = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)
+ %srv2 = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)
@llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_0_0t(
i32 5, i32 3, i32 24, i32 0, i1 false)
- ; CHECK: Binding for %typed2
+ ; CHECK: Binding [[SRV2:[0-9]+]]:
; CHECK: Symbol: ptr undef
; CHECK: Name: ""
; CHECK: Binding:
- ; CHECK: Record ID: 0
+ ; CHECK: Record ID: 2
; CHECK: Space: 5
; CHECK: Lower Bound: 3
; CHECK: Size: 24
@@ -60,67 +53,82 @@ define void @test_typedbuffer() {
; CHECK: Element Type: u32
; CHECK: Element Count: 4
- ret void
-}
+ ; RWBuffer<int> Buf : register(u7, space2)
+ %uav0 = call target("dx.TypedBuffer", i32, 1, 0, 1)
+ @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
+ ; CHECK: Lower Bound: 7
+ ; CHECK: Size: 1
+ ; CHECK: Class: UAV
+ ; CHECK: Kind: TypedBuffer
+ ; CHECK: Globally Coherent: 0
+ ; CHECK: HasCounter: 0
+ ; CHECK: IsROV: 0
+ ; CHECK: Element Type: i32
+ ; CHECK: Element Count: 1
-define void @test_structbuffer() {
- ; struct S { float4 a; uint4 b; };
- ; StructuredBuffer<S> Buf : register(t2, space4)
- %struct0 = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0)
- @llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
- i32 4, i32 2, i32 1, i32 0, i1 false)
- ; CHECK: Binding for %struct0
+ ; RWBuffer<float4> Buf : register(u5, space3)
+ %uav1 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+ @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: 4
- ; CHECK: Lower Bound: 2
+ ; CHECK: Space: 3
+ ; CHECK: Lower Bound: 5
; CHECK: Size: 1
- ; CHECK: Class: SRV
- ; CHECK: Kind: StructuredBuffer
- ; CHECK: Buffer Stride: 32
- ; CHECK: Alignment: 4
-
- ret void
-}
+ ; CHECK: Class: UAV
+ ; CHECK: Kind: TypedBuffer
+ ; CHECK: Globally Coherent: 0
+ ; CHECK: HasCounter: 0
+ ; CHECK: IsROV: 0
+ ; CHECK: Element Type: f32
+ ; CHECK: Element Count: 4
-define void @test_bytebuffer() {
- ; ByteAddressBuffer Buf : register(t8, space1)
- %byteaddr0 = call target("dx.RawBuffer", i8, 0, 0)
- @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t(
- i32 1, i32 8, i32 1, i32 0, i1 false)
- ; CHECK: Binding for %byteaddr0
+ ; RWBuffer<float4> BufferArray[10] : register(u0, space4)
+ ; RWBuffer<float4> Buf = BufferArray[0]
+ %uav2_1 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0(
+ i32 4, i32 0, i32 10, i32 0, i1 false)
+ ; RWBuffer<float4> Buf = BufferArray[5]
+ %uav2_2 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+ @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: 1
- ; CHECK: Lower Bound: 8
- ; CHECK: Size: 1
- ; CHECK: Class: SRV
- ; CHECK: Kind: RawBuffer
+ ; CHECK: Space: 4
+ ; CHECK: Lower Bound: 0
+ ; CHECK: Size: 10
+ ; CHECK: Class: UAV
+ ; CHECK: Kind: TypedBuffer
+ ; CHECK: Globally Coherent: 0
+ ; CHECK: HasCounter: 0
+ ; CHECK: IsROV: 0
+ ; CHECK: Element Type: f32
+ ; CHECK: Element Count: 4
+
+ ; CHECK-NOT: Binding {{[0-9]+}}:
ret void
}
-; Note: We need declarations for each handle.fromBinding in the same
-; order as they appear in source to ensure that we can put our CHECK
-; lines along side the thing they're checking.
-declare target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
- @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0t(
- i32, i32, i32, i32, i1) #0
-declare target("dx.TypedBuffer", i32, 1, 0, 1)
- @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0_1t(
- i32, i32, i32, i32, i1) #0
-declare target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)
- @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4i32_0_0_0t(
- i32, i32, i32, i32, i1) #0
-declare target("dx.RawBuffer", { <4 x float>, <4 x i32> }, 0, 0)
- @llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
- i32, i32, i32, i32, i1) #0
-declare target("dx.RawBuffer", i8, 0, 0)
- @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t(
- i32, i32, i32, i32, i1) #0
+; CHECK-DAG: Call bound to [[SRV0]]: %srv0 =
+; CHECK-DAG: Call bound to [[SRV1]]: %srv1 =
+; CHECK-DAG: Call bound to [[SRV2]]: %srv2 =
+; CHECK-DAG: Call bound to [[UAV0]]: %uav0 =
+; CHECK-DAG: Call bound to [[UAV1]]: %uav1 =
+; CHECK-DAG: Call bound to [[UAV2]]: %uav2_1 =
+; CHECK-DAG: Call bound to [[UAV2]]: %uav2_2 =
attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) }
>From 1820e792590c77e2670d523788d73dc43b9ecce3 Mon Sep 17 00:00:00 2001
From: Justin Bogner <mail at justinbogner.com>
Date: Wed, 21 Aug 2024 18:13:13 -0700
Subject: [PATCH 2/2] fix missing "else"
Created using spr 1.3.5-bogner
---
llvm/lib/Analysis/DXILResource.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 110a59331f15be..e07047e1313f8b 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -732,7 +732,7 @@ DXILResourceMap::DXILResourceMap(
} else if (RI.isCBuffer() && FirstCBuffer == Size) {
FirstCBuffer = I;
NextID = 0;
- } if (RI.isSampler() && FirstSampler == Size) {
+ } else if (RI.isSampler() && FirstSampler == Size) {
FirstSampler = I;
NextID = 0;
}
More information about the llvm-commits
mailing list