llvm-project/llvm/test/CodeGen/DirectX/CreateHandle-NURI.ll
Helena Kotas c69a70bf31
[DirectX] NonUniformResourceIndex lowering (#159608)
Introduces `llvm.{dx|svp}.resource.nonuniformindex` intrinsic that will be used when a resource index is not guaranteed to be uniform across threads (HLSL function NonUniformResourceIndex).

The DXIL lowering layer looks for this intrinsic call in the resource index calculation, makes sure it is reflected in the NonUniform flag on DXIL create handle ops (`dx.op.createHandle` and `dx.op.createHandleFromBinding`), and then removes it from the module.

Closes #155701
2025-09-22 21:37:56 -07:00

71 lines
3.0 KiB
LLVM

; RUN: opt -S -passes=dxil-op-lower %s | FileCheck %s
target triple = "dxil-pc-shadermodel6.0-compute"
@A.str = internal unnamed_addr constant [2 x i8] c"A\00", align 1
@B.str = internal unnamed_addr constant [2 x i8] c"A\00", align 1
declare i32 @some_val();
define void @test_buffers_with_nuri() {
%val = call i32 @some_val()
%foo = alloca i32, align 4
; RWBuffer<float> A[10];
;
; A[NonUniformResourceIndex(val)];
%nuri1 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val)
%res1 = call target("dx.TypedBuffer", float, 1, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 10, i32 %nuri1, ptr @A.str)
; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 %val, i1 true) #[[ATTR:.*]]
; CHECK-NOT: @llvm.dx.cast.handle
; CHECK-NOT: @llvm.dx.resource.nonuniformindex
; A[NonUniformResourceIndex(val + 1) % 10];
%add1 = add i32 %val, 1
%nuri2 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %add1)
%rem1 = urem i32 %nuri2, 10
%res2 = call target("dx.TypedBuffer", float, 1, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 10, i32 %rem1, ptr @A.str)
; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 %rem1, i1 true) #[[ATTR]]
; A[10 + 3 * NonUniformResourceIndex(GI)];
%mul1 = mul i32 %nuri1, 3
%add2 = add i32 %mul1, 10
%res3 = call target("dx.TypedBuffer", float, 1, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 10, i32 %add2, ptr @A.str)
; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 %add2, i1 true) #[[ATTR]]
; NonUniformResourceIndex value going through store & load - the flag is not going to get picked up:
%a = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val)
store i32 %a, ptr %foo
%b = load i32, ptr %foo
%res4 = call target("dx.TypedBuffer", float, 1, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 10, i32 %b, ptr @A.str)
; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 %b, i1 false) #[[ATTR]]
; NonUniformResourceIndex index value on a single resouce (not an array) - the flag is not going to get picked up:
;
; RWBuffer<float> B : register(u20);
; B[NonUniformResourceIndex(val)];
%nuri3 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val)
%res5 = call target("dx.TypedBuffer", float, 1, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 20, i32 0, i32 1, i32 %nuri1, ptr @B.str)
; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 %val, i1 false) #[[ATTR]]
; NonUniformResourceIndex on unrelated value - the call is removed:
; foo = NonUniformResourceIndex(val);
%nuri4 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val)
store i32 %nuri4, ptr %foo
; CHECK: store i32 %val, ptr %foo
; CHECK-NOT: @llvm.dx.resource.nonuniformindex
ret void
}
; CHECK: attributes #[[ATTR]] = {{{.*}} memory(read) {{.*}}}
attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) }