Skip to content

Commit 55fa1a5

Browse files
hekotamahesh-attarde
authored andcommitted
[HLSL] NonUniformResourceIndex implementation (llvm#160430)
Adds HLSL function `NonUniformResourceIndex` to `hlsl_intrinsics.h.` The function calls a builtin `__builtin_hlsl_resource_nonuniformindex` which gets translated to LLVM intrinsic `llvm.{dx|spv}.resource_nonuniformindex`. Closes llvm#157923
1 parent 28f44d1 commit 55fa1a5

File tree

5 files changed

+77
-0
lines changed

5 files changed

+77
-0
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4945,6 +4945,12 @@ def HLSLResourceHandleFromImplicitBinding : LangBuiltin<"HLSL_LANG"> {
49454945
let Prototype = "void(...)";
49464946
}
49474947

4948+
def HLSLResourceNonUniformIndex : LangBuiltin<"HLSL_LANG"> {
4949+
let Spellings = ["__builtin_hlsl_resource_nonuniformindex"];
4950+
let Attributes = [NoThrow];
4951+
let Prototype = "uint32_t(uint32_t)";
4952+
}
4953+
49484954
def HLSLAll : LangBuiltin<"HLSL_LANG"> {
49494955
let Spellings = ["__builtin_hlsl_all"];
49504956
let Attributes = [NoThrow, Const];

clang/lib/CodeGen/CGHLSLBuiltins.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,13 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
352352
SmallVector<Value *> Args{OrderID, SpaceOp, RangeOp, IndexOp, Name};
353353
return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
354354
}
355+
case Builtin::BI__builtin_hlsl_resource_nonuniformindex: {
356+
Value *IndexOp = EmitScalarExpr(E->getArg(0));
357+
llvm::Type *RetTy = ConvertType(E->getType());
358+
return Builder.CreateIntrinsic(
359+
RetTy, CGM.getHLSLRuntime().getNonUniformResourceIndexIntrinsic(),
360+
ArrayRef<Value *>{IndexOp});
361+
}
355362
case Builtin::BI__builtin_hlsl_all: {
356363
Value *Op0 = EmitScalarExpr(E->getArg(0));
357364
return Builder.CreateIntrinsic(

clang/lib/CodeGen/CGHLSLRuntime.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ class CGHLSLRuntime {
129129
resource_handlefrombinding)
130130
GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromImplicitBinding,
131131
resource_handlefromimplicitbinding)
132+
GENERATE_HLSL_INTRINSIC_FUNCTION(NonUniformResourceIndex,
133+
resource_nonuniformindex)
132134
GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter)
133135
GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync,
134136
group_memory_barrier_with_group_sync)

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,30 @@ constexpr int4 D3DCOLORtoUBYTE4(float4 V) {
422422
return __detail::d3d_color_to_ubyte4_impl(V);
423423
}
424424

425+
//===----------------------------------------------------------------------===//
426+
// NonUniformResourceIndex builtin
427+
//===----------------------------------------------------------------------===//
428+
429+
/// \fn uint NonUniformResourceIndex(uint I)
430+
/// \brief A compiler hint to indicate that a resource index varies across
431+
/// threads within a wave (i.e., it is non-uniform).
432+
/// \param I [in] Resource array index
433+
///
434+
/// The return value is the \Index parameter.
435+
///
436+
/// When indexing into an array of shader resources (e.g., textures, buffers),
437+
/// some GPU hardware and drivers require the compiler to know whether the index
438+
/// is uniform (same for all threads) or non-uniform (varies per thread).
439+
///
440+
/// Using NonUniformResourceIndex explicitly marks an index as non-uniform,
441+
/// disabling certain assumptions or optimizations that could lead to incorrect
442+
/// behavior when dynamically accessing resource arrays with non-uniform
443+
/// indices.
444+
445+
constexpr uint32_t NonUniformResourceIndex(uint32_t Index) {
446+
return __builtin_hlsl_resource_nonuniformindex(Index);
447+
}
448+
425449
//===----------------------------------------------------------------------===//
426450
// reflect builtin
427451
//===----------------------------------------------------------------------===//
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-compute -emit-llvm -disable-llvm-passes -o - %s \
2+
// RUN: | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
3+
// RUN: %clang_cc1 -finclude-default-header -triple spirv-pc-vulkan1.3-compute -emit-llvm -disable-llvm-passes -o - %s \
4+
// RUN: | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPV
5+
6+
RWBuffer<float> A[10];
7+
8+
[numthreads(4,1,1)]
9+
void main(uint GI : SV_GroupID) {
10+
// CHECK: %[[GI:.*]] = load i32, ptr %GI.addr
11+
// CHECK: %[[NURI_1:.*]] = call {{.*}} i32 @hlsl::NonUniformResourceIndex(unsigned int)(i32 noundef %[[GI]])
12+
// CHECK: call void @hlsl::RWBuffer<float>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
13+
// CHECK-SAME: (ptr {{.*}}, i32 noundef 0, i32 noundef 0, i32 noundef 10, i32 noundef %[[NURI_1]], ptr noundef @A.str)
14+
float a = A[NonUniformResourceIndex(GI)][0];
15+
16+
// CHECK: %[[GI:.*]] = load i32, ptr %GI.addr
17+
// CHECK: %[[ADD:.*]] = add i32 %[[GI]], 1
18+
// CHECK: %[[NURI_2:.*]] = call {{.*}} i32 @hlsl::NonUniformResourceIndex(unsigned int)(i32 noundef %[[ADD]])
19+
// CHECK: %[[MOD:.*]] = urem i32 %[[NURI_2]], 10
20+
// CHECK: call void @hlsl::RWBuffer<float>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
21+
// CHECK-SAME: (ptr {{.*}}, i32 noundef 0, i32 noundef 0, i32 noundef 10, i32 noundef %[[MOD]], ptr noundef @A.str)
22+
float b = A[NonUniformResourceIndex(GI + 1) % 10][0];
23+
24+
// CHECK: %[[GI:.*]] = load i32, ptr %GI.addr
25+
// CHECK: %[[NURI_3:.*]] = call {{.*}} i32 @hlsl::NonUniformResourceIndex(unsigned int)(i32 noundef %[[GI]])
26+
// CHECK: %[[MUL:.*]] = mul i32 3, %[[NURI_3]]
27+
// CHECK: %[[ADD2:.*]] = add i32 10, %[[MUL]]
28+
// CHECK: call void @hlsl::RWBuffer<float>::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*)
29+
// CHECK-SAME: (ptr {{.*}}, i32 noundef 0, i32 noundef 0, i32 noundef 10, i32 noundef %[[ADD2]], ptr noundef @A.str)
30+
float c = A[10 + 3 * NonUniformResourceIndex(GI)][0];
31+
A[0][0] = a + b + c;
32+
}
33+
34+
// CHECK: define {{.*}} i32 @hlsl::NonUniformResourceIndex(unsigned int)(i32 noundef %Index)
35+
// CHECK: %[[INDEX1:.*]] = load i32, ptr %Index.addr, align 4
36+
// DXIL: %[[INDEX2:.*]] = call i32 @llvm.dx.resource.nonuniformindex(i32 %[[INDEX1]])
37+
// SPV: %[[INDEX2:.*]] = call i32 @llvm.spv.resource.nonuniformindex(i32 %[[INDEX1]])
38+
// CHECK: ret i32 %[[INDEX2]]

0 commit comments

Comments
 (0)