|
| 1 | +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \ |
| 2 | +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s |
| 3 | + |
| 4 | +// This test verifies handling of multi-dimensional local arrays of resources |
| 5 | +// when used as a function argument and local variable. |
| 6 | + |
| 7 | +// CHECK: @_ZL1A = internal global %"class.hlsl::RWBuffer" poison, align 4 |
| 8 | +// CHECK: @_ZL1B = internal global %"class.hlsl::RWBuffer" poison, align 4 |
| 9 | + |
| 10 | +RWBuffer<float> A : register(u10); |
| 11 | +RWBuffer<float> B : register(u20); |
| 12 | +RWStructuredBuffer<float> Out; |
| 13 | + |
| 14 | +// NOTE: _ZN4hlsl8RWBufferIfEixEj is the subscript operator for RWBuffer<float> and |
| 15 | +// _ZN4hlsl18RWStructuredBufferIfEixEj is the subscript operator for RWStructuredBuffer<float> |
| 16 | + |
| 17 | +// CHECK: define {{.*}} float @_Z3fooA2_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([2 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %Arr) |
| 18 | +// CHECK-NEXT: entry: |
| 19 | +float foo(RWBuffer<float> Arr[2][2]) { |
| 20 | +// CHECK-NEXT: %[[Arr_1_Ptr:.*]] = getelementptr inbounds [2 x [2 x %"class.hlsl::RWBuffer"]], ptr %Arr, i32 0, i32 1 |
| 21 | +// CHECK-NEXT: %[[Arr_1_1_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %[[Arr_1_Ptr]], i32 0, i32 1 |
| 22 | +// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Arr_1_1_Ptr]], i32 noundef 0) |
| 23 | +// CHECK-NEXT: %[[Value:.*]] = load float, ptr %[[BufPtr]], align 4 |
| 24 | +// CHECK-NEXT: ret float %[[Value]] |
| 25 | + return Arr[1][1][0]; |
| 26 | +} |
| 27 | + |
| 28 | +// CHECK: define internal void @_Z4mainv() |
| 29 | +// CHECK-NEXT: entry: |
| 30 | +[numthreads(4,1,1)] |
| 31 | +void main() { |
| 32 | +// CHECK-NEXT: %L = alloca [2 x [2 x %"class.hlsl::RWBuffer"]], align 4 |
| 33 | +// CHECK-NEXT: %[[Tmp:.*]] = alloca [2 x [2 x %"class.hlsl::RWBuffer"]], align 4 |
| 34 | +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %L, ptr align 4 @_ZL1A, i32 4, i1 false) |
| 35 | +// CHECK-NEXT: %[[Ptr1:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %L, i32 1 |
| 36 | +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Ptr1]], ptr align 4 @_ZL1B, i32 4, i1 false) |
| 37 | +// CHECK-NEXT: %[[Ptr2:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %L, i32 1 |
| 38 | +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Ptr2]], ptr align 4 @_ZL1A, i32 4, i1 false) |
| 39 | +// CHECK-NEXT: %[[Ptr3:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %[[Ptr2]], i32 1 |
| 40 | +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Ptr3]], ptr align 4 @_ZL1B, i32 4, i1 false) |
| 41 | + RWBuffer<float> L[2][2] = { { A, B }, { A, B } }; |
| 42 | + |
| 43 | +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp]], ptr align 4 %L, i32 16, i1 false) |
| 44 | +// CHECK-NEXT: %[[ReturnedValue:.*]] = call {{.*}}float @_Z3fooA2_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([2 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %[[Tmp]]) |
| 45 | +// CHECK-NEXT: %[[OutBufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl18RWStructuredBufferIfEixEj(ptr {{.*}} @_ZL3Out, i32 noundef 0) |
| 46 | +// CHECK-NEXT: store float %[[ReturnedValue]], ptr %[[OutBufPtr]], align 4 |
| 47 | +// CHECK-NEXT: ret void |
| 48 | + Out[0] = foo(L); |
| 49 | +} |
0 commit comments