Skip to content

Commit a2935b7

Browse files
committed
Address Comments
1 parent cf26a2e commit a2935b7

File tree

3 files changed

+35
-244
lines changed

3 files changed

+35
-244
lines changed

llvm/include/llvm/Analysis/DXILResource.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,13 @@ class DXILResourceMap {
446446
/// Analyze and populate the directions of the resource counters.
447447
void populateCounterDirections(Module &M);
448448

449+
/// Resolves a resource handle into a vector of ResourceInfos that
450+
/// represent the possible unique creations of the handle. Certain cases are
451+
/// ambiguous so multiple creation instructions may be returned. The resulting
452+
/// ResourceInfo can be used to depuplicate unique handles that
453+
/// reference the same resource
454+
SmallVector<dxil::ResourceInfo *> findByUse(const Value *Key);
455+
449456
public:
450457
using iterator = SmallVector<dxil::ResourceInfo>::iterator;
451458
using const_iterator = SmallVector<dxil::ResourceInfo>::const_iterator;
@@ -462,13 +469,6 @@ class DXILResourceMap {
462469
return Pos == CallMap.end() ? Infos.end() : (Infos.begin() + Pos->second);
463470
}
464471

465-
/// Resolves a resource handle into a vector of ResourceInfos that
466-
/// represent the possible unique creations of the handle. Certain cases are
467-
/// ambiguous so multiple creation instructions may be returned. The resulting
468-
/// ResourceInfo can be used to depuplicate unique handles that
469-
/// reference the same resource
470-
SmallVector<dxil::ResourceInfo *> findByUse(const Value *Key);
471-
472472
const_iterator find(const CallInst *Key) const {
473473
auto Pos = CallMap.find(Key);
474474
return Pos == CallMap.end() ? Infos.end() : (Infos.begin() + Pos->second);

llvm/test/Analysis/DXILResource/buffer-frombinding.ll

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
define void @test_typedbuffer() {
66
; ByteAddressBuffer Buf : register(t8, space1)
77
%srv0 = call target("dx.RawBuffer", void, 0, 0)
8-
@llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
9-
i32 1, i32 8, i32 1, i32 0, i1 false)
8+
@llvm.dx.resource.handlefrombinding(i32 1, i32 8, i32 1, i32 0, i1 false)
109
; CHECK: Resource [[SRV0:[0-9]+]]:
1110
; CHECK: Binding:
1211
; CHECK: Record ID: 0
@@ -19,8 +18,7 @@ define void @test_typedbuffer() {
1918
; struct S { float4 a; uint4 b; };
2019
; StructuredBuffer<S> Buf : register(t2, space4)
2120
%srv1 = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0)
22-
@llvm.dx.resource.handlefrombinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
23-
i32 4, i32 2, i32 1, i32 0, i1 false)
21+
@llvm.dx.resource.handlefrombinding(i32 4, i32 2, i32 1, i32 0, i1 false)
2422
; CHECK: Resource [[SRV1:[0-9]+]]:
2523
; CHECK: Binding:
2624
; CHECK: Record ID: 1
@@ -34,8 +32,7 @@ define void @test_typedbuffer() {
3432

3533
; Buffer<uint4> Buf[24] : register(t3, space5)
3634
%srv2 = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)
37-
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_0_0t(
38-
i32 5, i32 3, i32 24, i32 0, i1 false)
35+
@llvm.dx.resource.handlefrombinding(i32 5, i32 3, i32 24, i32 0, i1 false)
3936
; CHECK: Resource [[SRV2:[0-9]+]]:
4037
; CHECK: Binding:
4138
; CHECK: Record ID: 2
@@ -49,8 +46,7 @@ define void @test_typedbuffer() {
4946

5047
; RWBuffer<int> Buf : register(u7, space2)
5148
%uav0 = call target("dx.TypedBuffer", i32, 1, 0, 1)
52-
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_1_0t(
53-
i32 2, i32 7, i32 1, i32 0, i1 false)
49+
@llvm.dx.resource.handlefrombinding(i32 2, i32 7, i32 1, i32 0, i1 false)
5450
; CHECK: Resource [[UAV0:[0-9]+]]:
5551
; CHECK: Binding:
5652
; CHECK: Record ID: 0
@@ -67,8 +63,7 @@ define void @test_typedbuffer() {
6763

6864
; RWBuffer<float4> Buf : register(u5, space3)
6965
%uav1 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
70-
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0(
71-
i32 3, i32 5, i32 1, i32 0, i1 false)
66+
@llvm.dx.resource.handlefrombinding(i32 3, i32 5, i32 1, i32 0, i1 false)
7267
call i32 @llvm.dx.resource.updatecounter(target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav1, i8 -1)
7368
; CHECK: Resource [[UAV1:[0-9]+]]:
7469
; CHECK: Binding:
@@ -87,12 +82,10 @@ define void @test_typedbuffer() {
8782
; RWBuffer<float4> BufferArray[10] : register(u0, space4)
8883
; RWBuffer<float4> Buf = BufferArray[0]
8984
%uav2_1 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
90-
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0(
91-
i32 4, i32 0, i32 10, i32 0, i1 false)
85+
@llvm.dx.resource.handlefrombinding(i32 4, i32 0, i32 10, i32 0, i1 false)
9286
; RWBuffer<float4> Buf = BufferArray[5]
9387
%uav2_2 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
94-
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0(
95-
i32 4, i32 0, i32 10, i32 5, i1 false)
88+
@llvm.dx.resource.handlefrombinding(i32 4, i32 0, i32 10, i32 5, i1 false)
9689
call i32 @llvm.dx.resource.updatecounter(target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav2_2, i8 1)
9790
; CHECK: Resource [[UAV2:[0-9]+]]:
9891
; CHECK: Binding:
@@ -108,8 +101,27 @@ define void @test_typedbuffer() {
108101
; CHECK: Element Type: f32
109102
; CHECK: Element Count: 4
110103

104+
; RWBuffer<float4> Buf : register(u0, space5)
105+
%uav3 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
106+
@llvm.dx.resource.handlefrombinding(i32 5, i32 0, i32 1, i32 0, i1 false)
107+
call i32 @llvm.dx.resource.updatecounter(target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav3, i8 -1)
108+
call i32 @llvm.dx.resource.updatecounter(target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav3, i8 1)
109+
; CHECK: Resource [[UAV3:[0-9]+]]:
110+
; CHECK: Binding:
111+
; CHECK: Record ID: 3
112+
; CHECK: Space: 5
113+
; CHECK: Lower Bound: 0
114+
; CHECK: Size: 1
115+
; CHECK: Globally Coherent: 0
116+
; CHECK: Counter Direction: Invalid
117+
; CHECK: Class: UAV
118+
; CHECK: Kind: TypedBuffer
119+
; CHECK: IsROV: 0
120+
; CHECK: Element Type: f32
121+
; CHECK: Element Count: 4
122+
111123
%cb0 = call target("dx.CBuffer", {float})
112-
@llvm.dx.resource.handlefrombinding(i32 1, i32 0, i32 1, i32 0, i1 false)
124+
@llvm.dx.resource.handlefrombinding(i32 1, i32 0, i32 1, i32 0, i1 false)
113125
; CHECK: Resource [[CB0:[0-9]+]]:
114126
; CHECK: Binding:
115127
; CHECK: Record ID: 0
@@ -121,7 +133,7 @@ define void @test_typedbuffer() {
121133
; CHECK: CBuffer size: 4
122134

123135
%cb1 = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
124-
@llvm.dx.resource.handlefrombinding(i32 1, i32 8, i32 1, i32 0, i1 false)
136+
@llvm.dx.resource.handlefrombinding(i32 1, i32 8, i32 1, i32 0, i1 false)
125137
; CHECK: Resource [[CB1:[0-9]+]]:
126138
; CHECK: Binding:
127139
; CHECK: Record ID: 1

llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp

Lines changed: 0 additions & 221 deletions
Original file line numberDiff line numberDiff line change
@@ -53,227 +53,6 @@ class UniqueResourceFromUseTest : public testing::Test {
5353
}
5454
};
5555

56-
TEST_F(UniqueResourceFromUseTest, TestTrivialUse) {
57-
StringRef Assembly = R"(
58-
define void @main() {
59-
entry:
60-
%handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, i1 false)
61-
call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
62-
call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
63-
ret void
64-
}
65-
66-
declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
67-
)";
68-
69-
auto M = parseAsm(Assembly);
70-
71-
DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);
72-
for (const Function &F : M->functions()) {
73-
if (F.getName() != "a.func") {
74-
continue;
75-
}
76-
77-
unsigned CalledResources = 0;
78-
79-
for (const User *U : F.users()) {
80-
const CallInst *CI = cast<CallInst>(U);
81-
const Value *Handle = CI->getArgOperand(0);
82-
const auto Bindings = DRM.findByUse(Handle);
83-
ASSERT_EQ(Bindings.size(), 1u)
84-
<< "Handle should resolve into one resource";
85-
86-
auto Binding = Bindings[0]->getBinding();
87-
EXPECT_EQ(0u, Binding.RecordID);
88-
EXPECT_EQ(1u, Binding.Space);
89-
EXPECT_EQ(2u, Binding.LowerBound);
90-
EXPECT_EQ(3u, Binding.Size);
91-
92-
CalledResources++;
93-
}
94-
95-
EXPECT_EQ(2u, CalledResources)
96-
<< "Expected 2 resolved call to create resource";
97-
}
98-
}
99-
100-
TEST_F(UniqueResourceFromUseTest, TestIndirectUse) {
101-
StringRef Assembly = R"(
102-
define void @foo() {
103-
%handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, i1 false)
104-
%handle2 = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %handle)
105-
%handle3 = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %handle2)
106-
%handle4 = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %handle3)
107-
call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle4)
108-
ret void
109-
}
110-
111-
declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
112-
declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %handle)
113-
)";
114-
115-
auto M = parseAsm(Assembly);
116-
117-
DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);
118-
for (const Function &F : M->functions()) {
119-
if (F.getName() != "a.func") {
120-
continue;
121-
}
122-
123-
unsigned CalledResources = 0;
124-
125-
for (const User *U : F.users()) {
126-
const CallInst *CI = cast<CallInst>(U);
127-
const Value *Handle = CI->getArgOperand(0);
128-
const auto Bindings = DRM.findByUse(Handle);
129-
ASSERT_EQ(Bindings.size(), 1u)
130-
<< "Handle should resolve into one resource";
131-
132-
auto Binding = Bindings[0]->getBinding();
133-
EXPECT_EQ(0u, Binding.RecordID);
134-
EXPECT_EQ(1u, Binding.Space);
135-
EXPECT_EQ(2u, Binding.LowerBound);
136-
EXPECT_EQ(3u, Binding.Size);
137-
138-
CalledResources++;
139-
}
140-
141-
EXPECT_EQ(1u, CalledResources)
142-
<< "Expected 1 resolved call to create resource";
143-
}
144-
}
145-
146-
TEST_F(UniqueResourceFromUseTest, TestAmbigousIndirectUse) {
147-
StringRef Assembly = R"(
148-
define void @foo() {
149-
%foo = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 1, i32 1, i32 1, i1 false)
150-
%bar = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 2, i32 2, i32 2, i1 false)
151-
%baz = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 3, i32 3, i32 3, i32 3, i1 false)
152-
%bat = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 4, i32 4, i32 4, i32 4, i1 false)
153-
%a = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %foo, target("dx.RawBuffer", float, 1, 0) %bar)
154-
%b = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %baz, target("dx.RawBuffer", float, 1, 0) %bat)
155-
%handle = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %a, target("dx.RawBuffer", float, 1, 0) %b)
156-
call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
157-
ret void
158-
}
159-
160-
declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
161-
declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %x, target("dx.RawBuffer", float, 1, 0) %y)
162-
)";
163-
164-
auto M = parseAsm(Assembly);
165-
166-
DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);
167-
for (const Function &F : M->functions()) {
168-
if (F.getName() != "a.func") {
169-
continue;
170-
}
171-
172-
unsigned CalledResources = 0;
173-
174-
for (const User *U : F.users()) {
175-
const CallInst *CI = cast<CallInst>(U);
176-
const Value *Handle = CI->getArgOperand(0);
177-
const auto Bindings = DRM.findByUse(Handle);
178-
ASSERT_EQ(Bindings.size(), 4u)
179-
<< "Handle should resolve into four resources";
180-
181-
auto Binding = Bindings[0]->getBinding();
182-
EXPECT_EQ(0u, Binding.RecordID);
183-
EXPECT_EQ(1u, Binding.Space);
184-
EXPECT_EQ(1u, Binding.LowerBound);
185-
EXPECT_EQ(1u, Binding.Size);
186-
187-
Binding = Bindings[1]->getBinding();
188-
EXPECT_EQ(1u, Binding.RecordID);
189-
EXPECT_EQ(2u, Binding.Space);
190-
EXPECT_EQ(2u, Binding.LowerBound);
191-
EXPECT_EQ(2u, Binding.Size);
192-
193-
Binding = Bindings[2]->getBinding();
194-
EXPECT_EQ(2u, Binding.RecordID);
195-
EXPECT_EQ(3u, Binding.Space);
196-
EXPECT_EQ(3u, Binding.LowerBound);
197-
EXPECT_EQ(3u, Binding.Size);
198-
199-
Binding = Bindings[3]->getBinding();
200-
EXPECT_EQ(3u, Binding.RecordID);
201-
EXPECT_EQ(4u, Binding.Space);
202-
EXPECT_EQ(4u, Binding.LowerBound);
203-
EXPECT_EQ(4u, Binding.Size);
204-
205-
CalledResources++;
206-
}
207-
208-
EXPECT_EQ(1u, CalledResources)
209-
<< "Expected 1 resolved call to create resource";
210-
}
211-
}
212-
213-
TEST_F(UniqueResourceFromUseTest, TestConditionalUse) {
214-
StringRef Assembly = R"(
215-
define void @foo(i32 %n) {
216-
entry:
217-
%x = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 1, i32 1, i32 1, i1 false)
218-
%y = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 4, i32 4, i32 4, i32 4, i1 false)
219-
%cond = icmp eq i32 %n, 0
220-
br i1 %cond, label %bb.true, label %bb.false
221-
222-
bb.true:
223-
%handle_t = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %x)
224-
br label %bb.exit
225-
226-
bb.false:
227-
%handle_f = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %y)
228-
br label %bb.exit
229-
230-
bb.exit:
231-
%handle = phi target("dx.RawBuffer", float, 1, 0) [ %handle_t, %bb.true ], [ %handle_f, %bb.false ]
232-
call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
233-
ret void
234-
}
235-
236-
declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
237-
declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %x)
238-
)";
239-
240-
auto M = parseAsm(Assembly);
241-
242-
DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);
243-
for (const Function &F : M->functions()) {
244-
if (F.getName() != "a.func") {
245-
continue;
246-
}
247-
248-
unsigned CalledResources = 0;
249-
250-
for (const User *U : F.users()) {
251-
const CallInst *CI = cast<CallInst>(U);
252-
const Value *Handle = CI->getArgOperand(0);
253-
const auto Bindings = DRM.findByUse(Handle);
254-
ASSERT_EQ(Bindings.size(), 2u)
255-
<< "Handle should resolve into four resources";
256-
257-
auto Binding = Bindings[0]->getBinding();
258-
EXPECT_EQ(0u, Binding.RecordID);
259-
EXPECT_EQ(1u, Binding.Space);
260-
EXPECT_EQ(1u, Binding.LowerBound);
261-
EXPECT_EQ(1u, Binding.Size);
262-
263-
Binding = Bindings[1]->getBinding();
264-
EXPECT_EQ(1u, Binding.RecordID);
265-
EXPECT_EQ(4u, Binding.Space);
266-
EXPECT_EQ(4u, Binding.LowerBound);
267-
EXPECT_EQ(4u, Binding.Size);
268-
269-
CalledResources++;
270-
}
271-
272-
EXPECT_EQ(1u, CalledResources)
273-
<< "Expected 1 resolved call to create resource";
274-
}
275-
}
276-
27756
// Test that several calls to decrement on the same resource don't raise a
27857
// Diagnositic and resolves to a single decrement entry
27958
TEST_F(UniqueResourceFromUseTest, TestResourceCounterDecrement) {

0 commit comments

Comments
 (0)