diff options
Diffstat (limited to 'clang/test/CodeGenHLSL/resources')
27 files changed, 1142 insertions, 815 deletions
diff --git a/clang/test/CodeGenHLSL/resources/AppendStructuredBuffer-elementtype.hlsl b/clang/test/CodeGenHLSL/resources/AppendStructuredBuffer-elementtype.hlsl index 28d9a4b8e596..094006fbd0eb 100644 --- a/clang/test/CodeGenHLSL/resources/AppendStructuredBuffer-elementtype.hlsl +++ b/clang/test/CodeGenHLSL/resources/AppendStructuredBuffer-elementtype.hlsl @@ -1,54 +1,54 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=DXIL
-// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPV
-
-struct MyStruct {
- float4 a;
- int2 b;
-};
-
-// DXIL: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.0" = type { target("dx.RawBuffer", i16, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.1" = type { target("dx.RawBuffer", i32, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.3" = type { target("dx.RawBuffer", i64, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.5" = type { target("dx.RawBuffer", half, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.6" = type { target("dx.RawBuffer", float, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.7" = type { target("dx.RawBuffer", double, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.8" = type { target("dx.RawBuffer", <4 x i16>, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.9" = type { target("dx.RawBuffer", <3 x i32>, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.10" = type { target("dx.RawBuffer", <2 x half>, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.11" = type { target("dx.RawBuffer", <3 x float>, 1, 0)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.12" = type { target("dx.RawBuffer", %struct.MyStruct, 1, 0)
-// DXIL: %struct.MyStruct = type <{ <4 x float>, <2 x i32> }>
-// DXIL: %"class.hlsl::AppendStructuredBuffer.13" = type { target("dx.RawBuffer", i32, 1, 0)
-// SPV: %"class.hlsl::AppendStructuredBuffer.13" = type { target("spirv.VulkanBuffer", [0 x i32], 12, 1)
-// DXIL: %"class.hlsl::AppendStructuredBuffer.14" = type { target("dx.RawBuffer", <4 x i32>, 1, 0)
-// SPV: %"class.hlsl::AppendStructuredBuffer.14" = type { target("spirv.VulkanBuffer", [0 x <4 x i32>], 12, 1)
-
-AppendStructuredBuffer<int16_t> BufI16;
-AppendStructuredBuffer<uint16_t> BufU16;
-AppendStructuredBuffer<int> BufI32;
-AppendStructuredBuffer<uint> BufU32;
-AppendStructuredBuffer<int64_t> BufI64;
-AppendStructuredBuffer<uint64_t> BufU64;
-AppendStructuredBuffer<half> BufF16;
-AppendStructuredBuffer<float> BufF32;
-AppendStructuredBuffer<double> BufF64;
-AppendStructuredBuffer< vector<int16_t, 4> > BufI16x4;
-AppendStructuredBuffer< vector<uint, 3> > BufU32x3;
-AppendStructuredBuffer<half2> BufF16x2;
-AppendStructuredBuffer<float3> BufF32x3;
-// TODO: AppendStructuredBuffer<snorm half> BufSNormF16;
-// TODO: AppendStructuredBuffer<unorm half> BufUNormF16;
-// TODO: AppendStructuredBuffer<snorm float> BufSNormF32;
-// TODO: AppendStructuredBuffer<unorm float> BufUNormF32;
-// TODO: AppendStructuredBuffer<snorm double> BufSNormF64;
-// TODO: AppendStructuredBuffer<unorm double> BufUNormF64;
-AppendStructuredBuffer<MyStruct> BufMyStruct;
-AppendStructuredBuffer<bool> BufBool;
-AppendStructuredBuffer<bool4> BufBoolVec;
-
-[numthreads(1,1,1)]
-void main(int GI : SV_GroupIndex) {
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=DXIL +// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPV + +struct MyStruct { + float4 a; + int2 b; +}; + +// DXIL: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.0" = type { target("dx.RawBuffer", i16, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.1" = type { target("dx.RawBuffer", i32, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.3" = type { target("dx.RawBuffer", i64, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.5" = type { target("dx.RawBuffer", half, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.6" = type { target("dx.RawBuffer", float, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.7" = type { target("dx.RawBuffer", double, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.8" = type { target("dx.RawBuffer", <4 x i16>, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.9" = type { target("dx.RawBuffer", <3 x i32>, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.10" = type { target("dx.RawBuffer", <2 x half>, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.11" = type { target("dx.RawBuffer", <3 x float>, 1, 0) +// DXIL: %"class.hlsl::AppendStructuredBuffer.12" = type { target("dx.RawBuffer", %struct.MyStruct, 1, 0) +// DXIL: %struct.MyStruct = type <{ <4 x float>, <2 x i32> }> +// DXIL: %"class.hlsl::AppendStructuredBuffer.13" = type { target("dx.RawBuffer", i32, 1, 0) +// SPV: %"class.hlsl::AppendStructuredBuffer.13" = type { target("spirv.VulkanBuffer", [0 x i32], 12, 1) +// DXIL: %"class.hlsl::AppendStructuredBuffer.14" = type { target("dx.RawBuffer", <4 x i32>, 1, 0) +// SPV: %"class.hlsl::AppendStructuredBuffer.14" = type { target("spirv.VulkanBuffer", [0 x <4 x i32>], 12, 1) + +AppendStructuredBuffer<int16_t> BufI16; +AppendStructuredBuffer<uint16_t> BufU16; +AppendStructuredBuffer<int> BufI32; +AppendStructuredBuffer<uint> BufU32; +AppendStructuredBuffer<int64_t> BufI64; +AppendStructuredBuffer<uint64_t> BufU64; +AppendStructuredBuffer<half> BufF16; +AppendStructuredBuffer<float> BufF32; +AppendStructuredBuffer<double> BufF64; +AppendStructuredBuffer< vector<int16_t, 4> > BufI16x4; +AppendStructuredBuffer< vector<uint, 3> > BufU32x3; +AppendStructuredBuffer<half2> BufF16x2; +AppendStructuredBuffer<float3> BufF32x3; +// TODO: AppendStructuredBuffer<snorm half> BufSNormF16; +// TODO: AppendStructuredBuffer<unorm half> BufUNormF16; +// TODO: AppendStructuredBuffer<snorm float> BufSNormF32; +// TODO: AppendStructuredBuffer<unorm float> BufUNormF32; +// TODO: AppendStructuredBuffer<snorm double> BufSNormF64; +// TODO: AppendStructuredBuffer<unorm double> BufUNormF64; +AppendStructuredBuffer<MyStruct> BufMyStruct; +AppendStructuredBuffer<bool> BufBool; +AppendStructuredBuffer<bool4> BufBoolVec; + +[numthreads(1,1,1)] +void main(int GI : SV_GroupIndex) { +} diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl index 3a8d2c03e173..5db156ed325d 100644 --- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl +++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl @@ -70,7 +70,7 @@ export void foo() { // CHECK: define linkonce_odr hidden void @_ZN4hlsl17ByteAddressBufferC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, // CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) // CHECK-DXIL: %[[HANDLE:.*]] = call target("dx.RawBuffer", i8, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t( -// CHECK-DXIL-SAME: i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i1 false, ptr %{{.*}}) +// CHECK-DXIL-SAME: i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr %{{.*}}) // CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]], ptr %__handle, align 4 @@ -79,7 +79,7 @@ export void foo() { // CHECK: define linkonce_odr hidden void @_ZN4hlsl19RWByteAddressBufferC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, // CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name) // CHECK: %[[HANDLE:.*]] = call target("dx.RawBuffer", i8, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i8_1_0t -// CHECK-SAME: (i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i1 false, ptr %{{.*}}) +// CHECK-SAME: (i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr %{{.*}}) // CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %this1, i32 0, i32 0 // CHECK-NEXT: store target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], ptr %__handle, align 4 diff --git a/clang/test/CodeGenHLSL/resources/ConsumeStructuredBuffer-elementtype.hlsl b/clang/test/CodeGenHLSL/resources/ConsumeStructuredBuffer-elementtype.hlsl index 70fe8670c59a..632fd910aee1 100644 --- a/clang/test/CodeGenHLSL/resources/ConsumeStructuredBuffer-elementtype.hlsl +++ b/clang/test/CodeGenHLSL/resources/ConsumeStructuredBuffer-elementtype.hlsl @@ -1,54 +1,54 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=DXIL
-// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPV
-
-struct MyStruct {
- float4 a;
- int2 b;
-};
-
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.0" = type { target("dx.RawBuffer", i16, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.1" = type { target("dx.RawBuffer", i32, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.3" = type { target("dx.RawBuffer", i64, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.5" = type { target("dx.RawBuffer", half, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.6" = type { target("dx.RawBuffer", float, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.7" = type { target("dx.RawBuffer", double, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.8" = type { target("dx.RawBuffer", <4 x i16>, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.9" = type { target("dx.RawBuffer", <3 x i32>, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.10" = type { target("dx.RawBuffer", <2 x half>, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.11" = type { target("dx.RawBuffer", <3 x float>, 1, 0)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.12" = type { target("dx.RawBuffer", %struct.MyStruct, 1, 0)
-// DXIL: %struct.MyStruct = type <{ <4 x float>, <2 x i32> }>
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.13" = type { target("dx.RawBuffer", i32, 1, 0)
-// SPV: %"class.hlsl::ConsumeStructuredBuffer.13" = type { target("spirv.VulkanBuffer", [0 x i32], 12, 1)
-// DXIL: %"class.hlsl::ConsumeStructuredBuffer.14" = type { target("dx.RawBuffer", <4 x i32>, 1, 0)
-// SPV: %"class.hlsl::ConsumeStructuredBuffer.14" = type { target("spirv.VulkanBuffer", [0 x <4 x i32>], 12, 1)
-
-ConsumeStructuredBuffer<int16_t> BufI16;
-ConsumeStructuredBuffer<uint16_t> BufU16;
-ConsumeStructuredBuffer<int> BufI32;
-ConsumeStructuredBuffer<uint> BufU32;
-ConsumeStructuredBuffer<int64_t> BufI64;
-ConsumeStructuredBuffer<uint64_t> BufU64;
-ConsumeStructuredBuffer<half> BufF16;
-ConsumeStructuredBuffer<float> BufF32;
-ConsumeStructuredBuffer<double> BufF64;
-ConsumeStructuredBuffer< vector<int16_t, 4> > BufI16x4;
-ConsumeStructuredBuffer< vector<uint, 3> > BufU32x3;
-ConsumeStructuredBuffer<half2> BufF16x2;
-ConsumeStructuredBuffer<float3> BufF32x3;
-// TODO: ConsumeStructuredBuffer<snorm half> BufSNormF16;
-// TODO: ConsumeStructuredBuffer<unorm half> BufUNormF16;
-// TODO: ConsumeStructuredBuffer<snorm float> BufSNormF32;
-// TODO: ConsumeStructuredBuffer<unorm float> BufUNormF32;
-// TODO: ConsumeStructuredBuffer<snorm double> BufSNormF64;
-// TODO: ConsumeStructuredBuffer<unorm double> BufUNormF64;
-ConsumeStructuredBuffer<MyStruct> BufMyStruct;
-ConsumeStructuredBuffer<bool> BufBool;
-ConsumeStructuredBuffer<bool4> BufBoolVec;
-
-[numthreads(1,1,1)]
-void main(int GI : SV_GroupIndex) {
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=DXIL +// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPV + +struct MyStruct { + float4 a; + int2 b; +}; + +// DXIL: %"class.hlsl::ConsumeStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.0" = type { target("dx.RawBuffer", i16, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.1" = type { target("dx.RawBuffer", i32, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.3" = type { target("dx.RawBuffer", i64, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.5" = type { target("dx.RawBuffer", half, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.6" = type { target("dx.RawBuffer", float, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.7" = type { target("dx.RawBuffer", double, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.8" = type { target("dx.RawBuffer", <4 x i16>, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.9" = type { target("dx.RawBuffer", <3 x i32>, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.10" = type { target("dx.RawBuffer", <2 x half>, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.11" = type { target("dx.RawBuffer", <3 x float>, 1, 0) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.12" = type { target("dx.RawBuffer", %struct.MyStruct, 1, 0) +// DXIL: %struct.MyStruct = type <{ <4 x float>, <2 x i32> }> +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.13" = type { target("dx.RawBuffer", i32, 1, 0) +// SPV: %"class.hlsl::ConsumeStructuredBuffer.13" = type { target("spirv.VulkanBuffer", [0 x i32], 12, 1) +// DXIL: %"class.hlsl::ConsumeStructuredBuffer.14" = type { target("dx.RawBuffer", <4 x i32>, 1, 0) +// SPV: %"class.hlsl::ConsumeStructuredBuffer.14" = type { target("spirv.VulkanBuffer", [0 x <4 x i32>], 12, 1) + +ConsumeStructuredBuffer<int16_t> BufI16; +ConsumeStructuredBuffer<uint16_t> BufU16; +ConsumeStructuredBuffer<int> BufI32; +ConsumeStructuredBuffer<uint> BufU32; +ConsumeStructuredBuffer<int64_t> BufI64; +ConsumeStructuredBuffer<uint64_t> BufU64; +ConsumeStructuredBuffer<half> BufF16; +ConsumeStructuredBuffer<float> BufF32; +ConsumeStructuredBuffer<double> BufF64; +ConsumeStructuredBuffer< vector<int16_t, 4> > BufI16x4; +ConsumeStructuredBuffer< vector<uint, 3> > BufU32x3; +ConsumeStructuredBuffer<half2> BufF16x2; +ConsumeStructuredBuffer<float3> BufF32x3; +// TODO: ConsumeStructuredBuffer<snorm half> BufSNormF16; +// TODO: ConsumeStructuredBuffer<unorm half> BufUNormF16; +// TODO: ConsumeStructuredBuffer<snorm float> BufSNormF32; +// TODO: ConsumeStructuredBuffer<unorm float> BufUNormF32; +// TODO: ConsumeStructuredBuffer<snorm double> BufSNormF64; +// TODO: ConsumeStructuredBuffer<unorm double> BufUNormF64; +ConsumeStructuredBuffer<MyStruct> BufMyStruct; +ConsumeStructuredBuffer<bool> BufBool; +ConsumeStructuredBuffer<bool4> BufBoolVec; + +[numthreads(1,1,1)] +void main(int GI : SV_GroupIndex) { +} diff --git a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl index 114468914e2e..127498460b03 100644 --- a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl +++ b/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl @@ -63,11 +63,11 @@ export void foo() { // CHECK: call void @_ZN4hlsl8RWBufferIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %{{.*}}) // Buf1 initialization part 3 - body of RWBuffer<float> C2 constructor with explicit binding that initializes -// handle with @llvm.dx.resource.handlefrombinding +// handle with @llvm.dx.resource.handlefrombinding // CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, // CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) // CHECK-DXIL: %[[HANDLE:.*]] = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t( -// CHECK-DXIL-SAME: i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i1 false, ptr %{{.*}}) +// CHECK-DXIL-SAME: i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr %{{.*}}) // CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %[[HANDLE]], ptr %__handle, align 4 @@ -76,7 +76,7 @@ export void foo() { // CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIdEC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, // CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name) // CHECK: %[[HANDLE:.*]] = call target("dx.TypedBuffer", double, 1, 0, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.TypedBuffer_f64_1_0_0t -// CHECK-SAME: (i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i1 false, ptr %{{.*}}) +// CHECK-SAME: (i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr %{{.*}}) // CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: store target("dx.TypedBuffer", double, 1, 0, 0) %[[HANDLE]], ptr %__handle, align 4 diff --git a/clang/test/CodeGenHLSL/resources/RWBuffer-elementtype.hlsl b/clang/test/CodeGenHLSL/resources/RWBuffer-elementtype.hlsl index 5512a657bc5f..f48521b0f176 100644 --- a/clang/test/CodeGenHLSL/resources/RWBuffer-elementtype.hlsl +++ b/clang/test/CodeGenHLSL/resources/RWBuffer-elementtype.hlsl @@ -18,18 +18,18 @@ // SPIRV: %"class.hlsl::RWBuffer" = type { target("spirv.SignedImage", i16, 5, 2, 0, 0, 2, 0) } // SPIRV: %"class.hlsl::RWBuffer.0" = type { target("spirv.Image", i16, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.1" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.2" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.3" = type { target("spirv.SignedImage", i64, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.4" = type { target("spirv.Image", i64, 5, 2, 0, 0, 2, 0) } +// SPIRV: %"class.hlsl::RWBuffer.1" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 24) } +// SPIRV: %"class.hlsl::RWBuffer.2" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 33) } +// SPIRV: %"class.hlsl::RWBuffer.3" = type { target("spirv.SignedImage", i64, 5, 2, 0, 0, 2, 41) } +// SPIRV: %"class.hlsl::RWBuffer.4" = type { target("spirv.Image", i64, 5, 2, 0, 0, 2, 40) } // SPIRV: %"class.hlsl::RWBuffer.5" = type { target("spirv.Image", half, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.6" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 0) } +// SPIRV: %"class.hlsl::RWBuffer.6" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 3) } // SPIRV: %"class.hlsl::RWBuffer.7" = type { target("spirv.Image", double, 5, 2, 0, 0, 2, 0) } // SPIRV: %"class.hlsl::RWBuffer.8" = type { target("spirv.SignedImage", i16, 5, 2, 0, 0, 2, 0) } // SPIRV: %"class.hlsl::RWBuffer.9" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) } // SPIRV: %"class.hlsl::RWBuffer.10" = type { target("spirv.Image", half, 5, 2, 0, 0, 2, 0) } // SPIRV: %"class.hlsl::RWBuffer.11" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.12" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 0) } +// SPIRV: %"class.hlsl::RWBuffer.12" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 21) } RWBuffer<int16_t> BufI16; RWBuffer<uint16_t> BufU16; diff --git a/clang/test/CodeGenHLSL/resources/RWBuffer-imageformat.hlsl b/clang/test/CodeGenHLSL/resources/RWBuffer-imageformat.hlsl new file mode 100644 index 000000000000..aebee894f79d --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/RWBuffer-imageformat.hlsl @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -triple spirv-pc-vulkan-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s + +// Signed integers +// CHECK: %"class.hlsl::RWBuffer" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 24) } +RWBuffer<int> rwb_int; +// CHECK: %"class.hlsl::RWBuffer.0" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 25) } +RWBuffer<int2> rwb_int2; +// CHECK: %"class.hlsl::RWBuffer.1" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 0) } +RWBuffer<int3> rwb_int3; +// CHECK: %"class.hlsl::RWBuffer.2" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 21) } +RWBuffer<int4> rwb_int4; + +// Unsigned integers +// CHECK: %"class.hlsl::RWBuffer.3" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 33) } +RWBuffer<uint> rwb_uint; +// CHECK: %"class.hlsl::RWBuffer.4" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 35) } +RWBuffer<uint2> rwb_uint2; +// CHECK: %"class.hlsl::RWBuffer.5" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) } +RWBuffer<uint3> rwb_uint3; +// CHECK: %"class.hlsl::RWBuffer.6" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 30) } +RWBuffer<uint4> rwb_uint4; + +// 64-bit integers +// CHECK: %"class.hlsl::RWBuffer.7" = type { target("spirv.SignedImage", i64, 5, 2, 0, 0, 2, 41) } +RWBuffer<int64_t> rwb_i64; +// CHECK: %"class.hlsl::RWBuffer.8" = type { target("spirv.SignedImage", i64, 5, 2, 0, 0, 2, 0) } +RWBuffer<int64_t2> rwb_i64_2; +// CHECK: %"class.hlsl::RWBuffer.9" = type { target("spirv.Image", i64, 5, 2, 0, 0, 2, 40) } +RWBuffer<uint64_t> rwb_u64; +// CHECK: %"class.hlsl::RWBuffer.10" = type { target("spirv.Image", i64, 5, 2, 0, 0, 2, 0) } +RWBuffer<uint64_t2> rwb_u64_2; + +// Floats +// CHECK: %"class.hlsl::RWBuffer.11" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 3) } +RWBuffer<float> rwb_float; +// CHECK: %"class.hlsl::RWBuffer.12" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 6) } +RWBuffer<float2> rwb_float2; +// CHECK: %"class.hlsl::RWBuffer.13" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 0) } +RWBuffer<float3> rwb_float3; +// CHECK: %"class.hlsl::RWBuffer.14" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 1) } +RWBuffer<float4> rwb_float4; + +// Other types that should get Unknown format +// CHECK: %"class.hlsl::RWBuffer.15" = type { target("spirv.Image", half, 5, 2, 0, 0, 2, 0) } +RWBuffer<half> rwb_half; +// CHECK: %"class.hlsl::RWBuffer.16" = type { target("spirv.Image", double, 5, 2, 0, 0, 2, 0) } +RWBuffer<double> rwb_double; + +// Non-UAV resource +// CHECK: %"class.hlsl::Buffer" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 1, 0) } +Buffer<int> b_int; + +[numthreads(1,1,1)] +void main(int GI : SV_GroupIndex) { + rwb_int[GI] = 0; + rwb_int2[GI] = 0; + rwb_int3[GI] = 0; + rwb_int4[GI] = 0; + rwb_uint[GI] = 0; + rwb_uint2[GI] = 0; + rwb_uint3[GI] = 0; + rwb_uint4[GI] = 0; + rwb_i64[GI] = 0; + rwb_i64_2[GI] = 0; + rwb_u64[GI] = 0; + rwb_u64_2[GI] = 0; + rwb_float[GI] = 0; + rwb_float2[GI] = 0; + rwb_float3[GI] = 0; + rwb_float4[GI] = 0; + rwb_half[GI] = 0; + rwb_double[GI] = 0; + int val = b_int[GI]; +} diff --git a/clang/test/CodeGenHLSL/resources/RWBuffer-subscript.hlsl b/clang/test/CodeGenHLSL/resources/RWBuffer-subscript.hlsl index 63e3552b680b..0de171cb452d 100644 --- a/clang/test/CodeGenHLSL/resources/RWBuffer-subscript.hlsl +++ b/clang/test/CodeGenHLSL/resources/RWBuffer-subscript.hlsl @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=DXC,CHECK -// RUN: %clang_cc1 -triple spirv1.6-pc-vulkan1.3-compute -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=SPIRV,CHECK +// RUN: %clang_cc1 -triple spirv1.6-pc-vulkan1.3-compute -fspv-use-unknown-image-format -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=SPIRV,CHECK RWBuffer<int> In; RWBuffer<int> Out; diff --git a/clang/test/CodeGenHLSL/resources/RWStructuredBuffer-elementtype.hlsl b/clang/test/CodeGenHLSL/resources/RWStructuredBuffer-elementtype.hlsl index f7cdc5d4d39f..472b9a8dae2a 100644 --- a/clang/test/CodeGenHLSL/resources/RWStructuredBuffer-elementtype.hlsl +++ b/clang/test/CodeGenHLSL/resources/RWStructuredBuffer-elementtype.hlsl @@ -1,61 +1,61 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK
-// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPV
-
-// CHECK: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.0" = type { target("dx.RawBuffer", i16, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.1" = type { target("dx.RawBuffer", i32, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.3" = type { target("dx.RawBuffer", i64, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.5" = type { target("dx.RawBuffer", half, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.6" = type { target("dx.RawBuffer", float, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.7" = type { target("dx.RawBuffer", double, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.8" = type { target("dx.RawBuffer", <4 x i16>, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.9" = type { target("dx.RawBuffer", <3 x i32>, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.10" = type { target("dx.RawBuffer", <2 x half>, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.11" = type { target("dx.RawBuffer", <3 x float>, 1, 0) }
-// CHECK: %"class.hlsl::RWStructuredBuffer.12" = type { target("dx.RawBuffer", i32, 1, 0) }
-// SPV: %"class.hlsl::RWStructuredBuffer.12" = type { target("spirv.VulkanBuffer", [0 x i32], 12, 1)
-// CHECK: %"class.hlsl::RWStructuredBuffer.13" = type { target("dx.RawBuffer", <4 x i32>, 1, 0) }
-// SPV: %"class.hlsl::RWStructuredBuffer.13" = type { target("spirv.VulkanBuffer", [0 x <4 x i32>], 12, 1)
-
-RWStructuredBuffer<int16_t> BufI16;
-RWStructuredBuffer<uint16_t> BufU16;
-RWStructuredBuffer<int> BufI32;
-RWStructuredBuffer<uint> BufU32;
-RWStructuredBuffer<int64_t> BufI64;
-RWStructuredBuffer<uint64_t> BufU64;
-RWStructuredBuffer<half> BufF16;
-RWStructuredBuffer<float> BufF32;
-RWStructuredBuffer<double> BufF64;
-RWStructuredBuffer< vector<int16_t, 4> > BufI16x4;
-RWStructuredBuffer< vector<uint, 3> > BufU32x3;
-RWStructuredBuffer<half2> BufF16x2;
-RWStructuredBuffer<float3> BufF32x3;
-RWStructuredBuffer<bool> BufBool;
-RWStructuredBuffer<bool4> BufBoolVec;
-// TODO: RWStructuredBuffer<snorm half> BufSNormF16;
-// TODO: RWStructuredBuffer<unorm half> BufUNormF16;
-// TODO: RWStructuredBuffer<snorm float> BufSNormF32;
-// TODO: RWStructuredBuffer<unorm float> BufUNormF32;
-// TODO: RWStructuredBuffer<snorm double> BufSNormF64;
-// TODO: RWStructuredBuffer<unorm double> BufUNormF64;
-
-[numthreads(1,1,1)]
-void main(int GI : SV_GroupIndex) {
- BufI16[GI] = 0;
- BufU16[GI] = 0;
- BufI32[GI] = 0;
- BufU32[GI] = 0;
- BufI64[GI] = 0;
- BufU64[GI] = 0;
- BufF16[GI] = 0;
- BufF32[GI] = 0;
- BufF64[GI] = 0;
- BufI16x4[GI] = 0;
- BufU32x3[GI] = 0;
- BufF16x2[GI] = 0;
- BufF32x3[GI] = 0;
- BufBool[GI] = false;
- BufBool[GI] = false;
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK +// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPV + +// CHECK: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.0" = type { target("dx.RawBuffer", i16, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.1" = type { target("dx.RawBuffer", i32, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.3" = type { target("dx.RawBuffer", i64, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.5" = type { target("dx.RawBuffer", half, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.6" = type { target("dx.RawBuffer", float, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.7" = type { target("dx.RawBuffer", double, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.8" = type { target("dx.RawBuffer", <4 x i16>, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.9" = type { target("dx.RawBuffer", <3 x i32>, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.10" = type { target("dx.RawBuffer", <2 x half>, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.11" = type { target("dx.RawBuffer", <3 x float>, 1, 0) } +// CHECK: %"class.hlsl::RWStructuredBuffer.12" = type { target("dx.RawBuffer", i32, 1, 0) } +// SPV: %"class.hlsl::RWStructuredBuffer.12" = type { target("spirv.VulkanBuffer", [0 x i32], 12, 1) +// CHECK: %"class.hlsl::RWStructuredBuffer.13" = type { target("dx.RawBuffer", <4 x i32>, 1, 0) } +// SPV: %"class.hlsl::RWStructuredBuffer.13" = type { target("spirv.VulkanBuffer", [0 x <4 x i32>], 12, 1) + +RWStructuredBuffer<int16_t> BufI16; +RWStructuredBuffer<uint16_t> BufU16; +RWStructuredBuffer<int> BufI32; +RWStructuredBuffer<uint> BufU32; +RWStructuredBuffer<int64_t> BufI64; +RWStructuredBuffer<uint64_t> BufU64; +RWStructuredBuffer<half> BufF16; +RWStructuredBuffer<float> BufF32; +RWStructuredBuffer<double> BufF64; +RWStructuredBuffer< vector<int16_t, 4> > BufI16x4; +RWStructuredBuffer< vector<uint, 3> > BufU32x3; +RWStructuredBuffer<half2> BufF16x2; +RWStructuredBuffer<float3> BufF32x3; +RWStructuredBuffer<bool> BufBool; +RWStructuredBuffer<bool4> BufBoolVec; +// TODO: RWStructuredBuffer<snorm half> BufSNormF16; +// TODO: RWStructuredBuffer<unorm half> BufUNormF16; +// TODO: RWStructuredBuffer<snorm float> BufSNormF32; +// TODO: RWStructuredBuffer<unorm float> BufUNormF32; +// TODO: RWStructuredBuffer<snorm double> BufSNormF64; +// TODO: RWStructuredBuffer<unorm double> BufUNormF64; + +[numthreads(1,1,1)] +void main(int GI : SV_GroupIndex) { + BufI16[GI] = 0; + BufU16[GI] = 0; + BufI32[GI] = 0; + BufU32[GI] = 0; + BufI64[GI] = 0; + BufU64[GI] = 0; + BufF16[GI] = 0; + BufF32[GI] = 0; + BufF64[GI] = 0; + BufI16x4[GI] = 0; + BufU32x3[GI] = 0; + BufF16x2[GI] = 0; + BufF32x3[GI] = 0; + BufBool[GI] = false; + BufBool[GI] = false; +} diff --git a/clang/test/CodeGenHLSL/resources/RasterizerOrderedStructuredBuffer-elementtype.hlsl b/clang/test/CodeGenHLSL/resources/RasterizerOrderedStructuredBuffer-elementtype.hlsl index b7ab09f6be7a..6c5a705d5cf2 100644 --- a/clang/test/CodeGenHLSL/resources/RasterizerOrderedStructuredBuffer-elementtype.hlsl +++ b/clang/test/CodeGenHLSL/resources/RasterizerOrderedStructuredBuffer-elementtype.hlsl @@ -1,60 +1,60 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=DXIL
-
-struct MyStruct {
- float4 a;
- int2 b;
-};
-
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 1) }
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.0" = type { target("dx.RawBuffer", i16, 1, 1) }
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.1" = type { target("dx.RawBuffer", i32, 1, 1) }
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 1) }
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.3" = type { target("dx.RawBuffer", i64, 1, 1) }
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 1) }
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.5" = type { target("dx.RawBuffer", half, 1, 1) }
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.6" = type { target("dx.RawBuffer", float, 1, 1) }
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.7" = type { target("dx.RawBuffer", double, 1, 1) }
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.8" = type { target("dx.RawBuffer", <4 x i16>, 1, 1) }
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.9" = type { target("dx.RawBuffer", <3 x i32>, 1, 1) }
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.10" = type { target("dx.RawBuffer", <2 x half>, 1, 1) }
-// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.11" = type { target("dx.RawBuffer", <3 x float>, 1, 1) }
-// DXIL: %struct.MyStruct = type <{ <4 x float>, <2 x i32> }>
-
-RasterizerOrderedStructuredBuffer<int16_t> BufI16;
-RasterizerOrderedStructuredBuffer<uint16_t> BufU16;
-RasterizerOrderedStructuredBuffer<int> BufI32;
-RasterizerOrderedStructuredBuffer<uint> BufU32;
-RasterizerOrderedStructuredBuffer<int64_t> BufI64;
-RasterizerOrderedStructuredBuffer<uint64_t> BufU64;
-RasterizerOrderedStructuredBuffer<half> BufF16;
-RasterizerOrderedStructuredBuffer<float> BufF32;
-RasterizerOrderedStructuredBuffer<double> BufF64;
-RasterizerOrderedStructuredBuffer< vector<int16_t, 4> > BufI16x4;
-RasterizerOrderedStructuredBuffer< vector<uint, 3> > BufU32x3;
-RasterizerOrderedStructuredBuffer<half2> BufF16x2;
-RasterizerOrderedStructuredBuffer<float3> BufF32x3;
-// TODO: RasterizerOrderedStructuredBuffer<snorm half> BufSNormF16;
-// TODO: RasterizerOrderedStructuredBuffer<unorm half> BufUNormF16;
-// TODO: RasterizerOrderedStructuredBuffer<snorm float> BufSNormF32;
-// TODO: RasterizerOrderedStructuredBuffer<unorm float> BufUNormF32;
-// TODO: RasterizerOrderedStructuredBuffer<snorm double> BufSNormF64;
-// TODO: RasterizerOrderedStructuredBuffer<unorm double> BufUNormF64;
-RasterizerOrderedStructuredBuffer<MyStruct> BufMyStruct;
-
-[numthreads(1,1,1)]
-void main(int GI : SV_GroupIndex) {
- BufI16[GI] = 0;
- BufU16[GI] = 0;
- BufI32[GI] = 0;
- BufU32[GI] = 0;
- BufI64[GI] = 0;
- BufU64[GI] = 0;
- BufF16[GI] = 0;
- BufF32[GI] = 0;
- BufF64[GI] = 0;
- BufI16x4[GI] = 0;
- BufU32x3[GI] = 0;
- BufF16x2[GI] = 0;
- BufF32x3[GI] = 0;
- BufMyStruct[GI] = {{0,0,0,0},{0,0}};
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=DXIL + +struct MyStruct { + float4 a; + int2 b; +}; + +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 1) } +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.0" = type { target("dx.RawBuffer", i16, 1, 1) } +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.1" = type { target("dx.RawBuffer", i32, 1, 1) } +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 1) } +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.3" = type { target("dx.RawBuffer", i64, 1, 1) } +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 1) } +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.5" = type { target("dx.RawBuffer", half, 1, 1) } +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.6" = type { target("dx.RawBuffer", float, 1, 1) } +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.7" = type { target("dx.RawBuffer", double, 1, 1) } +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.8" = type { target("dx.RawBuffer", <4 x i16>, 1, 1) } +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.9" = type { target("dx.RawBuffer", <3 x i32>, 1, 1) } +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.10" = type { target("dx.RawBuffer", <2 x half>, 1, 1) } +// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.11" = type { target("dx.RawBuffer", <3 x float>, 1, 1) } +// DXIL: %struct.MyStruct = type <{ <4 x float>, <2 x i32> }> + +RasterizerOrderedStructuredBuffer<int16_t> BufI16; +RasterizerOrderedStructuredBuffer<uint16_t> BufU16; +RasterizerOrderedStructuredBuffer<int> BufI32; +RasterizerOrderedStructuredBuffer<uint> BufU32; +RasterizerOrderedStructuredBuffer<int64_t> BufI64; +RasterizerOrderedStructuredBuffer<uint64_t> BufU64; +RasterizerOrderedStructuredBuffer<half> BufF16; +RasterizerOrderedStructuredBuffer<float> BufF32; +RasterizerOrderedStructuredBuffer<double> BufF64; +RasterizerOrderedStructuredBuffer< vector<int16_t, 4> > BufI16x4; +RasterizerOrderedStructuredBuffer< vector<uint, 3> > BufU32x3; +RasterizerOrderedStructuredBuffer<half2> BufF16x2; +RasterizerOrderedStructuredBuffer<float3> BufF32x3; +// TODO: RasterizerOrderedStructuredBuffer<snorm half> BufSNormF16; +// TODO: RasterizerOrderedStructuredBuffer<unorm half> BufUNormF16; +// TODO: RasterizerOrderedStructuredBuffer<snorm float> BufSNormF32; +// TODO: RasterizerOrderedStructuredBuffer<unorm float> BufUNormF32; +// TODO: RasterizerOrderedStructuredBuffer<snorm double> BufSNormF64; +// TODO: RasterizerOrderedStructuredBuffer<unorm double> BufUNormF64; +RasterizerOrderedStructuredBuffer<MyStruct> BufMyStruct; + +[numthreads(1,1,1)] +void main(int GI : SV_GroupIndex) { + BufI16[GI] = 0; + BufU16[GI] = 0; + BufI32[GI] = 0; + BufU32[GI] = 0; + BufI64[GI] = 0; + BufU64[GI] = 0; + BufF16[GI] = 0; + BufF32[GI] = 0; + BufF64[GI] = 0; + BufI16x4[GI] = 0; + BufU32x3[GI] = 0; + BufF16x2[GI] = 0; + BufF32x3[GI] = 0; + BufMyStruct[GI] = {{0,0,0,0},{0,0}}; +} diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffer-elementtype.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffer-elementtype.hlsl index 0bb08065ddc2..00216df7fa29 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffer-elementtype.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffer-elementtype.hlsl @@ -1,61 +1,61 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK
-// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPV
-
-// CHECK: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", i16, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.0" = type { target("dx.RawBuffer", i16, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.1" = type { target("dx.RawBuffer", i32, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.2" = type { target("dx.RawBuffer", i32, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.3" = type { target("dx.RawBuffer", i64, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.4" = type { target("dx.RawBuffer", i64, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.5" = type { target("dx.RawBuffer", half, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.6" = type { target("dx.RawBuffer", float, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.7" = type { target("dx.RawBuffer", double, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.8" = type { target("dx.RawBuffer", <4 x i16>, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.9" = type { target("dx.RawBuffer", <3 x i32>, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.10" = type { target("dx.RawBuffer", <2 x half>, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.11" = type { target("dx.RawBuffer", <3 x float>, 0, 0) }
-// CHECK: %"class.hlsl::StructuredBuffer.12" = type { target("dx.RawBuffer", i32, 0, 0) }
-// SPV: %"class.hlsl::StructuredBuffer.12" = type { target("spirv.VulkanBuffer", [0 x i32], 12, 0)
-// CHECK: %"class.hlsl::StructuredBuffer.13" = type { target("dx.RawBuffer", <4 x i32>, 0, 0) }
-// SPV: %"class.hlsl::StructuredBuffer.13" = type { target("spirv.VulkanBuffer", [0 x <4 x i32>], 12, 0)
-
-StructuredBuffer<int16_t> BufI16;
-StructuredBuffer<uint16_t> BufU16;
-StructuredBuffer<int> BufI32;
-StructuredBuffer<uint> BufU32;
-StructuredBuffer<int64_t> BufI64;
-StructuredBuffer<uint64_t> BufU64;
-StructuredBuffer<half> BufF16;
-StructuredBuffer<float> BufF32;
-StructuredBuffer<double> BufF64;
-StructuredBuffer< vector<int16_t, 4> > BufI16x4;
-StructuredBuffer< vector<uint, 3> > BufU32x3;
-StructuredBuffer<half2> BufF16x2;
-StructuredBuffer<float3> BufF32x3;
-StructuredBuffer<bool> BufBool;
-StructuredBuffer<bool4> BufBoolVec;
-// TODO: StructuredBuffer<snorm half> BufSNormF16;
-// TODO: StructuredBuffer<unorm half> BufUNormF16;
-// TODO: StructuredBuffer<snorm float> BufSNormF32;
-// TODO: StructuredBuffer<unorm float> BufUNormF32;
-// TODO: StructuredBuffer<snorm double> BufSNormF64;
-// TODO: StructuredBuffer<unorm double> BufUNormF64;
-
-[numthreads(1,1,1)]
-void main(int GI : SV_GroupIndex) {
- int16_t v1 = BufI16[GI];
- uint16_t v2 = BufU16[GI];
- int v3 = BufI32[GI];
- uint v4 = BufU32[GI];
- int64_t v5 = BufI64[GI];
- uint64_t v6 = BufU64[GI];
- half v7 = BufF16[GI];
- float v8 = BufF32[GI];
- double v9 = BufF64[GI];
- vector<int16_t,4> v10 = BufI16x4[GI];
- vector<int, 3> v11 = BufU32x3[GI];
- half2 v12 = BufF16x2[GI];
- float3 v13 = BufF32x3[GI];
- bool v14 = BufBool[GI];
- bool4 v15 = BufBoolVec[GI];
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK +// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPV + +// CHECK: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", i16, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.0" = type { target("dx.RawBuffer", i16, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.1" = type { target("dx.RawBuffer", i32, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.2" = type { target("dx.RawBuffer", i32, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.3" = type { target("dx.RawBuffer", i64, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.4" = type { target("dx.RawBuffer", i64, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.5" = type { target("dx.RawBuffer", half, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.6" = type { target("dx.RawBuffer", float, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.7" = type { target("dx.RawBuffer", double, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.8" = type { target("dx.RawBuffer", <4 x i16>, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.9" = type { target("dx.RawBuffer", <3 x i32>, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.10" = type { target("dx.RawBuffer", <2 x half>, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.11" = type { target("dx.RawBuffer", <3 x float>, 0, 0) } +// CHECK: %"class.hlsl::StructuredBuffer.12" = type { target("dx.RawBuffer", i32, 0, 0) } +// SPV: %"class.hlsl::StructuredBuffer.12" = type { target("spirv.VulkanBuffer", [0 x i32], 12, 0) +// CHECK: %"class.hlsl::StructuredBuffer.13" = type { target("dx.RawBuffer", <4 x i32>, 0, 0) } +// SPV: %"class.hlsl::StructuredBuffer.13" = type { target("spirv.VulkanBuffer", [0 x <4 x i32>], 12, 0) + +StructuredBuffer<int16_t> BufI16; +StructuredBuffer<uint16_t> BufU16; +StructuredBuffer<int> BufI32; +StructuredBuffer<uint> BufU32; +StructuredBuffer<int64_t> BufI64; +StructuredBuffer<uint64_t> BufU64; +StructuredBuffer<half> BufF16; +StructuredBuffer<float> BufF32; +StructuredBuffer<double> BufF64; +StructuredBuffer< vector<int16_t, 4> > BufI16x4; +StructuredBuffer< vector<uint, 3> > BufU32x3; +StructuredBuffer<half2> BufF16x2; +StructuredBuffer<float3> BufF32x3; +StructuredBuffer<bool> BufBool; +StructuredBuffer<bool4> BufBoolVec; +// TODO: StructuredBuffer<snorm half> BufSNormF16; +// TODO: StructuredBuffer<unorm half> BufUNormF16; +// TODO: StructuredBuffer<snorm float> BufSNormF32; +// TODO: StructuredBuffer<unorm float> BufUNormF32; +// TODO: StructuredBuffer<snorm double> BufSNormF64; +// TODO: StructuredBuffer<unorm double> BufUNormF64; + +[numthreads(1,1,1)] +void main(int GI : SV_GroupIndex) { + int16_t v1 = BufI16[GI]; + uint16_t v2 = BufU16[GI]; + int v3 = BufI32[GI]; + uint v4 = BufU32[GI]; + int64_t v5 = BufI64[GI]; + uint64_t v6 = BufU64[GI]; + half v7 = BufF16[GI]; + float v8 = BufF32[GI]; + double v9 = BufF64[GI]; + vector<int16_t,4> v10 = BufI16x4[GI]; + vector<int, 3> v11 = BufU32x3[GI]; + half2 v12 = BufF16x2[GI]; + float3 v13 = BufF32x3[GI]; + bool v14 = BufBool[GI]; + bool4 v15 = BufBoolVec[GI]; +} diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl index 28841732df99..91410e600c6e 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl @@ -71,7 +71,7 @@ export void foo() { // CHECK: define linkonce_odr hidden void @_ZN4hlsl16StructuredBufferIfEC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, // CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) // CHECK-DXIL: %[[HANDLE:.*]] = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t( -// CHECK-SAME: i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i1 false, ptr %{{.*}}) +// CHECK-SAME: i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr %{{.*}}) // CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 0, 0) %[[HANDLE]], ptr %__handle, align 4 @@ -80,7 +80,7 @@ export void foo() { // CHECK: define linkonce_odr hidden void @_ZN4hlsl18RWStructuredBufferIfEC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, // CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name) // CHECK: %[[HANDLE:.*]] = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f32_1_0t -// CHECK-SAME: (i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i1 false, ptr %{{.*}}) +// CHECK-SAME: (i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr %{{.*}}) // CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: store target("dx.RawBuffer", float, 1, 0) %[[HANDLE]], ptr %__handle, align 4 diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-subscripts.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-subscripts.hlsl index cdeef2626eb6..4c26d70c0924 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-subscripts.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-subscripts.hlsl @@ -1,51 +1,51 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s -check-prefixes=DXIL,CHECK
-// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-compute -emit-llvm -o - -O0 %s | FileCheck %s -check-prefixes=SPV,CHECK
-
-struct S {
- float f;
-};
-
-StructuredBuffer<int> In;
-RWStructuredBuffer<int> Out1;
-RWStructuredBuffer<S> RWSB3;
-
-#ifndef __SPIRV__
-// RasterizerOrderedStructuredBuffer are not implement in SPIR-V yet.
-RasterizerOrderedStructuredBuffer<int> Out2;
-#endif
-
-[numthreads(1,1,1)]
-void main(unsigned GI : SV_GroupIndex) {
- // CHECK: define void @main()
-
- // DXIL: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0) %{{.*}}, i32 %{{.*}})
- // SPV: %[[INPTR:.*]] = call noundef align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_0t(target("spirv.VulkanBuffer", [0 x i32], 12, 0) %{{.*}}, i32 %{{.*}})
- // CHECK: %[[LOAD:.*]] = load i32, ptr {{.*}}%[[INPTR]]
- // DXIL: %[[OUT1PTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0) %{{.*}}, i32 %{{.*}})
- // SPV: %[[OUT1PTR:.*]] = call noundef align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t(target("spirv.VulkanBuffer", [0 x i32], 12, 1) %{{.*}}, i32 %{{.*}})
- // CHECK: store i32 %[[LOAD]], ptr {{.*}}%[[OUT1PTR]]
- Out1[GI] = In[GI];
-
-#ifndef __SPIRV__
- // DXIL: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0) %{{.*}}, i32 %{{.*}})
- // DXIL: %[[LOAD:.*]] = load i32, ptr %[[INPTR]]
- // DXIL: %[[OUT2PTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_1t(target("dx.RawBuffer", i32, 1, 1) %{{.*}}, i32 %{{.*}})
- // DXIL: store i32 %[[LOAD]], ptr %[[OUT2PTR]]
- Out2[GI] = In[GI];
-#endif
-
- // For SPIR-V, the addrspacecast comes from `S::operator=` member function, which expects
- // parameters in address space 0. This is why hlsl_device is a sub address
- // space of the default address space.
- // SPV: %[[INPTR:.*]] = call noundef align 1 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0s_struct.Ss_12_1t(target("spirv.VulkanBuffer", [0 x %struct.S], 12, 1) %{{.*}}, i32 %{{.*}})
- // SPV: %[[INCAST:.*]] = addrspacecast ptr addrspace(11) %[[INPTR]] to ptr
- // SPV: %[[OUTPTR:.*]] = call noundef align 1 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0s_struct.Ss_12_1t(target("spirv.VulkanBuffer", [0 x %struct.S], 12, 1) %{{.*}}, i32 %{{.*}})
- // SPV: %[[OUTCAST:.*]] = addrspacecast ptr addrspace(11) %[[OUTPTR]] to ptr
- // SPV: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[OUTCAST]], ptr align 1 %[[INCAST]], i64 4, i1 false)
-
- // For DXIL, hlsl_device and the default address space map to the same target address space. No need for an address space cast.
- // DXIL: %[[INPTR:.*]] = call noundef nonnull align 1 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_s_struct.Ss_1_0t(target("dx.RawBuffer", %struct.S, 1, 0) %{{.*}}, i32 %{{.*}})
- // DXIL: %[[OUTPTR:.*]] = call noundef nonnull align 1 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_s_struct.Ss_1_0t(target("dx.RawBuffer", %struct.S, 1, 0) %{{.*}}, i32 %{{.*}})
- // DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 1 %[[OUTPTR]], ptr align 1 %[[INPTR]], i32 4, i1 false)
- RWSB3[0] = RWSB3[1];
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s -check-prefixes=DXIL,CHECK +// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-compute -emit-llvm -o - -O0 %s | FileCheck %s -check-prefixes=SPV,CHECK + +struct S { + float f; +}; + +StructuredBuffer<int> In; +RWStructuredBuffer<int> Out1; +RWStructuredBuffer<S> RWSB3; + +#ifndef __SPIRV__ +// RasterizerOrderedStructuredBuffer are not implement in SPIR-V yet. +RasterizerOrderedStructuredBuffer<int> Out2; +#endif + +[numthreads(1,1,1)] +void main(unsigned GI : SV_GroupIndex) { + // CHECK: define void @main() + + // DXIL: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0) %{{.*}}, i32 %{{.*}}) + // SPV: %[[INPTR:.*]] = call noundef align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_0t(target("spirv.VulkanBuffer", [0 x i32], 12, 0) %{{.*}}, i32 %{{.*}}) + // CHECK: %[[LOAD:.*]] = load i32, ptr {{.*}}%[[INPTR]] + // DXIL: %[[OUT1PTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0) %{{.*}}, i32 %{{.*}}) + // SPV: %[[OUT1PTR:.*]] = call noundef align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t(target("spirv.VulkanBuffer", [0 x i32], 12, 1) %{{.*}}, i32 %{{.*}}) + // CHECK: store i32 %[[LOAD]], ptr {{.*}}%[[OUT1PTR]] + Out1[GI] = In[GI]; + +#ifndef __SPIRV__ + // DXIL: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0) %{{.*}}, i32 %{{.*}}) + // DXIL: %[[LOAD:.*]] = load i32, ptr %[[INPTR]] + // DXIL: %[[OUT2PTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_1t(target("dx.RawBuffer", i32, 1, 1) %{{.*}}, i32 %{{.*}}) + // DXIL: store i32 %[[LOAD]], ptr %[[OUT2PTR]] + Out2[GI] = In[GI]; +#endif + + // For SPIR-V, the addrspacecast comes from `S::operator=` member function, which expects + // parameters in address space 0. This is why hlsl_device is a sub address + // space of the default address space. + // SPV: %[[INPTR:.*]] = call noundef align 1 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0s_struct.Ss_12_1t(target("spirv.VulkanBuffer", [0 x %struct.S], 12, 1) %{{.*}}, i32 %{{.*}}) + // SPV: %[[INCAST:.*]] = addrspacecast ptr addrspace(11) %[[INPTR]] to ptr + // SPV: %[[OUTPTR:.*]] = call noundef align 1 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0s_struct.Ss_12_1t(target("spirv.VulkanBuffer", [0 x %struct.S], 12, 1) %{{.*}}, i32 %{{.*}}) + // SPV: %[[OUTCAST:.*]] = addrspacecast ptr addrspace(11) %[[OUTPTR]] to ptr + // SPV: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[OUTCAST]], ptr align 1 %[[INCAST]], i64 4, i1 false) + + // For DXIL, hlsl_device and the default address space map to the same target address space. No need for an address space cast. + // DXIL: %[[INPTR:.*]] = call noundef nonnull align 1 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_s_struct.Ss_1_0t(target("dx.RawBuffer", %struct.S, 1, 0) %{{.*}}, i32 %{{.*}}) + // DXIL: %[[OUTPTR:.*]] = call noundef nonnull align 1 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_s_struct.Ss_1_0t(target("dx.RawBuffer", %struct.S, 1, 0) %{{.*}}, i32 %{{.*}}) + // DXIL: call void @llvm.memcpy.p0.p0.i32(ptr align 1 %[[OUTPTR]], ptr align 1 %[[INPTR]], i32 4, i1 false) + RWSB3[0] = RWSB3[1]; +} diff --git a/clang/test/CodeGenHLSL/resources/cbuffer.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer.hlsl index b58a49b41eb9..8dcff5dad9d1 100644 --- a/clang/test/CodeGenHLSL/resources/cbuffer.hlsl +++ b/clang/test/CodeGenHLSL/resources/cbuffer.hlsl @@ -276,61 +276,61 @@ cbuffer CB_C { // CHECK: define internal void @_init_buffer_CBScalars.cb() // CHECK-NEXT: entry: // CHECK-NEXT: %CBScalars.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBScalars, 56, 0, 8, 16, 24, 32, 36, 40, 48)) -// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBScalarss_56_0_8_16_24_32_36_40_48tt(i32 5, i32 1, i32 1, i32 0, i1 false, ptr @CBScalars.str) +// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBScalarss_56_0_8_16_24_32_36_40_48tt(i32 5, i32 1, i32 1, i32 0, ptr @CBScalars.str) // CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBScalars, 56, 0, 8, 16, 24, 32, 36, 40, 48)) %CBScalars.cb_h, ptr @CBScalars.cb, align 4 // CHECK: define internal void @_init_buffer_CBVectors.cb() // CHECK-NEXT: entry: // CHECK-NEXT: %CBVectors.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBVectors, 136, 0, 16, 40, 48, 80, 96, 112)) -// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBVectorss_136_0_16_40_48_80_96_112tt(i32 0, i32 0, i32 1, i32 0, i1 false, ptr @CBVectors.str) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBVectorss_136_0_16_40_48_80_96_112tt(i32 0, i32 0, i32 1, i32 0, ptr @CBVectors.str) // CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBVectors, 136, 0, 16, 40, 48, 80, 96, 112)) %CBVectors.cb_h, ptr @CBVectors.cb, align 4 // CHECK: define internal void @_init_buffer_CBArrays.cb() // CHECK-NEXT: entry: // CHECK-NEXT: %CBArrays.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBArrays, 708, 0, 48, 112, 176, 224, 608, 624, 656)) -// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBArrayss_708_0_48_112_176_224_608_624_656tt(i32 0, i32 2, i32 1, i32 0, i1 false, ptr @CBArrays.str) +// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBArrayss_708_0_48_112_176_224_608_624_656tt(i32 0, i32 2, i32 1, i32 0, ptr @CBArrays.str) // CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBArrays, 708, 0, 48, 112, 176, 224, 608, 624, 656)) %CBArrays.cb_h, ptr @CBArrays.cb, align 4 // CHECK: define internal void @_init_buffer_CBTypedefArray.cb() // CHECK-NEXT: entry: // CHECK-NEXT: %CBTypedefArray.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBTypedefArray, 128, 0, 64)) -// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBTypedefArrays_128_0_64tt(i32 1, i32 2, i32 1, i32 0, i1 false, ptr @CBTypedefArray.str) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBTypedefArrays_128_0_64tt(i32 1, i32 2, i32 1, i32 0, ptr @CBTypedefArray.str) // CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBTypedefArray, 128, 0, 64)) %CBTypedefArray.cb_h, ptr @CBTypedefArray.cb, align 4 // CHECK: define internal void @_init_buffer_CBStructs.cb() // CHECK-NEXT: entry: // CHECK-NEXT: %CBStructs.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBStructs, 246, 0, 16, 32, 64, 144, 238, 240)) -// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBStructss_246_0_16_32_64_144_238_240tt(i32 2, i32 0, i32 1, i32 0, i1 false, ptr @CBStructs.str) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBStructss_246_0_16_32_64_144_238_240tt(i32 2, i32 0, i32 1, i32 0, ptr @CBStructs.str) // CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBStructs, 246, 0, 16, 32, 64, 144, 238, 240)) %CBStructs.cb_h, ptr @CBStructs.cb, align 4 // CHECK: define internal void @_init_buffer_CBClasses.cb() // CHECK-NEXT: entry: // CHECK-NEXT: %CBClasses.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBClasses, 260, 0, 16, 32, 112)) -// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBClassess_260_0_16_32_112tt(i32 3, i32 0, i32 1, i32 0, i1 false, ptr @CBClasses.str) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBClassess_260_0_16_32_112tt(i32 3, i32 0, i32 1, i32 0, ptr @CBClasses.str) // CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBClasses, 260, 0, 16, 32, 112)) %CBClasses.cb_h, ptr @CBClasses.cb, align 4 // CHECK: define internal void @_init_buffer_CBMix.cb() // CHECK-NEXT: entry: // CHECK-NEXT: %CBMix.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBMix, 170, 0, 24, 32, 120, 128, 136, 144, 152, 160, 168)) -// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBMixs_170_0_24_32_120_128_136_144_152_160_168tt(i32 4, i32 0, i32 1, i32 0, i1 false, ptr @CBMix.str) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBMixs_170_0_24_32_120_128_136_144_152_160_168tt(i32 4, i32 0, i32 1, i32 0, ptr @CBMix.str) // CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBMix, 170, 0, 24, 32, 120, 128, 136, 144, 152, 160, 168)) %CBMix.cb_h, ptr @CBMix.cb, align 4 // CHECK: define internal void @_init_buffer_CB_A.cb() // CHECK-NEXT: entry: // CHECK-NEXT: %CB_A.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_A, 188, 0, 32, 76, 80, 120, 128, 144, 160, 182)) -// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB_As_188_0_32_76_80_120_128_144_160_182tt(i32 5, i32 0, i32 1, i32 0, i1 false, ptr @CB_A.str) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB_As_188_0_32_76_80_120_128_144_160_182tt(i32 5, i32 0, i32 1, i32 0, ptr @CB_A.str) // CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_A, 188, 0, 32, 76, 80, 120, 128, 144, 160, 182)) %CB_A.cb_h, ptr @CB_A.cb, align 4 // CHECK: define internal void @_init_buffer_CB_B.cb() // CHECK-NEXT: entry: // CHECK-NEXT: %CB_B.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_B, 94, 0, 88)) -// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB_Bs_94_0_88tt(i32 6, i32 0, i32 1, i32 0, i1 false, ptr @CB_B.str) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB_Bs_94_0_88tt(i32 6, i32 0, i32 1, i32 0, ptr @CB_B.str) // CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_B, 94, 0, 88)) %CB_B.cb_h, ptr @CB_B.cb, align 4 // CHECK: define internal void @_init_buffer_CB_C.cb() // CHECK-NEXT: entry: // CHECK-NEXT: %CB_C.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_C, 400, 0, 16, 112, 128, 392)) -// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB_Cs_400_0_16_112_128_392tt(i32 7, i32 0, i32 1, i32 0, i1 false, ptr @CB_C.str) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB_Cs_400_0_16_112_128_392tt(i32 7, i32 0, i32 1, i32 0, ptr @CB_C.str) // CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_C, 400, 0, 16, 112, 128, 392)) %CB_C.cb_h, ptr @CB_C.cb, align 4 RWBuffer<float> Buf; diff --git a/clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl index 33f480bf445e..b7bdce32e650 100644 --- a/clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl +++ b/clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl @@ -1,54 +1,54 @@ -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s
-
-// Make sure cbuffer inside namespace works.
-
-// CHECK: %"n0::n1::__cblayout_A" = type <{ float }>
-// CHECK: %"n0::__cblayout_B" = type <{ float }>
-// CHECK: %"n0::n2::__cblayout_C" = type <{ float, target("dx.Layout", %"n0::Foo", 4, 0) }>
-// CHECK: %"n0::Foo" = type <{ float }>
-
-// CHECK: @A.cb = global target("dx.CBuffer", target("dx.Layout", %"n0::n1::__cblayout_A", 4, 0))
-// CHECK: @_ZN2n02n11aE = external hidden addrspace(2) global float, align 4
-
-// CHECK: @B.cb = global target("dx.CBuffer", target("dx.Layout", %"n0::__cblayout_B", 4, 0))
-// CHECK: @_ZN2n01aE = external hidden addrspace(2) global float, align 4
-
-// CHECK: @C.cb = global target("dx.CBuffer", target("dx.Layout", %"n0::n2::__cblayout_C", 20, 0, 16))
-// CHECK: @_ZN2n02n21aE = external hidden addrspace(2) global float, align 4
-// CHECK: external hidden addrspace(2) global target("dx.Layout", %"n0::Foo", 4, 0), align 1
-
-namespace n0 {
- struct Foo {
- float f;
- };
-
- namespace n1 {
- cbuffer A {
- float a;
- }
- }
- cbuffer B {
- float a;
- }
- namespace n2 {
- cbuffer C {
- float a;
- Foo b;
- }
- }
-}
-
-float foo() {
- // CHECK: load float, ptr addrspace(2) @_ZN2n02n11aE, align 4
- // CHECK: load float, ptr addrspace(2) @_ZN2n01aE, align 4
- // CHECK: load float, ptr addrspace(2) @_ZN2n02n21aE, align 4
- return n0::n1::a + n0::a + n0::n2::a;
-}
-
-[numthreads(4,1,1)]
-void main() {}
-
-// CHECK: !hlsl.cbs = !{![[A:[0-9]+]], ![[B:[0-9]+]], ![[C:[0-9]+]]}
-// CHECK: [[A]] = !{ptr @A.cb, ptr addrspace(2) @_ZN2n02n11aE}
-// CHECK: [[B]] = !{ptr @B.cb, ptr addrspace(2) @_ZN2n01aE}
-// CHECK: [[C]] = !{ptr @C.cb, ptr addrspace(2) @_ZN2n02n21aE, ptr addrspace(2) @_ZN2n02n21bE}
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// Make sure cbuffer inside namespace works. + +// CHECK: %"n0::n1::__cblayout_A" = type <{ float }> +// CHECK: %"n0::__cblayout_B" = type <{ float }> +// CHECK: %"n0::n2::__cblayout_C" = type <{ float, target("dx.Layout", %"n0::Foo", 4, 0) }> +// CHECK: %"n0::Foo" = type <{ float }> + +// CHECK: @A.cb = global target("dx.CBuffer", target("dx.Layout", %"n0::n1::__cblayout_A", 4, 0)) +// CHECK: @_ZN2n02n11aE = external hidden addrspace(2) global float, align 4 + +// CHECK: @B.cb = global target("dx.CBuffer", target("dx.Layout", %"n0::__cblayout_B", 4, 0)) +// CHECK: @_ZN2n01aE = external hidden addrspace(2) global float, align 4 + +// CHECK: @C.cb = global target("dx.CBuffer", target("dx.Layout", %"n0::n2::__cblayout_C", 20, 0, 16)) +// CHECK: @_ZN2n02n21aE = external hidden addrspace(2) global float, align 4 +// CHECK: external hidden addrspace(2) global target("dx.Layout", %"n0::Foo", 4, 0), align 1 + +namespace n0 { + struct Foo { + float f; + }; + + namespace n1 { + cbuffer A { + float a; + } + } + cbuffer B { + float a; + } + namespace n2 { + cbuffer C { + float a; + Foo b; + } + } +} + +float foo() { + // CHECK: load float, ptr addrspace(2) @_ZN2n02n11aE, align 4 + // CHECK: load float, ptr addrspace(2) @_ZN2n01aE, align 4 + // CHECK: load float, ptr addrspace(2) @_ZN2n02n21aE, align 4 + return n0::n1::a + n0::a + n0::n2::a; +} + +[numthreads(4,1,1)] +void main() {} + +// CHECK: !hlsl.cbs = !{![[A:[0-9]+]], ![[B:[0-9]+]], ![[C:[0-9]+]]} +// CHECK: [[A]] = !{ptr @A.cb, ptr addrspace(2) @_ZN2n02n11aE} +// CHECK: [[B]] = !{ptr @B.cb, ptr addrspace(2) @_ZN2n01aE} +// CHECK: [[C]] = !{ptr @C.cb, ptr addrspace(2) @_ZN2n02n21aE, ptr addrspace(2) @_ZN2n02n21bE} diff --git a/clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl index 16d22a5b1fdd..7bedd63c9f65 100644 --- a/clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl +++ b/clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl @@ -31,7 +31,7 @@ cbuffer CB : register(b0) { // CHECK: define internal void @_init_buffer_CB.cb() // CHECK-NEXT: entry: // CHECK-NEXT: %CB.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 176, 16, 168, 88)) -// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_176_16_168_88tt(i32 3, i32 1, i32 1, i32 0, i1 false, ptr @CB.str) +// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_176_16_168_88tt(i32 3, i32 1, i32 1, i32 0, ptr @CB.str) float foo() { // CHECK: load float, ptr addrspace(2) @a, align 4 diff --git a/clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl index cda231d8d2eb..fa3405df9e3d 100644 --- a/clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl +++ b/clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl @@ -1,29 +1,29 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s
-
-// CHECK: %__cblayout_A = type <{ float }>
-
-// CHECK: @A.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_A, 4, 0))
-// CHECK: @a = external hidden addrspace(2) global float, align 4
-// CHECK-DAG: @_ZL1b = internal global float 3.000000e+00, align 4
-// CHECK-NOT: @B.cb
-
-cbuffer A {
- float a;
- static float b = 3;
- float foo() { return a + b; }
-}
-
-cbuffer B {
- // intentionally empty
-}
-
-// CHECK: define {{.*}} float @_Z3foov() #0 {
-// CHECK: load float, ptr addrspace(2) @a, align 4
-// CHECK: load float, ptr @_ZL1b, align 4
-
-extern float bar() {
- return foo();
-}
-
-// CHECK: !hlsl.cbs = !{![[CB:[0-9]+]]}
-// CHECK: ![[CB]] = !{ptr @A.cb, ptr addrspace(2) @a}
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: %__cblayout_A = type <{ float }> + +// CHECK: @A.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_A, 4, 0)) +// CHECK: @a = external hidden addrspace(2) global float, align 4 +// CHECK-DAG: @_ZL1b = internal global float 3.000000e+00, align 4 +// CHECK-NOT: @B.cb + +cbuffer A { + float a; + static float b = 3; + float foo() { return a + b; } +} + +cbuffer B { + // intentionally empty +} + +// CHECK: define {{.*}} float @_Z3foov() #0 { +// CHECK: load float, ptr addrspace(2) @a, align 4 +// CHECK: load float, ptr @_ZL1b, align 4 + +extern float bar() { + return foo(); +} + +// CHECK: !hlsl.cbs = !{![[CB:[0-9]+]]} +// CHECK: ![[CB]] = !{ptr @A.cb, ptr addrspace(2) @a} diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl index 5b62452ef984..bbd162e3aad2 100644 --- a/clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl +++ b/clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl @@ -1,29 +1,29 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
-
-// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1
-
-RWBuffer<float> A[4][3] : register(u2);
-RWStructuredBuffer<float> Out;
-
-// Make sure A[GI.x][GI.y] is translated to a RWBuffer<float> constructor call with range 12 and dynamically calculated index
-
-// NOTE:
-// Constructor call for explicit binding has "jjij" in the mangled name and the arguments are (register, space, range_size, index, name).
-
-// CHECK: define internal void @_Z4mainDv3_j(<3 x i32> noundef %GI)
-// CHECK: %[[GI_alloca:.*]] = alloca <3 x i32>, align 16
-// CHECK: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer
-// CHECK: store <3 x i32> %GI, ptr %[[GI_alloca]]
-
-// CHECK: %[[GI:.*]] = load <3 x i32>, ptr %[[GI_alloca]], align 16
-// CHECK: %[[GI_y:.*]] = extractelement <3 x i32> %[[GI]], i32 1
-// CHECK: %[[GI:.*]] = load <3 x i32>, ptr %[[GI_alloca]], align 16
-// CHECK: %[[GI_x:.*]] = extractelement <3 x i32> %[[GI]], i32 0
-// CHECK: %[[Tmp1:.*]] = mul i32 %[[GI_x]], 3
-// CHECK: %[[Index:.*]] = add i32 %[[GI_y]], %[[Tmp1]]
-// CHECK: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 2, i32 noundef 0, i32 noundef 12, i32 noundef %[[Index]], ptr noundef @A.str)
-[numthreads(4,1,1)]
-void main(uint3 GI : SV_GroupThreadID) {
- Out[0] = A[GI.x][GI.y][0];
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1 + +RWBuffer<float> A[4][3] : register(u2); +RWStructuredBuffer<float> Out; + +// Make sure A[GI.x][GI.y] is translated to a RWBuffer<float> constructor call with range 12 and dynamically calculated index + +// NOTE: +// Constructor call for explicit binding has "jjij" in the mangled name and the arguments are (register, space, range_size, index, name). + +// CHECK: define internal void @_Z4mainDv3_j(<3 x i32> noundef %GI) +// CHECK: %[[GI_alloca:.*]] = alloca <3 x i32>, align 16 +// CHECK: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer +// CHECK: store <3 x i32> %GI, ptr %[[GI_alloca]] + +// CHECK: %[[GI:.*]] = load <3 x i32>, ptr %[[GI_alloca]], align 16 +// CHECK: %[[GI_y:.*]] = extractelement <3 x i32> %[[GI]], i32 1 +// CHECK: %[[GI:.*]] = load <3 x i32>, ptr %[[GI_alloca]], align 16 +// CHECK: %[[GI_x:.*]] = extractelement <3 x i32> %[[GI]], i32 0 +// CHECK: %[[Tmp1:.*]] = mul i32 %[[GI_x]], 3 +// CHECK: %[[Index:.*]] = add i32 %[[GI_y]], %[[Tmp1]] +// CHECK: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 2, i32 noundef 0, i32 noundef 12, i32 noundef %[[Index]], ptr noundef @A.str) +[numthreads(4,1,1)] +void main(uint3 GI : SV_GroupThreadID) { + Out[0] = A[GI.x][GI.y][0]; +} diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl index 8d664dad5815..36871f9a63b3 100644 --- a/clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl +++ b/clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl @@ -1,46 +1,46 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
-// RUN: %clang_cc1 -finclude-default-header -triple spirv-unknown-vulkan-compute \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
-
-// CHECK: @[[BufB:.*]] = private unnamed_addr constant [2 x i8] c"B\00", align 1
-// CHECK: @[[BufC:.*]] = private unnamed_addr constant [2 x i8] c"C\00", align 1
-// CHECK: @[[BufD:.*]] = private unnamed_addr constant [2 x i8] c"D\00", align 1
-
-RWBuffer<float> B[4][4] : register(u2);
-RWBuffer<int> C[2][2][5] : register(u10, space1);
-
-typedef RWBuffer<uint> RWBufferArrayTenByFive[10][5]; // test typedef for the resource array type
-RWBufferArrayTenByFive D; // implicit binding -> u18, space0
-
-RWStructuredBuffer<float> Out;
-
-[numthreads(4,1,1)]
-void main() {
- // CHECK: define internal{{.*}} void @_Z4mainv()
- // CHECK: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer
- // CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::RWBuffer
- // CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer
- // CHECK: %[[Tmp3:.*]] = alloca %"class.hlsl::RWBuffer
-
- // NOTE:
- // Constructor call for explicit binding has "jjij" in the mangled name and the arguments are (register, space, range_size, index, name).
- // For implicit binding the constructor has "jijj" in the mangled name and the arguments are (space, range_size, index, order_id, name).
- // The range_size can be -1 for unbounded arrays, and that is the only signed int in the signature.
- // The order_id argument is a sequential number that is assigned to resources with implicit binding and corresponds to the order in which
- // the resources were declared. It is needed because implicit bindings are assigned later on in an LLVM pass that needs to know the order
- // of the resource declarations.
-
- // Make sure that B[3][2] is translated to a RWBuffer<float> constructor call for explicit binding (u2, space0) with range 16 and index 14
- // CHECK: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 2, i32 noundef 0, i32 noundef 16, i32 noundef 14, ptr noundef @[[BufB]])
-
- // Make sure that C[1][0][3] is translated to a RWBuffer<int> constructor call for explicit binding (u10, space1) with range 20 and index 13
- // CHECK: call void @_ZN4hlsl8RWBufferIiEC1EjjijPKc(ptr {{.*}} %[[Tmp1]], i32 noundef 10, i32 noundef 1, i32 noundef 20, i32 noundef 13, ptr noundef @[[BufC]])
-
- // Make sure that D[9][2] is translated to a RWBuffer<uint> constructor call for implicit binding (u18, space0) with range 50 and index 47
- // CHECK: call void @_ZN4hlsl8RWBufferIjEC1EjijjPKc(ptr {{.*}} %[[Tmp2]], i32 noundef 0, i32 noundef 50, i32 noundef 47, i32 noundef 0, ptr noundef @[[BufD]])
-
- // Make sure that the second B[3][2] is translated to the same a RWBuffer<float> constructor call as the first B[3][2] subscript
- // CHECK: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp3]], i32 noundef 2, i32 noundef 0, i32 noundef 16, i32 noundef 14, ptr noundef @[[BufB]])
- Out[0] = B[3][2][0] + (float)C[1][0][3][0] + (float)D[9][2][0] + B[3][2][1];
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s +// RUN: %clang_cc1 -finclude-default-header -triple spirv-unknown-vulkan-compute \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +// CHECK: @[[BufB:.*]] = private unnamed_addr constant [2 x i8] c"B\00", align 1 +// CHECK: @[[BufC:.*]] = private unnamed_addr constant [2 x i8] c"C\00", align 1 +// CHECK: @[[BufD:.*]] = private unnamed_addr constant [2 x i8] c"D\00", align 1 + +RWBuffer<float> B[4][4] : register(u2); +RWBuffer<int> C[2][2][5] : register(u10, space1); + +typedef RWBuffer<uint> RWBufferArrayTenByFive[10][5]; // test typedef for the resource array type +RWBufferArrayTenByFive D; // implicit binding -> u18, space0 + +RWStructuredBuffer<float> Out; + +[numthreads(4,1,1)] +void main() { + // CHECK: define internal{{.*}} void @_Z4mainv() + // CHECK: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer + // CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::RWBuffer + // CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer + // CHECK: %[[Tmp3:.*]] = alloca %"class.hlsl::RWBuffer + + // NOTE: + // Constructor call for explicit binding has "jjij" in the mangled name and the arguments are (register, space, range_size, index, name). + // For implicit binding the constructor has "jijj" in the mangled name and the arguments are (space, range_size, index, order_id, name). + // The range_size can be -1 for unbounded arrays, and that is the only signed int in the signature. + // The order_id argument is a sequential number that is assigned to resources with implicit binding and corresponds to the order in which + // the resources were declared. It is needed because implicit bindings are assigned later on in an LLVM pass that needs to know the order + // of the resource declarations. + + // Make sure that B[3][2] is translated to a RWBuffer<float> constructor call for explicit binding (u2, space0) with range 16 and index 14 + // CHECK: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 2, i32 noundef 0, i32 noundef 16, i32 noundef 14, ptr noundef @[[BufB]]) + + // Make sure that C[1][0][3] is translated to a RWBuffer<int> constructor call for explicit binding (u10, space1) with range 20 and index 13 + // CHECK: call void @_ZN4hlsl8RWBufferIiEC1EjjijPKc(ptr {{.*}} %[[Tmp1]], i32 noundef 10, i32 noundef 1, i32 noundef 20, i32 noundef 13, ptr noundef @[[BufC]]) + + // Make sure that D[9][2] is translated to a RWBuffer<uint> constructor call for implicit binding (u18, space0) with range 50 and index 47 + // CHECK: call void @_ZN4hlsl8RWBufferIjEC1EjijjPKc(ptr {{.*}} %[[Tmp2]], i32 noundef 0, i32 noundef 50, i32 noundef 47, i32 noundef 0, ptr noundef @[[BufD]]) + + // Make sure that the second B[3][2] is translated to the same a RWBuffer<float> constructor call as the first B[3][2] subscript + // CHECK: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp3]], i32 noundef 2, i32 noundef 0, i32 noundef 16, i32 noundef 14, ptr noundef @[[BufB]]) + Out[0] = B[3][2][0] + (float)C[1][0][3][0] + (float)D[9][2][0] + B[3][2][1]; +} diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl new file mode 100644 index 000000000000..7c52c7116f3d --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl @@ -0,0 +1,109 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1 + +RWBuffer<float> A[5][4][3][2] : register(u10, space2); +RWStructuredBuffer<float> Out; + +// CHECK: define {{.*}} float @_Z3fooA3_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([3 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %Arr) +// CHECK-NEXT: entry: +float foo(RWBuffer<float> Arr[3][2]) { +// CHECK-NEXT: %[[Arr_1_Ptr:.*]] = getelementptr inbounds [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %Arr, i32 0, i32 1 +// CHECK-NEXT: %[[Arr_1_0_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %[[Arr_1_Ptr]], i32 0, i32 0 +// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Arr_1_0_Ptr]], i32 noundef 0) +// CHECK-NEXT: %[[Value:.*]] = load float, ptr %[[BufPtr]], align 4 +// CHECK-NEXT: ret float %[[Value]] + return Arr[1][0][0]; +} + +// NOTE: +// - _ZN4hlsl8RWBufferIfEC1EjjijPKc is the constructor call for explicit binding +// (has "jjij" in the mangled name) and the arguments are (register, space, range_size, index, name). +// - _ZN4hlsl8RWBufferIfEixEj is the subscript operator for RWBuffer<float> + +// CHECK: define internal void @_Z4mainj(i32 noundef %GI) +// CHECK-NEXT: entry: +// CHECK-NEXT: %[[GI_alloca:.*]] = alloca i32, align 4 +// CHECK-NEXT: %Sub = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4 +// CHECK-NEXT: %[[Tmp0:.*]] = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4 +// CHECK-NEXT: %a = alloca float, align 4 +// CHECK-NEXT: %b = alloca float, align 4 +// CHECK-NEXT: %[[Tmp1:.*]] = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4 +// CHECK-NEXT: %[[Tmp2:.*]] = alloca [3 x [2 x %"class.hlsl::RWBuffer"]], align 4 +// CHECK-NEXT: store i32 %GI, ptr %[[GI_alloca]], align 4 +[numthreads(4,1,1)] +void main(uint GI : SV_GroupThreadID) { +// Codegen for "A[4][1]" - create local array [[Tmp0]] of size 3 x 2 and initialize +// each element by a call to the resource constructor +// The resource index for A[4][1][0][0] is 102 = 4 * (4 * 3 * 2) + 1 * (3 * 2) +// (index in the resource array as if it was flattened) +// CHECK-NEXT: %[[Ptr_Tmp0_0_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 0, i32 0 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_0_0]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 102, ptr noundef @[[BufA]]) +// CHECK-NEXT: %[[Ptr_Tmp0_0_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 0, i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_0_1]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 103, ptr noundef @[[BufA]]) +// CHECK-NEXT: %[[Ptr_Tmp0_1_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 1, i32 0 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_1_0]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 104, ptr noundef @[[BufA]]) +// CHECK-NEXT: %[[Ptr_Tmp0_1_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 1, i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_1_1]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 105, ptr noundef @[[BufA]]) +// CHECK-NEXT: %[[Ptr_Tmp0_2_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 2, i32 0 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_2_0]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 106, ptr noundef @[[BufA]]) +// CHECK-NEXT: %[[Ptr_Tmp0_2_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %tmp, i32 0, i32 2, i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_2_1]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef 107, ptr noundef @[[BufA]]) +// After this Tmp0 values are copied to %Sub using the standard array loop initializaion +// (generated from ArrayInitLoopExpr AST node) + RWBuffer<float> Sub[3][2] = A[4][1]; + +// CHECK: %[[Ptr_Sub_2:.*]] = getelementptr inbounds [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %Sub, i32 0, i32 2 +// CHECK: %[[Ptr_Sub_2_1:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %[[Ptr_Sub_2]], i32 0, i32 1 +// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Ptr_Sub_2_1]], i32 noundef 0) +// CHECK-NEXT: %[[Sub_2_1_0_Value:.*]] = load float, ptr %[[BufPtr]], align 4 +// CHECK-NEXT: store float %[[Sub_2_1_0_Value]], ptr %a, align 4 + float a = Sub[2][1][0]; + +// Codegen for "foo(A[2][GI])" - create local array [[Tmp2]] of size 3 x 2 and initialize +// each element by a call to the resource constructor with dynamic index, and then +// copy-in the array as an argument of "foo" + +// Calculate the resource index for A[2][GI][0][0] (index in the resource array as if it was flattened) +// The index is 2 * (4 * 3 * 2) + GI * (3 * 2) = 48 + GI * 6 +// CHECK: %[[GI:.*]] = load i32, ptr %[[GI_alloca]], align 4 +// CHECK-NEXT: %[[Index_A_2_GI_Tmp:.*]] = mul i32 %[[GI]], 6 +// CHECK-NEXT: %[[Index_A_2_GI_0_0:.*]] = add i32 %[[Index_A_2_GI_Tmp]], 48 + +// A[2][GI][0][0] +// CHECK-NEXT: %[[Ptr_Tmp2_0_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 0, i32 0 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_0_0]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_0_0]], ptr noundef @[[BufA]]) + +// A[2][GI][0][1] +// CHECK-NEXT: %[[Index_A_2_GI_0_1:.*]] = add i32 %[[Index_A_2_GI_0_0]], 1 +// CHECK-NEXT: %[[Ptr_Tmp2_0_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 0, i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_0_1]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_0_1]], ptr noundef @[[BufA]]) + +// A[2][GI][1][0] +// CHECK-NEXT: %[[Index_A_2_GI_1_0:.*]] = add i32 %[[Index_A_2_GI_0_1]], 1 +// CHECK-NEXT: %[[Ptr_Tmp2_1_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 1, i32 0 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_1_0]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_1_0]], ptr noundef @[[BufA]]) + +// A[2][GI][1][1] +// CHECK-NEXT: %[[Index_A_2_GI_1_1:.*]] = add i32 %[[Index_A_2_GI_1_0]], 1 +// CHECK-NEXT: %[[Ptr_Tmp2_1_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 1, i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_1_1]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_1_1]], ptr noundef @[[BufA]]) + +// A[2][GI][2][0] +// CHECK-NEXT: %[[Index_A_2_GI_2_0:.*]] = add i32 %[[Index_A_2_GI_1_1]], 1 +// CHECK-NEXT: %[[Ptr_Tmp2_2_0:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 2, i32 0 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_2_0]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_2_0]], ptr noundef @[[BufA]]) + +// A[2][GI][2][1] +// CHECK-NEXT: %[[Index_A_2_GI_2_1:.*]] = add i32 %[[Index_A_2_GI_2_0]], 1 +// CHECK-NEXT: %[[Ptr_Tmp2_2_1:.*]] = getelementptr [3 x [2 x %"class.hlsl::RWBuffer"]], ptr %[[Tmp2]], i32 0, i32 2, i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_2_1]], i32 noundef 10, i32 noundef 2, i32 noundef 120, i32 noundef %[[Index_A_2_GI_2_1]], ptr noundef @[[BufA]]) + +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp1]], ptr align 4 %[[Tmp2]], i32 24, i1 false) +// CHECK-NEXT: %[[FooReturned:.*]] = call {{.*}} float @_Z3fooA3_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([3 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %[[Tmp1]]) +// CHECK-NEXT: store float %[[FooReturned]], ptr %b, align 4 + float b = foo(A[2][GI]); + + Out[0] = a + b; +} diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-subarray-one.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-one.hlsl new file mode 100644 index 000000000000..5caf2b6db4c8 --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/res-array-global-subarray-one.hlsl @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1 + +RWBuffer<float> A[4][2] : register(u10, space2); +RWStructuredBuffer<float> Out; + +float foo(RWBuffer<float> Arr[2]) { + return Arr[1][0]; +} + +// NOTE: +// - _ZN4hlsl8RWBufferIfEC1EjjijPKc is the constructor call for explicit binding +// (has "jjij" in the mangled name) and the arguments are (register, space, range_size, index, name). +// - _ZN4hlsl8RWBufferIfEixEj is the subscript operator for RWBuffer<float> + +// CHECK: define internal void @_Z4mainj(i32 noundef %GI) +// CHECK-NEXT: entry: +// CHECK-NEXT: %[[GI_alloca:.*]] = alloca i32, align 4 +// CHECK-NEXT: %Sub = alloca [2 x %"class.hlsl::RWBuffer"], align 4 +// CHECK-NEXT: %[[Tmp0:.*]] = alloca [2 x %"class.hlsl::RWBuffer"], align 4 +// CHECK-NEXT: %a = alloca float, align 4 +// CHECK-NEXT: %b = alloca float, align 4 +// CHECK-NEXT: %[[Tmp1:.*]] = alloca [2 x %"class.hlsl::RWBuffer"], align 4 +// CHECK-NEXT: %[[Tmp2:.*]] = alloca [2 x %"class.hlsl::RWBuffer"], align 4 +// CHECK-NEXT: store i32 %GI, ptr %[[GI_alloca]], align 4 +[numthreads(4,1,1)] +void main(uint GI : SV_GroupThreadID) { +// Codegen for "A[2]" - create local array [[Tmp0]] of size 2 and initialize +// each element by a call to the resource constructor +// CHECK-NEXT: %[[Ptr_Tmp0_0:.*]] = getelementptr [2 x %"class.hlsl::RWBuffer"], ptr %[[Tmp0]], i32 0, i32 0 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_0]], i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef 6, ptr noundef @[[BufA]]) +// CHECK-NEXT: %[[Ptr_Tmp0_1:.*]] = getelementptr [2 x %"class.hlsl::RWBuffer"], ptr %[[Tmp0]], i32 0, i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp0_1]], i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef 7, ptr noundef @[[BufA]]) +// After this Tmp0 values are copied to %Sub using the standard array loop initializaion +// (generated from ArrayInitLoopExpr AST node) + RWBuffer<float> Sub[2] = A[3]; + +// CHECK: %[[Ptr_Sub_1:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %Sub, i32 0, i32 1 +// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Ptr_Sub_1]], i32 noundef 0) +// CHECK-NEXT: %[[Sub_1_0_Value:.*]] = load float, ptr %[[BufPtr]], align 4 +// CHECK-NEXT: store float %[[Sub_1_0_Value]], ptr %a, align 4 + float a = Sub[1][0]; + +// Codegen for "foo(A[GI])" - create local array [[Tmp2]] of size 2 and initialize +// each element by a call to the resource constructor with dynamic index, and then +// copy-in the array as an argument of "foo" +// CHECK: %[[GI:.*]] = load i32, ptr %[[GI_alloca]], align 4 +// CHECK-NEXT: %[[Index_A_GI_0:.*]] = mul i32 %[[GI]], 2 +// CHECK-NEXT: %[[Ptr_Tmp2_GI_0:.*]] = getelementptr [2 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 0 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_GI_0]], i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef %[[Index_A_GI_0]], ptr noundef @[[BufA]]) +// CHECK-NEXT: %[[Index_A_GI_1:.*]] = add i32 %[[Index_A_GI_0]], 1 +// CHECK-NEXT: %[[Ptr_Tmp2_GI_1:.*]] = getelementptr [2 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Ptr_Tmp2_GI_1]], i32 noundef 10, i32 noundef 2, i32 noundef 8, i32 noundef %[[Index_A_GI_1]], ptr noundef @[[BufA]]) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp1]], ptr align 4 %[[Tmp2]], i32 8, i1 false) +// CHECK-NEXT: %[[FooReturned:.*]] = call {{.*}} float @_Z3fooA2_N4hlsl8RWBufferIfEE(ptr noundef byval([2 x %"class.hlsl::RWBuffer"]) align 4 %[[Tmp1]]) +// CHECK-NEXT: store float %[[FooReturned]], ptr %b, align 4 + float b = foo(A[GI]); + + Out[0] = a + b; +} diff --git a/clang/test/CodeGenHLSL/resources/res-array-global-unbounded.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global-unbounded.hlsl new file mode 100644 index 000000000000..edf9ce01f72a --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/res-array-global-unbounded.hlsl @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s -check-prefixes=CHECK,DXIL
+// RUN: %clang_cc1 -finclude-default-header -triple spirv-unknown-vulkan-compute \
+// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s -check-prefixes=CHECK,SPV
+
+// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1
+// CHECK: @[[BufB:.*]] = private unnamed_addr constant [2 x i8] c"B\00", align 1
+
+RWBuffer<float> A[] : register(u10, space1);
+RWBuffer<int> B[][5][4];
+
+RWStructuredBuffer<float> Out;
+
+float foo(RWBuffer<int> Arr[4], uint Index) {
+ return (float)Arr[Index][0];
+}
+
+// NOTE:
+// - _ZN4hlsl8RWBufferIfEC1EjjijPKc is the constructor call for explicit binding for RWBuffer<float>
+// (has "jjij" in the mangled name) and the arguments are (register, space, range_size, index, name).
+// - _ZN4hlsl8RWBufferIiEC1EjijjPKc is the constructor call for implicit binding for RWBuffer<int>
+// (has "jijj" in the mangled name) and the arguments are (space, range_size, index, order_id, name).
+// - _ZN4hlsl8RWBufferIfEixEj is the subscript operator on RWBuffer<float>
+
+[numthreads(4,1,1)]
+void main(uint GI : SV_GroupIndex) {
+ // CHECK: define internal {{.*}}void @_Z4mainj(i32 noundef %GI)
+ // CHECK: %[[GI_alloca:.*]] = alloca i32, align 4
+ // CHECK-NEXT: %a = alloca float, align 4
+ // CHECK-NEXT: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer
+ // CHECK-NEXT: %b = alloca float, align 4
+ // CHECK-NEXT: %[[Tmp1:.*]] = alloca [4 x %"class.hlsl::RWBuffer"]
+ // CHECK-NEXT: %[[Tmp2:.*]] = alloca [4 x %"class.hlsl::RWBuffer"]
+ // CHECK-NEXT: store i32 %GI, ptr %[[GI_alloca]], align 4
+
+ // Make sure A[100] is translated to a RWBuffer<float> constructor call with range -1 and index 100
+ // and explicit binding (u10, space1)
+ // CHECK: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 10, i32 noundef 1, i32 noundef -1, i32 noundef 100, ptr noundef @A.str)
+ // CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr{{.*}} @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Tmp0]], i32 noundef 0)
+ // CHECK-NEXT: %[[Value1:.*]] = load float, ptr{{.*}} %[[BufPtr]], align 4
+ // CHECK-NEXT: store float %[[Value1]], ptr %a, align 4
+ float a = A[100][0];
+
+ // Make sure B[2][3] is translated to a local RWBuffer<int>[4] array where each array element
+ // is initialized by a constructor call with range -1 and index 52-55 and implicit binding
+ // (space 0, order_id 0)
+ // The first index is calculated from the array dimensions (unbounded x 5 x 4) and indices (2, 3)
+ // as 2 * 5 * 4 + 3 * 4 = 52 and the following indices are sequential.
+ // CHECK-NEXT: %[[Ptr_Tmp2_0:.*]] = getelementptr [4 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 0
+ // CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc(ptr {{.*}} %[[Ptr_Tmp2_0]], i32 noundef 0, i32 noundef -1, i32 noundef 52, i32 noundef 0, ptr noundef @B.str)
+ // CHECK-NEXT: %[[Ptr_Tmp2_1:.*]] = getelementptr [4 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 1
+ // CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc(ptr {{.*}} %[[Ptr_Tmp2_1]], i32 noundef 0, i32 noundef -1, i32 noundef 53, i32 noundef 0, ptr noundef @B.str)
+ // CHECK-NEXT: %[[Ptr_Tmp2_2:.*]] = getelementptr [4 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 2
+ // CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc(ptr {{.*}} %[[Ptr_Tmp2_2]], i32 noundef 0, i32 noundef -1, i32 noundef 54, i32 noundef 0, ptr noundef @B.str)
+ // CHECK-NEXT: %[[Ptr_Tmp2_3:.*]] = getelementptr [4 x %"class.hlsl::RWBuffer"], ptr %[[Tmp2]], i32 0, i32 3
+ // CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc(ptr {{.*}} %[[Ptr_Tmp2_3]], i32 noundef 0, i32 noundef -1, i32 noundef 55, i32 noundef 0, ptr noundef @B.str)
+ // DXIL-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp1]], ptr align 4 %[[Tmp2]], i32 16, i1 false)
+ // SPV-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[Tmp1]], ptr align 8 %[[Tmp2]], i64 32, i1 false)
+ // CHECK-NEXT: %[[GI:.*]] = load i32, ptr %[[GI_alloca]], align 4
+ // DXIL-NEXT: %[[Value2:.*]] = call {{.*}} float @_Z3fooA4_N4hlsl8RWBufferIiEEj(ptr noundef byval([4 x %"class.hlsl::RWBuffer"]) align 4 %[[Tmp1]], i32 noundef %[[GI]])
+ // SPV-NEXT: %[[Value2:.*]] = call {{.*}} float @_Z3fooA4_N4hlsl8RWBufferIiEEj(ptr noundef byval([4 x %"class.hlsl::RWBuffer"]) align 8 %[[Tmp1]], i32 noundef %[[GI]])
+ // CHECK-NEXT: store float %[[Value2]], ptr %b, align 4
+ float b = foo(B[2][3], GI);
+
+ Out[0] = a + b;
+}
diff --git a/clang/test/CodeGenHLSL/resources/res-array-global.hlsl b/clang/test/CodeGenHLSL/resources/res-array-global.hlsl index 595ea818e913..0abdf5f88cf6 100644 --- a/clang/test/CodeGenHLSL/resources/res-array-global.hlsl +++ b/clang/test/CodeGenHLSL/resources/res-array-global.hlsl @@ -1,75 +1,75 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s -check-prefixes=CHECK,DXIL
-// RUN: %clang_cc1 -finclude-default-header -triple spirv-unknown-vulkan-compute \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s -check-prefixes=CHECK,SPV
-
-// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1
-// CHECK: @[[BufB:.*]] = private unnamed_addr constant [2 x i8] c"B\00", align 1
-// CHECK: @[[BufC:.*]] = private unnamed_addr constant [2 x i8] c"C\00", align 1
-// CHECK: @[[BufD:.*]] = private unnamed_addr constant [2 x i8] c"D\00", align 1
-// CHECK: @[[BufE:.*]] = private unnamed_addr constant [2 x i8] c"E\00", align 1
-
-// different explicit binding for DXIL and SPIR-V
-[[vk::binding(12, 2)]]
-RWBuffer<float> A[4] : register(u10, space1);
-
-[[vk::binding(13)]] // SPIR-V explicit binding 13, set 0
-RWBuffer<int> B[5]; // DXIL implicit binding in space0
-
-// same explicit binding for both DXIL and SPIR-V
-// (SPIR-V takes the binding from register annotation if there is no vk::binding attribute))
-RWBuffer<int> C[3] : register(u2);
-
-// implicit binding for both DXIL and SPIR-V in space/set 0
-RWBuffer<double> D[10];
-
-// implicit binding for both DXIL and SPIR-V with specified space/set 0
-RWBuffer<uint> E[15] : register(space2);
-
-RWStructuredBuffer<float> Out;
-
-[numthreads(4,1,1)]
-void main() {
- // CHECK: define internal{{.*}} void @_Z4mainv()
- // CHECK: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer
- // CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::RWBuffer
- // CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer
- // CHECK: %[[Tmp3:.*]] = alloca %"class.hlsl::RWBuffer
- // CHECK: %[[Tmp4:.*]] = alloca %"class.hlsl::RWBuffer
-
- // NOTE:
- // Constructor call for explicit binding has "jjij" in the mangled name and the arguments are (register, space, range_size, index, name).
- // For implicit binding the constructor has "jijj" in the mangled name and the arguments are (space, range_size, index, order_id, name).
- // The range_size can be -1 for unbounded arrays, and that is the only signed int in the signature.
- // The order_id argument is a sequential number that is assigned to resources with implicit binding and corresponds to the order in which
- // the resources were declared. It is needed because implicit bindings are assigned later on in an LLVM pass that needs to know the order
- // of the resource declarations.
-
- // Make sure A[2] is translated to a RWBuffer<float> constructor call with range 4 and index 2
- // and DXIL explicit binding (u10, space1)
- // and SPIR-V explicit binding (binding 12, set 2)
- // DXIL: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 10, i32 noundef 1, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]])
- // SPV: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 12, i32 noundef 2, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]])
-
- // Make sure B[3] is translated to a RWBuffer<int> constructor call with range 5 and index 3
- // and DXIL for implicit binding in space0, order id 0
- // and SPIR-V explicit binding (binding 13, set 0)
- // DXIL: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc(ptr {{.*}} %[[Tmp1]], i32 noundef 0, i32 noundef 5, i32 noundef 3, i32 noundef 0, ptr noundef @[[BufB]])
- // SPV: call void @_ZN4hlsl8RWBufferIiEC1EjjijPKc(ptr {{.*}} %[[Tmp1]], i32 noundef 13, i32 noundef 0, i32 noundef 5, i32 noundef 3, ptr noundef @[[BufB]])
-
- // Make sure C[1] is translated to a RWBuffer<int> constructor call with range 3 and index 1
- // and DXIL explicit binding (u2, space0)
- // and SPIR-V explicit binding (binding 2, set 0)
- // DXIL: call void @_ZN4hlsl8RWBufferIiEC1EjjijPKc(ptr {{.*}} %[[Tmp2]], i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]])
- // SPV: call void @_ZN4hlsl8RWBufferIiEC1EjjijPKc(ptr {{.*}} %[[Tmp2]], i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]])
-
- // Make sure D[7] is translated to a RWBuffer<double> constructor call with implicit binding
- // for both DXIL and SPIR-V
- // DXIL: call void @_ZN4hlsl8RWBufferIdEC1EjijjPKc(ptr {{.*}} %[[Tmp3]], i32 noundef 0, i32 noundef 10, i32 noundef 7, i32 noundef 1, ptr noundef @[[BufD]])
- // SPV: call void @_ZN4hlsl8RWBufferIdEC1EjijjPKc(ptr {{.*}} %[[Tmp3]], i32 noundef 0, i32 noundef 10, i32 noundef 7, i32 noundef 0, ptr noundef @[[BufD]])
-
- // Make sure E[5][0] is translated to RWBuffer<uint> constructor call with implicit binding and specified space/set 2
- // DXIL: call void @_ZN4hlsl8RWBufferIjEC1EjijjPKc(ptr {{.*}} %[[Tmp4]], i32 noundef 2, i32 noundef 15, i32 noundef 5, i32 noundef 2, ptr noundef @[[BufE]])
- // SPV: call void @_ZN4hlsl8RWBufferIjEC1EjijjPKc(ptr {{.*}} %[[Tmp4]], i32 noundef 2, i32 noundef 15, i32 noundef 5, i32 noundef 1, ptr noundef @[[BufE]])
- Out[0] = A[2][0] + (float)B[3][0] + (float)C[1][0] + (float)D[7][0] + (float)E[5][0];
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s -check-prefixes=CHECK,DXIL +// RUN: %clang_cc1 -finclude-default-header -triple spirv-unknown-vulkan-compute \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s -check-prefixes=CHECK,SPV + +// CHECK: @[[BufA:.*]] = private unnamed_addr constant [2 x i8] c"A\00", align 1 +// CHECK: @[[BufB:.*]] = private unnamed_addr constant [2 x i8] c"B\00", align 1 +// CHECK: @[[BufC:.*]] = private unnamed_addr constant [2 x i8] c"C\00", align 1 +// CHECK: @[[BufD:.*]] = private unnamed_addr constant [2 x i8] c"D\00", align 1 +// CHECK: @[[BufE:.*]] = private unnamed_addr constant [2 x i8] c"E\00", align 1 + +// different explicit binding for DXIL and SPIR-V +[[vk::binding(12, 2)]] +RWBuffer<float> A[4] : register(u10, space1); + +[[vk::binding(13)]] // SPIR-V explicit binding 13, set 0 +RWBuffer<int> B[5]; // DXIL implicit binding in space0 + +// same explicit binding for both DXIL and SPIR-V +// (SPIR-V takes the binding from register annotation if there is no vk::binding attribute)) +RWBuffer<int> C[3] : register(u2); + +// implicit binding for both DXIL and SPIR-V in space/set 0 +RWBuffer<double> D[10]; + +// implicit binding for both DXIL and SPIR-V with specified space/set 0 +RWBuffer<uint> E[15] : register(space2); + +RWStructuredBuffer<float> Out; + +[numthreads(4,1,1)] +void main() { + // CHECK: define internal{{.*}} void @_Z4mainv() + // CHECK: %[[Tmp0:.*]] = alloca %"class.hlsl::RWBuffer + // CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::RWBuffer + // CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer + // CHECK: %[[Tmp3:.*]] = alloca %"class.hlsl::RWBuffer + // CHECK: %[[Tmp4:.*]] = alloca %"class.hlsl::RWBuffer + + // NOTE: + // Constructor call for explicit binding has "jjij" in the mangled name and the arguments are (register, space, range_size, index, name). + // For implicit binding the constructor has "jijj" in the mangled name and the arguments are (space, range_size, index, order_id, name). + // The range_size can be -1 for unbounded arrays, and that is the only signed int in the signature. + // The order_id argument is a sequential number that is assigned to resources with implicit binding and corresponds to the order in which + // the resources were declared. It is needed because implicit bindings are assigned later on in an LLVM pass that needs to know the order + // of the resource declarations. + + // Make sure A[2] is translated to a RWBuffer<float> constructor call with range 4 and index 2 + // and DXIL explicit binding (u10, space1) + // and SPIR-V explicit binding (binding 12, set 2) + // DXIL: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 10, i32 noundef 1, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]]) + // SPV: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr {{.*}} %[[Tmp0]], i32 noundef 12, i32 noundef 2, i32 noundef 4, i32 noundef 2, ptr noundef @[[BufA]]) + + // Make sure B[3] is translated to a RWBuffer<int> constructor call with range 5 and index 3 + // and DXIL for implicit binding in space0, order id 0 + // and SPIR-V explicit binding (binding 13, set 0) + // DXIL: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc(ptr {{.*}} %[[Tmp1]], i32 noundef 0, i32 noundef 5, i32 noundef 3, i32 noundef 0, ptr noundef @[[BufB]]) + // SPV: call void @_ZN4hlsl8RWBufferIiEC1EjjijPKc(ptr {{.*}} %[[Tmp1]], i32 noundef 13, i32 noundef 0, i32 noundef 5, i32 noundef 3, ptr noundef @[[BufB]]) + + // Make sure C[1] is translated to a RWBuffer<int> constructor call with range 3 and index 1 + // and DXIL explicit binding (u2, space0) + // and SPIR-V explicit binding (binding 2, set 0) + // DXIL: call void @_ZN4hlsl8RWBufferIiEC1EjjijPKc(ptr {{.*}} %[[Tmp2]], i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]]) + // SPV: call void @_ZN4hlsl8RWBufferIiEC1EjjijPKc(ptr {{.*}} %[[Tmp2]], i32 noundef 2, i32 noundef 0, i32 noundef 3, i32 noundef 1, ptr noundef @[[BufC]]) + + // Make sure D[7] is translated to a RWBuffer<double> constructor call with implicit binding + // for both DXIL and SPIR-V + // DXIL: call void @_ZN4hlsl8RWBufferIdEC1EjijjPKc(ptr {{.*}} %[[Tmp3]], i32 noundef 0, i32 noundef 10, i32 noundef 7, i32 noundef 1, ptr noundef @[[BufD]]) + // SPV: call void @_ZN4hlsl8RWBufferIdEC1EjijjPKc(ptr {{.*}} %[[Tmp3]], i32 noundef 0, i32 noundef 10, i32 noundef 7, i32 noundef 0, ptr noundef @[[BufD]]) + + // Make sure E[5][0] is translated to RWBuffer<uint> constructor call with implicit binding and specified space/set 2 + // DXIL: call void @_ZN4hlsl8RWBufferIjEC1EjijjPKc(ptr {{.*}} %[[Tmp4]], i32 noundef 2, i32 noundef 15, i32 noundef 5, i32 noundef 2, ptr noundef @[[BufE]]) + // SPV: call void @_ZN4hlsl8RWBufferIjEC1EjijjPKc(ptr {{.*}} %[[Tmp4]], i32 noundef 2, i32 noundef 15, i32 noundef 5, i32 noundef 1, ptr noundef @[[BufE]]) + Out[0] = A[2][0] + (float)B[3][0] + (float)C[1][0] + (float)D[7][0] + (float)E[5][0]; +} diff --git a/clang/test/CodeGenHLSL/resources/res-array-local-multi-dim.hlsl b/clang/test/CodeGenHLSL/resources/res-array-local-multi-dim.hlsl index d803882fd2f7..92dba219f229 100644 --- a/clang/test/CodeGenHLSL/resources/res-array-local-multi-dim.hlsl +++ b/clang/test/CodeGenHLSL/resources/res-array-local-multi-dim.hlsl @@ -1,49 +1,65 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
-
-// This test verifies handling of multi-dimensional local arrays of resources
-// when used as a function argument and local variable.
-
-// CHECK: @_ZL1A = internal global %"class.hlsl::RWBuffer" poison, align 4
-// CHECK: @_ZL1B = internal global %"class.hlsl::RWBuffer" poison, align 4
-
-RWBuffer<float> A : register(u10);
-RWBuffer<float> B : register(u20);
-RWStructuredBuffer<float> Out;
-
-// NOTE: _ZN4hlsl8RWBufferIfEixEj is the subscript operator for RWBuffer<float> and
-// _ZN4hlsl18RWStructuredBufferIfEixEj is the subscript operator for RWStructuredBuffer<float>
-
-// CHECK: define {{.*}} float @_Z3fooA2_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([2 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %Arr)
-// CHECK-NEXT: entry:
-float foo(RWBuffer<float> Arr[2][2]) {
-// CHECK-NEXT: %[[Arr_1_Ptr:.*]] = getelementptr inbounds [2 x [2 x %"class.hlsl::RWBuffer"]], ptr %Arr, i32 0, i32 1
-// CHECK-NEXT: %[[Arr_1_1_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %[[Arr_1_Ptr]], i32 0, i32 1
-// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Arr_1_1_Ptr]], i32 noundef 0)
-// CHECK-NEXT: %[[Value:.*]] = load float, ptr %[[BufPtr]], align 4
-// CHECK-NEXT: ret float %[[Value]]
- return Arr[1][1][0];
-}
-
-// CHECK: define internal void @_Z4mainv()
-// CHECK-NEXT: entry:
-[numthreads(4,1,1)]
-void main() {
-// CHECK-NEXT: %L = alloca [2 x [2 x %"class.hlsl::RWBuffer"]], align 4
-// CHECK-NEXT: %[[Tmp:.*]] = alloca [2 x [2 x %"class.hlsl::RWBuffer"]], align 4
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %L, ptr align 4 @_ZL1A, i32 4, i1 false)
-// CHECK-NEXT: %[[Ptr1:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %L, i32 1
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Ptr1]], ptr align 4 @_ZL1B, i32 4, i1 false)
-// CHECK-NEXT: %[[Ptr2:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %L, i32 1
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Ptr2]], ptr align 4 @_ZL1A, i32 4, i1 false)
-// CHECK-NEXT: %[[Ptr3:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %[[Ptr2]], i32 1
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Ptr3]], ptr align 4 @_ZL1B, i32 4, i1 false)
- RWBuffer<float> L[2][2] = { { A, B }, { A, B } };
-
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp]], ptr align 4 %L, i32 16, i1 false)
-// CHECK-NEXT: %[[ReturnedValue:.*]] = call {{.*}}float @_Z3fooA2_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([2 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %[[Tmp]])
-// CHECK-NEXT: %[[OutBufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl18RWStructuredBufferIfEixEj(ptr {{.*}} @_ZL3Out, i32 noundef 0)
-// CHECK-NEXT: store float %[[ReturnedValue]], ptr %[[OutBufPtr]], align 4
-// CHECK-NEXT: ret void
- Out[0] = foo(L);
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +// This test verifies handling of multi-dimensional local arrays of resources +// when used as a function argument and local variable. + +// CHECK: @_ZL1A = internal global %"class.hlsl::RWBuffer" poison, align 4 +// CHECK: @_ZL1B = internal global %"class.hlsl::RWBuffer" poison, align 4 + +RWBuffer<float> A : register(u10); +RWBuffer<float> B : register(u20); +RWStructuredBuffer<float> Out; + +// NOTE: _ZN4hlsl8RWBufferIfEixEj is the subscript operator for RWBuffer<float> and +// _ZN4hlsl18RWStructuredBufferIfEixEj is the subscript operator for RWStructuredBuffer<float> + +// CHECK: define {{.*}} float @_Z3fooA2_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([2 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %Arr) +// CHECK-NEXT: entry: +float foo(RWBuffer<float> Arr[2][2]) { +// CHECK-NEXT: %[[Arr_1_Ptr:.*]] = getelementptr inbounds [2 x [2 x %"class.hlsl::RWBuffer"]], ptr %Arr, i32 0, i32 1 +// CHECK-NEXT: %[[Arr_1_1_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %[[Arr_1_Ptr]], i32 0, i32 1 +// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Arr_1_1_Ptr]], i32 noundef 0) +// CHECK-NEXT: %[[Value:.*]] = load float, ptr %[[BufPtr]], align 4 +// CHECK-NEXT: ret float %[[Value]] + return Arr[1][1][0]; +} + +// CHECK: define internal void @_Z4mainv() +// CHECK-NEXT: entry: +[numthreads(4,1,1)] +void main() { +// CHECK: %L = alloca [2 x [2 x %"class.hlsl::RWBuffer"]], align 4 +// CHECK: %[[ref_tmp:.*]] = alloca %"class.hlsl::RWBuffer", align 4 +// CHECK: %[[ref_tmp1:.*]] = alloca %"class.hlsl::RWBuffer", align 4 +// CHECK: %[[ref_tmp2:.*]] = alloca %"class.hlsl::RWBuffer", align 4 +// CHECK: %[[ref_tmp3:.*]] = alloca %"class.hlsl::RWBuffer", align 4 +// CHECK: %[[ref_tmp4:.*]] = alloca %"class.hlsl::RWBuffer", align 4 +// CHECK: %[[ref_tmp5:.*]] = alloca %"class.hlsl::RWBuffer", align 4 +// CHECK: %[[ref_tmp6:.*]] = alloca %"class.hlsl::RWBuffer", align 4 +// CHECK: %[[ref_tmp7:.*]] = alloca %"class.hlsl::RWBuffer", align 4 +// CHECK: %[[agg_tmp:.*]] = alloca [2 x [2 x %"class.hlsl::RWBuffer"]], align 4 +// CHECK: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp]], ptr {{.*}} @_ZL1A) +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp1]], ptr {{.*}} %[[ref_tmp]]) +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp2]], ptr {{.*}} @_ZL1B) +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp3]], ptr {{.*}} %[[ref_tmp2]]) +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp4]], ptr {{.*}} @_ZL1A) +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp5]], ptr {{.*}} %[[ref_tmp4]]) +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp6]], ptr {{.*}} @_ZL1B) +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp7]], ptr {{.*}} %[[ref_tmp6]]) +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %L, ptr {{.*}} %[[ref_tmp1]]) +// CHECK-NEXT: %[[arrayinit_element:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %L, i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[arrayinit_element]], ptr {{.*}} %[[ref_tmp3]]) +// CHECK-NEXT: %[[arrayinit_element8:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %L, i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[arrayinit_element8]], ptr {{.*}} %[[ref_tmp5]]) +// CHECK-NEXT: %[[arrayinit_element9:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %[[arrayinit_element8]], i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[arrayinit_element9]], ptr {{.*}} %[[ref_tmp7]]) + RWBuffer<float> L[2][2] = { { A, B }, { A, B } }; + +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[agg_tmp]], ptr align 4 %L, i32 16, i1 false) +// CHECK-NEXT: %[[ReturnedValue:.*]] = call {{.*}}float @_Z3fooA2_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([2 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %[[agg_tmp]]) +// CHECK-NEXT: %[[OutBufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl18RWStructuredBufferIfEixEj(ptr {{.*}} @_ZL3Out, i32 noundef 0) +// CHECK-NEXT: store float %[[ReturnedValue]], ptr %[[OutBufPtr]], align 4 +// CHECK-NEXT: ret void + Out[0] = foo(L); +} diff --git a/clang/test/CodeGenHLSL/resources/res-array-local1.hlsl b/clang/test/CodeGenHLSL/resources/res-array-local1.hlsl index c0d508b1395c..9e31f4f150c5 100644 --- a/clang/test/CodeGenHLSL/resources/res-array-local1.hlsl +++ b/clang/test/CodeGenHLSL/resources/res-array-local1.hlsl @@ -1,64 +1,64 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
-
-// This test verifies local arrays of resources in HLSL.
-
-// CHECK: @_ZL1A = internal global %"class.hlsl::RWBuffer" poison, align 4
-// CHECK: @_ZL1B = internal global %"class.hlsl::RWBuffer" poison, align 4
-// CHECK: @_ZL1C = internal global %"class.hlsl::RWBuffer" poison, align 4
-
-RWBuffer<float> A : register(u1);
-RWBuffer<float> B : register(u2);
-RWBuffer<float> C : register(u3);
-RWStructuredBuffer<float> Out : register(u0);
-
-// CHECK: define internal void @_Z4mainv()
-// CHECK-NEXT: entry:
-[numthreads(4,1,1)]
-void main() {
-// CHECK-NEXT: %First = alloca [3 x %"class.hlsl::RWBuffer"], align 4
-// CHECK-NEXT: %Second = alloca [4 x %"class.hlsl::RWBuffer"], align 4
- RWBuffer<float> First[3] = { A, B, C };
- RWBuffer<float> Second[4];
-
-// Verify initialization of First array from an initialization list
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %First, ptr align 4 @_ZL1A, i32 4, i1 false)
-// CHECK-NEXT: %[[Ptr1:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %First, i32 1
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Ptr1]], ptr align 4 @_ZL1B, i32 4, i1 false)
-// CHECK-NEXT: %[[Ptr2:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %First, i32 2
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Ptr2]], ptr align 4 @_ZL1C, i32 4, i1 false)
-
-// Verify default initialization of Second array, which means there is a loop iterating
-// over the array elements and calling the default constructor for each
-// CHECK-NEXT: %[[ArrayBeginPtr:.*]] = getelementptr inbounds [4 x %"class.hlsl::RWBuffer"], ptr %Second, i32 0, i32 0
-// CHECK-NEXT: %[[ArrayEndPtr:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %[[ArrayBeginPtr]], i32 4
-// CHECK-NEXT: br label %[[ArrayInitLoop:.*]]
-// CHECK: [[ArrayInitLoop]]:
-// CHECK-NEXT: %[[ArrayCurPtr:.*]] = phi ptr [ %[[ArrayBeginPtr]], %entry ], [ %[[ArrayNextPtr:.*]], %[[ArrayInitLoop]] ]
-// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1Ev(ptr {{.*}} %[[ArrayCurPtr]])
-// CHECK-NEXT: %[[ArrayNextPtr]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %[[ArrayCurPtr]], i32 1
-// CHECK-NEXT: %[[ArrayInitDone:.*]] = icmp eq ptr %[[ArrayNextPtr]], %[[ArrayEndPtr]]
-// CHECK-NEXT: br i1 %[[ArrayInitDone]], label %[[AfterArrayInit:.*]], label %[[ArrayInitLoop]]
-// CHECK: [[AfterArrayInit]]:
-
-// Initialize First[2] with C
-// CHECK: %[[Ptr3:.*]] = getelementptr inbounds [4 x %"class.hlsl::RWBuffer"], ptr %Second, i32 0, i32 2
-// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Ptr3]], ptr align 4 @_ZL1C, i32 4, i1 false)
- Second[2] = C;
-
- // NOTE: _ZN4hlsl8RWBufferIfEixEj is the subscript operator for RWBuffer<float>
-
-// get First[1][0] value
-// CHECK: %[[First_1_Ptr:.*]] = getelementptr inbounds [3 x %"class.hlsl::RWBuffer"], ptr %First, i32 0, i32 1
-// CHECK: %[[BufPtr1:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[First_1_Ptr]], i32 noundef 0)
-// CHECK: %[[Value1:.*]] = load float, ptr %[[BufPtr1]], align 4
-
-// get Second[2][0] value
-// CHECK: %[[Second_2_Ptr:.*]] = getelementptr inbounds [4 x %"class.hlsl::RWBuffer"], ptr %Second, i32 0, i32 2
-// CHECK: %[[BufPtr2:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Second_2_Ptr]], i32 noundef 0)
-// CHECK: %[[Value2:.*]] = load float, ptr %[[BufPtr2]], align 4
-
-// add them
-// CHECK: %{{.*}} = fadd {{.*}} float %[[Value1]], %[[Value2]]
- Out[0] = First[1][0] + Second[2][0];
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +// This test verifies local arrays of resources in HLSL. + +// CHECK: @_ZL1A = internal global %"class.hlsl::RWBuffer" poison, align 4 +// CHECK: @_ZL1B = internal global %"class.hlsl::RWBuffer" poison, align 4 +// CHECK: @_ZL1C = internal global %"class.hlsl::RWBuffer" poison, align 4 + +RWBuffer<float> A : register(u1); +RWBuffer<float> B : register(u2); +RWBuffer<float> C : register(u3); +RWStructuredBuffer<float> Out : register(u0); + +// CHECK: define internal void @_Z4mainv() +// CHECK-NEXT: entry: +[numthreads(4,1,1)] +void main() { +// CHECK-NEXT: %First = alloca [3 x %"class.hlsl::RWBuffer"], align 4 +// CHECK-NEXT: %Second = alloca [4 x %"class.hlsl::RWBuffer"], align 4 + RWBuffer<float> First[3] = { A, B, C }; + RWBuffer<float> Second[4]; + +// Verify initialization of First array from an initialization list +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %First, ptr {{.*}} @_ZL1A) +// CHECK-NEXT: %[[Ptr1:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %First, i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[Ptr1]], ptr {{.*}} @_ZL1B) +// CHECK-NEXT: %[[Ptr2:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %First, i32 2 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[Ptr2]], ptr {{.*}} @_ZL1C) + +// Verify default initialization of Second array, which means there is a loop iterating +// over the array elements and calling the default constructor for each +// CHECK-NEXT: %[[ArrayBeginPtr:.*]] = getelementptr inbounds [4 x %"class.hlsl::RWBuffer"], ptr %Second, i32 0, i32 0 +// CHECK-NEXT: %[[ArrayEndPtr:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %[[ArrayBeginPtr]], i32 4 +// CHECK-NEXT: br label %[[ArrayInitLoop:.*]] +// CHECK: [[ArrayInitLoop]]: +// CHECK-NEXT: %[[ArrayCurPtr:.*]] = phi ptr [ %[[ArrayBeginPtr]], %entry ], [ %[[ArrayNextPtr:.*]], %[[ArrayInitLoop]] ] +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1Ev(ptr {{.*}} %[[ArrayCurPtr]]) +// CHECK-NEXT: %[[ArrayNextPtr]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %[[ArrayCurPtr]], i32 1 +// CHECK-NEXT: %[[ArrayInitDone:.*]] = icmp eq ptr %[[ArrayNextPtr]], %[[ArrayEndPtr]] +// CHECK-NEXT: br i1 %[[ArrayInitDone]], label %[[AfterArrayInit:.*]], label %[[ArrayInitLoop]] +// CHECK: [[AfterArrayInit]]: + +// Initialize First[2] with C +// CHECK: %[[Ptr3:.*]] = getelementptr inbounds [4 x %"class.hlsl::RWBuffer"], ptr %Second, i32 0, i32 2 +// CHECK: call {{.*}} @_ZN4hlsl8RWBufferIfEaSERKS1_(ptr {{.*}} %[[Ptr3]], ptr {{.*}} @_ZL1C) + Second[2] = C; + + // NOTE: _ZN4hlsl8RWBufferIfEixEj is the subscript operator for RWBuffer<float> + +// get First[1][0] value +// CHECK: %[[First_1_Ptr:.*]] = getelementptr inbounds [3 x %"class.hlsl::RWBuffer"], ptr %First, i32 0, i32 1 +// CHECK: %[[BufPtr1:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[First_1_Ptr]], i32 noundef 0) +// CHECK: %[[Value1:.*]] = load float, ptr %[[BufPtr1]], align 4 + +// get Second[2][0] value +// CHECK: %[[Second_2_Ptr:.*]] = getelementptr inbounds [4 x %"class.hlsl::RWBuffer"], ptr %Second, i32 0, i32 2 +// CHECK: %[[BufPtr2:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Second_2_Ptr]], i32 noundef 0) +// CHECK: %[[Value2:.*]] = load float, ptr %[[BufPtr2]], align 4 + +// add them +// CHECK: %{{.*}} = fadd {{.*}} float %[[Value1]], %[[Value2]] + Out[0] = First[1][0] + Second[2][0]; +} diff --git a/clang/test/CodeGenHLSL/resources/res-array-local2.hlsl b/clang/test/CodeGenHLSL/resources/res-array-local2.hlsl index 39f3aeb66ceb..4a02b9f8ced4 100644 --- a/clang/test/CodeGenHLSL/resources/res-array-local2.hlsl +++ b/clang/test/CodeGenHLSL/resources/res-array-local2.hlsl @@ -1,37 +1,37 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
-
-// This test verifies handling of local arrays of resources when used as a function argument.
-
-// CHECK: @_ZL1A = internal global [3 x %"class.hlsl::RWBuffer"] poison, align 4
-
-RWBuffer<float> A[3] : register(u0);
-RWStructuredBuffer<float> Out : register(u0);
-
-// NOTE: _ZN4hlsl8RWBufferIfEixEj is the subscript operator for RWBuffer<float> and
-// _ZN4hlsl18RWStructuredBufferIfEixEj is the subscript operator for RWStructuredBuffer<float>
-
-// CHECK: define {{.*}} float @_Z3fooA3_N4hlsl8RWBufferIfEE(ptr noundef byval([3 x %"class.hlsl::RWBuffer"]) align 4 %LocalA)
-// CHECK-NEXT: entry:
-float foo(RWBuffer<float> LocalA[3]) {
-// CHECK-NEXT: %[[LocalA_2_Ptr:.*]] = getelementptr inbounds [3 x %"class.hlsl::RWBuffer"], ptr %LocalA, i32 0, i32 2
-// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[LocalA_2_Ptr]], i32 noundef 0)
-// CHECK-NEXT: %[[Value:.*]] = load float, ptr %[[BufPtr]], align 4
-// CHECK-NEXT: ret float %[[Value]]
- return LocalA[2][0];
-}
-
-// CHECK: define internal void @_Z4mainv()
-// CHECK-NEXT: entry:
-[numthreads(4,1,1)]
-void main() {
-// Check that the `main` function calls `foo` with a local copy of the array
-// CHECK-NEXT: %[[Tmp:.*]] = alloca [3 x %"class.hlsl::RWBuffer"], align 4
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp]], ptr align 4 @_ZL1A, i32 12, i1 false)
-
-// CHECK-NEXT: %[[ReturnedValue:.*]] = call {{.*}} float @_Z3fooA3_N4hlsl8RWBufferIfEE(ptr noundef byval([3 x %"class.hlsl::RWBuffer"]) align 4 %[[Tmp]])
-// CHECK-NEXT: %[[OutBufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl18RWStructuredBufferIfEixEj(ptr {{.*}} @_ZL3Out, i32 noundef 0)
-// CHECK-NEXT: store float %[[ReturnedValue]], ptr %[[OutBufPtr]], align 4
-// CHECK-NEXT: ret void
- Out[0] = foo(A);
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +// This test verifies handling of local arrays of resources when used as a function argument. + +// CHECK: @_ZL1A = internal global [3 x %"class.hlsl::RWBuffer"] poison, align 4 + +RWBuffer<float> A[3] : register(u0); +RWStructuredBuffer<float> Out : register(u0); + +// NOTE: _ZN4hlsl8RWBufferIfEixEj is the subscript operator for RWBuffer<float> and +// _ZN4hlsl18RWStructuredBufferIfEixEj is the subscript operator for RWStructuredBuffer<float> + +// CHECK: define {{.*}} float @_Z3fooA3_N4hlsl8RWBufferIfEE(ptr noundef byval([3 x %"class.hlsl::RWBuffer"]) align 4 %LocalA) +// CHECK-NEXT: entry: +float foo(RWBuffer<float> LocalA[3]) { +// CHECK-NEXT: %[[LocalA_2_Ptr:.*]] = getelementptr inbounds [3 x %"class.hlsl::RWBuffer"], ptr %LocalA, i32 0, i32 2 +// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[LocalA_2_Ptr]], i32 noundef 0) +// CHECK-NEXT: %[[Value:.*]] = load float, ptr %[[BufPtr]], align 4 +// CHECK-NEXT: ret float %[[Value]] + return LocalA[2][0]; +} + +// CHECK: define internal void @_Z4mainv() +// CHECK-NEXT: entry: +[numthreads(4,1,1)] +void main() { +// Check that the `main` function calls `foo` with a local copy of the array +// CHECK-NEXT: %[[Tmp:.*]] = alloca [3 x %"class.hlsl::RWBuffer"], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp]], ptr align 4 @_ZL1A, i32 12, i1 false) + +// CHECK-NEXT: %[[ReturnedValue:.*]] = call {{.*}} float @_Z3fooA3_N4hlsl8RWBufferIfEE(ptr noundef byval([3 x %"class.hlsl::RWBuffer"]) align 4 %[[Tmp]]) +// CHECK-NEXT: %[[OutBufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl18RWStructuredBufferIfEixEj(ptr {{.*}} @_ZL3Out, i32 noundef 0) +// CHECK-NEXT: store float %[[ReturnedValue]], ptr %[[OutBufPtr]], align 4 +// CHECK-NEXT: ret void + Out[0] = foo(A); +} diff --git a/clang/test/CodeGenHLSL/resources/res-array-local3.hlsl b/clang/test/CodeGenHLSL/resources/res-array-local3.hlsl index e5bcdc651254..21ca3f4a98f9 100644 --- a/clang/test/CodeGenHLSL/resources/res-array-local3.hlsl +++ b/clang/test/CodeGenHLSL/resources/res-array-local3.hlsl @@ -1,62 +1,62 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
-// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
-
-// This test verifies handling of local arrays of resources when used
-// as a function argument that is modified inside the function.
-
-// CHECK: @_ZL1X = internal global %"class.hlsl::RWBuffer" poison, align 4
-// CHECK: @_ZL1Y = internal global %"class.hlsl::RWBuffer" poison, align 4
-
-RWBuffer<int> X : register(u0);
-RWBuffer<int> Y : register(u1);
-
-// CHECK: define {{.*}} @_Z6SomeFnA2_N4hlsl8RWBufferIiEEji(
-// CHECK-SAME: ptr noundef byval([2 x %"class.hlsl::RWBuffer"]) align 4 %B, i32 noundef %Idx, i32 noundef %Val0)
-// CHECK-NEXT: entry:
-// CHECK-NEXT: %[[Idx_addr:.*]] = alloca i32, align 4
-// CHECK-NEXT: %[[Val0_addr:.*]] = alloca i32, align 4
-// CHECK-NEXT: store i32 %Idx, ptr %[[Idx_addr]], align 4
-// CHECK-NEXT: store i32 %Val0, ptr %[[Val0_addr]], align 4
-void SomeFn(RWBuffer<int> B[2], uint Idx, int Val0) {
-
-// CHECK-NEXT: %[[B_0_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %B, i32 0, i32 0
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[B_0_Ptr]], ptr align 4 @_ZL1Y, i32 4, i1 false)
- B[0] = Y;
-
-// NOTE: _ZN4hlsl8RWBufferIiEixEj is the subscript operator for RWBuffer<int>
-
-// CHECK-NEXT: %[[Val0:.*]] = load i32, ptr %[[Val0_addr]], align 4
-// CHECK-NEXT: %[[B_0_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %B, i32 0, i32 0
-// CHECK-NEXT: %[[Idx:.*]] = load i32, ptr %[[Idx_addr]], align 4
-// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIiEixEj(ptr {{.*}} %[[B_0_Ptr]], i32 noundef %[[Idx]])
-// CHECK-NEXT: store i32 %[[Val0]], ptr %[[BufPtr]], align 4
- B[0][Idx] = Val0;
-}
-
-// CHECK: define {{.*}} void @_Z4mainj(i32 noundef %GI)
-// CHECK-NEXT: entry:
-// CHECK-NEXT: %[[GI_addr:.*]] = alloca i32, align 4
-[numthreads(4,1,1)]
-void main(uint GI : SV_GroupIndex) {
-// CHECK-NEXT: %A = alloca [2 x %"class.hlsl::RWBuffer"], align 4
-// CHECK-NEXT: %[[Tmp:.*]] = alloca [2 x %"class.hlsl::RWBuffer"], align 4
-// CHECK-NEXT: store i32 %GI, ptr %GI.addr, align 4
-
-// Initialization of array A with resources X and Y
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %A, ptr align 4 @_ZL1X, i32 4, i1 false)
-// CHECK-NEXT: %[[A_1_Ptr:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %A, i32 1
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[A_1_Ptr]], ptr align 4 @_ZL1Y, i32 4, i1 false)
- RWBuffer<int> A[2] = {X, Y};
-
-// Verify that SomeFn is called with a local copy of the array A
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp]], ptr align 4 %A, i32 8, i1 false)
-// CHECK-NEXT: %[[GI:.*]] = load i32, ptr %[[GI_addr]], align 4
-// CHECK-NEXT: call void @_Z6SomeFnA2_N4hlsl8RWBufferIiEEji(ptr noundef byval([2 x %"class.hlsl::RWBuffer"]) align 4 %[[Tmp]], i32 noundef %[[GI]], i32 noundef 1)
- SomeFn(A, GI, 1);
-
-// CHECK-NEXT: %[[A_0_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %A, i32 0, i32 0
-// CHECK-NEXT: %[[GI:.*]] = load i32, ptr %[[GI_addr]], align 4
-// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIiEixEj(ptr {{.*}} %[[A_0_Ptr]], i32 noundef %[[GI]])
-// CHECK-NEXT: store i32 2, ptr %[[BufPtr]], align 4
- A[0][GI] = 2;
-}
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +// This test verifies handling of local arrays of resources when used +// as a function argument that is modified inside the function. + +// CHECK: @_ZL1X = internal global %"class.hlsl::RWBuffer" poison, align 4 +// CHECK: @_ZL1Y = internal global %"class.hlsl::RWBuffer" poison, align 4 + +RWBuffer<int> X : register(u0); +RWBuffer<int> Y : register(u1); + +// CHECK: define {{.*}} @_Z6SomeFnA2_N4hlsl8RWBufferIiEEji( +// CHECK-SAME: ptr noundef byval([2 x %"class.hlsl::RWBuffer"]) align 4 %B, i32 noundef %Idx, i32 noundef %Val0) +// CHECK-NEXT: entry: +// CHECK-NEXT: %[[Idx_addr:.*]] = alloca i32, align 4 +// CHECK-NEXT: %[[Val0_addr:.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 %Idx, ptr %[[Idx_addr]], align 4 +// CHECK-NEXT: store i32 %Val0, ptr %[[Val0_addr]], align 4 +void SomeFn(RWBuffer<int> B[2], uint Idx, int Val0) { + +// CHECK-NEXT: %[[B_0_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %B, i32 0, i32 0 +// CHECK-NEXT: call {{.*}} @_ZN4hlsl8RWBufferIiEaSERKS1_(ptr {{.*}} %[[B_0_Ptr]], ptr {{.*}} @_ZL1Y) + B[0] = Y; + +// NOTE: _ZN4hlsl8RWBufferIiEixEj is the subscript operator for RWBuffer<int> + +// CHECK-NEXT: %[[Val0:.*]] = load i32, ptr %[[Val0_addr]], align 4 +// CHECK-NEXT: %[[B_0_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %B, i32 0, i32 0 +// CHECK-NEXT: %[[Idx:.*]] = load i32, ptr %[[Idx_addr]], align 4 +// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIiEixEj(ptr {{.*}} %[[B_0_Ptr]], i32 noundef %[[Idx]]) +// CHECK-NEXT: store i32 %[[Val0]], ptr %[[BufPtr]], align 4 + B[0][Idx] = Val0; +} + +// CHECK: define {{.*}} void @_Z4mainj(i32 noundef %GI) +// CHECK-NEXT: entry: +// CHECK-NEXT: %[[GI_addr:.*]] = alloca i32, align 4 +[numthreads(4,1,1)] +void main(uint GI : SV_GroupIndex) { +// CHECK-NEXT: %A = alloca [2 x %"class.hlsl::RWBuffer"], align 4 +// CHECK-NEXT: %[[Tmp:.*]] = alloca [2 x %"class.hlsl::RWBuffer"], align 4 +// CHECK-NEXT: store i32 %GI, ptr %GI.addr, align 4 + +// Initialization of array A with resources X and Y +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1ERKS1_(ptr {{.*}} %A, ptr {{.*}} @_ZL1X) +// CHECK-NEXT: %[[A_1_Ptr:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %A, i32 1 +// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1ERKS1_(ptr {{.*}} %[[A_1_Ptr]], ptr {{.*}} @_ZL1Y) + RWBuffer<int> A[2] = {X, Y}; + +// Verify that SomeFn is called with a local copy of the array A +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp]], ptr align 4 %A, i32 8, i1 false) +// CHECK-NEXT: %[[GI:.*]] = load i32, ptr %[[GI_addr]], align 4 +// CHECK-NEXT: call void @_Z6SomeFnA2_N4hlsl8RWBufferIiEEji(ptr noundef byval([2 x %"class.hlsl::RWBuffer"]) align 4 %[[Tmp]], i32 noundef %[[GI]], i32 noundef 1) + SomeFn(A, GI, 1); + +// CHECK-NEXT: %[[A_0_Ptr:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %A, i32 0, i32 0 +// CHECK-NEXT: %[[GI:.*]] = load i32, ptr %[[GI_addr]], align 4 +// CHECK-NEXT: %[[BufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIiEixEj(ptr {{.*}} %[[A_0_Ptr]], i32 noundef %[[GI]]) +// CHECK-NEXT: store i32 2, ptr %[[BufPtr]], align 4 + A[0][GI] = 2; +} diff --git a/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl b/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl index 2a6e51d765bd..27af47e9587c 100644 --- a/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl +++ b/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl @@ -14,28 +14,28 @@ // CHECK: %[[HANDLE:.*]] = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) // CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_1_0_0t( -// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i1 false, ptr %{{.*}}) +// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, ptr %{{.*}}) // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %this{{[0-9]*}}, i32 0, i32 0 // CHECK: store target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %[[HANDLE]], ptr %[[HANDLE_PTR]], align 4 RWBuffer<float4> U0S0 : register(u0); // CHECK: %[[HANDLE:.*]] = call target("dx.TypedBuffer", float, 1, 0, 0) // CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t( -// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i1 false, ptr %{{.*}}) +// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, ptr %{{.*}}) // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %this{{[0-9]*}}, i32 0, i32 0 // CHECK: store target("dx.TypedBuffer", float, 1, 0, 0) %[[HANDLE]], ptr %[[HANDLE_PTR]], align 4 RWBuffer<float> U5S3 : register(u5, space3); // CHECK: %[[HANDLE:.*]] = call target("dx.RawBuffer", i32, 0, 0) // CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t( -// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i1 false, ptr %{{.*}}) +// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, ptr %{{.*}}) // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %this{{[0-9]*}}, i32 0, i32 0 // CHECK: store target("dx.RawBuffer", i32, 0, 0) %[[HANDLE]], ptr %[[HANDLE_PTR]], align 4 StructuredBuffer<int> T2S2 : register(t2, space2); // CHECK: %[[HANDLE:.*]] = call target("dx.RawBuffer", %struct.S, 1, 0) // CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_s_struct.Ss_1_0t( -// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i1 false, ptr %{{.*}}) +// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, ptr %{{.*}}) // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %this{{[0-9]*}}, i32 0, i32 0 // CHECK: store target("dx.RawBuffer", %struct.S, 1, 0) %[[HANDLE]], ptr %[[HANDLE_PTR]], align 4 struct S { |
