Skip to content

Commit f12fb2f

Browse files
authored
[HLSL] Analyze updateCounter usage (#135669)
Fixes #135667 Analyze and annotate `ResourceInfo` with the derived direction of calls to updateCounter (if any). This change only sets the value. Any diagnostics that should be raised must be done somewhere else.
1 parent dd9f92c commit f12fb2f

File tree

4 files changed

+195
-207
lines changed

4 files changed

+195
-207
lines changed

llvm/include/llvm/Analysis/DXILResource.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,19 @@ class DXILResourceMap {
457457
unsigned FirstCBuffer = 0;
458458
unsigned FirstSampler = 0;
459459

460-
/// Populate the map given the resource binding calls in the given module.
460+
/// Populate all the resource instance data.
461461
void populate(Module &M, DXILResourceTypeMap &DRTM);
462+
/// Populate the map given the resource binding calls in the given module.
463+
void populateResourceInfos(Module &M, DXILResourceTypeMap &DRTM);
464+
/// Analyze and populate the directions of the resource counters.
465+
void populateCounterDirections(Module &M);
466+
467+
/// Resolves a resource handle into a vector of ResourceInfos that
468+
/// represent the possible unique creations of the handle. Certain cases are
469+
/// ambiguous so multiple creation instructions may be returned. The resulting
470+
/// ResourceInfo can be used to depuplicate unique handles that
471+
/// reference the same resource
472+
SmallVector<dxil::ResourceInfo *> findByUse(const Value *Key);
462473

463474
public:
464475
using iterator = SmallVector<dxil::ResourceInfo>::iterator;
@@ -476,13 +487,6 @@ class DXILResourceMap {
476487
return Pos == CallMap.end() ? Infos.end() : (Infos.begin() + Pos->second);
477488
}
478489

479-
/// Resolves a resource handle into a vector of ResourceInfos that
480-
/// represent the possible unique creations of the handle. Certain cases are
481-
/// ambiguous so multiple creation instructions may be returned. The resulting
482-
/// ResourceInfo can be used to depuplicate unique handles that
483-
/// reference the same resource
484-
SmallVector<dxil::ResourceInfo> findByUse(const Value *Key) const;
485-
486490
const_iterator find(const CallInst *Key) const {
487491
auto Pos = CallMap.find(Key);
488492
return Pos == CallMap.end() ? Infos.end() : (Infos.begin() + Pos->second);

llvm/lib/Analysis/DXILResource.cpp

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -697,8 +697,12 @@ bool DXILResourceTypeMap::invalidate(Module &M, const PreservedAnalyses &PA,
697697
}
698698

699699
//===----------------------------------------------------------------------===//
700+
static bool isUpdateCounterIntrinsic(Function &F) {
701+
return F.getIntrinsicID() == Intrinsic::dx_resource_updatecounter;
702+
}
700703

701-
void DXILResourceMap::populate(Module &M, DXILResourceTypeMap &DRTM) {
704+
void DXILResourceMap::populateResourceInfos(Module &M,
705+
DXILResourceTypeMap &DRTM) {
702706
SmallVector<std::tuple<CallInst *, ResourceInfo, ResourceTypeInfo>> CIToInfos;
703707

704708
for (Function &F : M.functions()) {
@@ -777,6 +781,48 @@ void DXILResourceMap::populate(Module &M, DXILResourceTypeMap &DRTM) {
777781
}
778782
}
779783

784+
void DXILResourceMap::populateCounterDirections(Module &M) {
785+
for (Function &F : M.functions()) {
786+
if (!isUpdateCounterIntrinsic(F))
787+
continue;
788+
789+
LLVM_DEBUG(dbgs() << "Update Counter Function: " << F.getName() << "\n");
790+
791+
for (const User *U : F.users()) {
792+
const CallInst *CI = dyn_cast<CallInst>(U);
793+
assert(CI && "Users of dx_resource_updateCounter must be call instrs");
794+
795+
// Determine if the use is an increment or decrement
796+
Value *CountArg = CI->getArgOperand(1);
797+
ConstantInt *CountValue = cast<ConstantInt>(CountArg);
798+
int64_t CountLiteral = CountValue->getSExtValue();
799+
800+
// 0 is an unknown direction and shouldn't result in an insert
801+
if (CountLiteral == 0)
802+
continue;
803+
804+
ResourceCounterDirection Direction = ResourceCounterDirection::Decrement;
805+
if (CountLiteral > 0)
806+
Direction = ResourceCounterDirection::Increment;
807+
808+
// Collect all potential creation points for the handle arg
809+
Value *HandleArg = CI->getArgOperand(0);
810+
SmallVector<ResourceInfo *> RBInfos = findByUse(HandleArg);
811+
for (ResourceInfo *RBInfo : RBInfos) {
812+
if (RBInfo->CounterDirection == ResourceCounterDirection::Unknown)
813+
RBInfo->CounterDirection = Direction;
814+
else if (RBInfo->CounterDirection != Direction)
815+
RBInfo->CounterDirection = ResourceCounterDirection::Invalid;
816+
}
817+
}
818+
}
819+
}
820+
821+
void DXILResourceMap::populate(Module &M, DXILResourceTypeMap &DRTM) {
822+
populateResourceInfos(M, DRTM);
823+
populateCounterDirections(M);
824+
}
825+
780826
void DXILResourceMap::print(raw_ostream &OS, DXILResourceTypeMap &DRTM,
781827
const DataLayout &DL) const {
782828
for (unsigned I = 0, E = Infos.size(); I != E; ++I) {
@@ -793,10 +839,9 @@ void DXILResourceMap::print(raw_ostream &OS, DXILResourceTypeMap &DRTM,
793839
}
794840
}
795841

796-
SmallVector<dxil::ResourceInfo>
797-
DXILResourceMap::findByUse(const Value *Key) const {
842+
SmallVector<dxil::ResourceInfo *> DXILResourceMap::findByUse(const Value *Key) {
798843
if (const PHINode *Phi = dyn_cast<PHINode>(Key)) {
799-
SmallVector<dxil::ResourceInfo> Children;
844+
SmallVector<dxil::ResourceInfo *> Children;
800845
for (const Value *V : Phi->operands()) {
801846
Children.append(findByUse(V));
802847
}
@@ -810,9 +855,9 @@ DXILResourceMap::findByUse(const Value *Key) const {
810855
switch (CI->getIntrinsicID()) {
811856
// Found the create, return the binding
812857
case Intrinsic::dx_resource_handlefrombinding: {
813-
const auto *It = find(CI);
814-
assert(It != Infos.end() && "HandleFromBinding must be in resource map");
815-
return {*It};
858+
auto Pos = CallMap.find(CI);
859+
assert(Pos != CallMap.end() && "HandleFromBinding must be in resource map");
860+
return {&Infos[Pos->second]};
816861
}
817862
default:
818863
break;
@@ -821,7 +866,7 @@ DXILResourceMap::findByUse(const Value *Key) const {
821866
// Check if any of the parameters are the resource we are following. If so
822867
// keep searching. If none of them are return an empty list
823868
const Type *UseType = CI->getType();
824-
SmallVector<dxil::ResourceInfo> Children;
869+
SmallVector<dxil::ResourceInfo *> Children;
825870
for (const Value *V : CI->args()) {
826871
if (V->getType() != UseType)
827872
continue;

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

Lines changed: 32 additions & 18 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,16 +63,16 @@ 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)
67+
call i32 @llvm.dx.resource.updatecounter(target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav1, i8 -1)
7268
; CHECK: Resource [[UAV1:[0-9]+]]:
7369
; CHECK: Binding:
7470
; CHECK: Record ID: 1
7571
; CHECK: Space: 3
7672
; CHECK: Lower Bound: 5
7773
; CHECK: Size: 1
7874
; CHECK: Globally Coherent: 0
79-
; CHECK: Counter Direction: Unknown
75+
; CHECK: Counter Direction: Decrement
8076
; CHECK: Class: UAV
8177
; CHECK: Kind: TypedBuffer
8278
; CHECK: IsROV: 0
@@ -86,28 +82,46 @@ define void @test_typedbuffer() {
8682
; RWBuffer<float4> BufferArray[10] : register(u0, space4)
8783
; RWBuffer<float4> Buf = BufferArray[0]
8884
%uav2_1 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
89-
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0(
90-
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)
9186
; RWBuffer<float4> Buf = BufferArray[5]
9287
%uav2_2 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
93-
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0(
94-
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)
89+
call i32 @llvm.dx.resource.updatecounter(target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav2_2, i8 1)
9590
; CHECK: Resource [[UAV2:[0-9]+]]:
9691
; CHECK: Binding:
9792
; CHECK: Record ID: 2
9893
; CHECK: Space: 4
9994
; CHECK: Lower Bound: 0
10095
; CHECK: Size: 10
10196
; CHECK: Globally Coherent: 0
102-
; CHECK: Counter Direction: Unknown
97+
; CHECK: Counter Direction: Increment
98+
; CHECK: Class: UAV
99+
; CHECK: Kind: TypedBuffer
100+
; CHECK: IsROV: 0
101+
; CHECK: Element Type: f32
102+
; CHECK: Element Count: 4
103+
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
103117
; CHECK: Class: UAV
104118
; CHECK: Kind: TypedBuffer
105119
; CHECK: IsROV: 0
106120
; CHECK: Element Type: f32
107121
; CHECK: Element Count: 4
108122

109123
%cb0 = call target("dx.CBuffer", {float})
110-
@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)
111125
; CHECK: Resource [[CB0:[0-9]+]]:
112126
; CHECK: Binding:
113127
; CHECK: Record ID: 0
@@ -119,7 +133,7 @@ define void @test_typedbuffer() {
119133
; CHECK: CBuffer size: 4
120134

121135
%cb1 = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
122-
@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)
123137
; CHECK: Resource [[CB1:[0-9]+]]:
124138
; CHECK: Binding:
125139
; CHECK: Record ID: 1

0 commit comments

Comments
 (0)