Author: Helena Kotas Date: 2026-06-18T22:52:28-07:00 New Revision: ed287c064db043a94b5470ebf36524153aeaf33f
URL: https://github.com/llvm/llvm-project/commit/ed287c064db043a94b5470ebf36524153aeaf33f DIFF: https://github.com/llvm/llvm-project/commit/ed287c064db043a94b5470ebf36524153aeaf33f.diff LOG: [HLSL][NFC] Add codegen test for ConstantBuffer<T> element access and initialization (#204507) Adding tests coverage for `ConstantBuffer<T>` element access and initialization. Related to llvm/wg-hlsl#302 and llvm/llvm-project#195153 Added: clang/test/CodeGenHLSL/resources/ConstantBufferT.hlsl Modified: Removed: ################################################################################ diff --git a/clang/test/CodeGenHLSL/resources/ConstantBufferT.hlsl b/clang/test/CodeGenHLSL/resources/ConstantBufferT.hlsl new file mode 100644 index 0000000000000..30c2c9bb5c2f6 --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/ConstantBufferT.hlsl @@ -0,0 +1,142 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | \ +// RUN: llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DCONST_ADDR_SPACE=2 -DPADDING_TYPE="dx.Padding" +// RUN: %clang_cc1 -triple spirv-vulkan-library -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | \ +// RUN: llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-SPV -DCONST_ADDR_SPACE=12 -DPADDING_TYPE="spirv.Padding" + +struct S { + float3 f3; + int a; +}; + +struct MyConstants { + float f; + int2 i2; + half3 h3; + double d; + int array[2]; + float2x2 m; + S s; +}; + +ConstantBuffer<MyConstants> CB; +ConstantBuffer<S> CBArray[2]; + +// CHECK-DXIL: %"class.hlsl::ConstantBuffer" = type { target("dx.CBuffer", %MyConstants) } +// CHECK-SPV: %"class.hlsl::ConstantBuffer" = type { target("spirv.VulkanBuffer", %MyConstants, 2, 0) } + +// CHECK: %MyConstants = type <{ float, <2 x i32>, target("[[PADDING_TYPE]]", 4), <3 x float>, +// CHECK-SAME: target("[[PADDING_TYPE]]", 4), double, target("[[PADDING_TYPE]]", 8), +// CHECK-SAME: <{ [1 x <{ i32, target("[[PADDING_TYPE]]", 12) }>], i32 }>, +// CHECK-SAME: target("[[PADDING_TYPE]]", 12), <{ [1 x <{ <2 x float>, target("[[PADDING_TYPE]]", 8) }>], +// CHECK-SAME: <2 x float> }>, target("[[PADDING_TYPE]]", 8), %S }> + +// CHECK: %S = type <{ <3 x float>, i32 }> +// CHECK: %struct.S = type { <3 x float>, i32 } + +// CHECK: @CB = internal global %"class.hlsl::ConstantBuffer" poison, align {{(4|8)}} +// CHECK: [[CBStr:.*]] = private unnamed_addr constant [3 x i8] c"CB\00", align 1 +// CHECK: [[CBArrayStr:.*]] = private unnamed_addr constant [8 x i8] c"CBArray\00", align 1 + +// CB initialization +// +// CHECK-LABEL: __cxx_global_var_init +// CHECK: call void @hlsl::ConstantBuffer<MyConstants>::__createFromImplicitBinding({{[^)]+}}) +// CHECK-SAME: (ptr dead_on_unwind writable sret(%"class.hlsl::ConstantBuffer") align {{(4|8)}} @CB, +// CHECK-SAME: i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef [[CBStr]]) + +// CHECK: define linkonce_odr hidden void @hlsl::ConstantBuffer<MyConstants>::__createFromImplicitBinding( +// CHECK-DXIL: call target("dx.CBuffer", %MyConstants) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s_MyConstantsst +// CHECK-SPV: call target("spirv.VulkanBuffer", %MyConstants, 2, 0) @llvm.spv.resource.handlefromimplicitbinding.tspirv.VulkanBuffer_s_MyConstantss_2_0t( + +// CHECK-LABEL: TestElementAccess +void TestElementAccess() { +// CHECK: [[CB_PTR:%.*]] = call {{.*}} ptr addrspace([[CONST_ADDR_SPACE]]) @hlsl::ConstantBuffer<MyConstants>::operator MyConstants const AS[[CONST_ADDR_SPACE]]&() const(ptr {{.*}} @CB) +// CHECK-NEXT: [[CB_F_PTR:%.*]] = getelementptr inbounds nuw %MyConstants, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_PTR]], i32 0, i32 0 +// CHECK-NEXT: [[CB_F:%.*]] = load float, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_F_PTR]], align 4 +// CHECK-NEXT: store float [[CB_F]], ptr %f, align 4 + float f = CB.f; + +// CHECK-NEXT: [[CB_PTR:%.*]] = call {{.*}} ptr addrspace([[CONST_ADDR_SPACE]]) @hlsl::ConstantBuffer<MyConstants>::operator MyConstants const AS[[CONST_ADDR_SPACE]]&() const(ptr {{.*}} @CB) +// CHECK-NEXT: [[CB_I2_PTR:%.*]] = getelementptr inbounds nuw %MyConstants, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_PTR]], i32 0, i32 1 +// CHECK-NEXT: [[CB_I2:%.*]] = load <2 x i32>, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_I2_PTR]], align 4 +// CHECK-NEXT: store <2 x i32> [[CB_I2]], ptr %i2, align 4 + int2 i2 = CB.i2; + +// CHECK-NEXT: [[CB_PTR:%.*]] = call {{.*}} ptr addrspace([[CONST_ADDR_SPACE]]) @hlsl::ConstantBuffer<MyConstants>::operator MyConstants const AS[[CONST_ADDR_SPACE]]&() const(ptr {{.*}} @CB) +// CHECK-NEXT: [[CB_H3_PTR:%.*]] = getelementptr inbounds nuw %MyConstants, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_PTR]], i32 0, i32 3 +// CHECK-NEXT: [[CB_H3:%.*]] = load <3 x float>, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_H3_PTR]], align 4 +// CHECK-NEXT: store <3 x float> [[CB_H3]], ptr %h3, align 4 + half3 h3 = CB.h3; + +// CHECK-NEXT: [[CB_PTR:%.*]] = call {{.*}} ptr addrspace([[CONST_ADDR_SPACE]]) @hlsl::ConstantBuffer<MyConstants>::operator MyConstants const AS[[CONST_ADDR_SPACE]]&() const(ptr {{.*}} @CB) +// CHECK-NEXT: [[CB_D_PTR:%.*]] = getelementptr inbounds nuw %MyConstants, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_PTR]], i32 0, i32 5 +// CHECK-NEXT: [[CB_D:%.*]] = load double, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_D_PTR]], align 8 +// CHECK-NEXT: store double [[CB_D]], ptr %d, align 8 + double d = CB.d; + +// CHECK-NEXT: [[CB_PTR:%.*]] = call {{.*}} ptr addrspace([[CONST_ADDR_SPACE]]) @hlsl::ConstantBuffer<MyConstants>::operator MyConstants const AS[[CONST_ADDR_SPACE]]&() const(ptr {{.*}} @CB) +// CHECK-NEXT: [[CB_ARRAY_PTR:%.*]] = getelementptr inbounds nuw %MyConstants, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_PTR]], i32 0, i32 7 +// CHECK-NEXT: [[CB_ARRAY_DECAY_PTR:%.*]] = getelementptr inbounds [2 x i32], ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_ARRAY_PTR]], {{(i32|i64)}} 0, {{(i32|i64)}} 0 +// CHECK-NEXT: [[CB_ARRAY_1_PTR:%.*]] = getelementptr <{ i32, target("[[PADDING_TYPE]]", 12) }>, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_ARRAY_DECAY_PTR]], {{(i32|i64)}} 1, {{(i32|i64)}} 0 +// CHECK-NEXT: [[CB_ARRAY_1:%.*]] = load i32, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_ARRAY_1_PTR]], align 16 +// CHECK-NEXT: store i32 [[CB_ARRAY_1]], ptr %arrayEl, align 4 + int arrayEl = CB.array[1]; + +// CHECK-NEXT: [[CB_PTR:%.*]] = call {{.*}} ptr addrspace([[CONST_ADDR_SPACE]]) @hlsl::ConstantBuffer<MyConstants>::operator MyConstants const AS[[CONST_ADDR_SPACE]]&() const(ptr {{.*}} @CB) +// CHECK-NEXT: [[CB_M_PTR:%.*]] = getelementptr inbounds nuw %MyConstants, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_PTR]], i32 0, i32 9 +// CHECK-NEXT: [[CB_M:%.*]] = load <4 x float>, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_M_PTR]], align 4 +// CHECK-NEXT: store <4 x float> [[CB_M]], ptr %m, align 4 + float2x2 m = CB.m; + +// CHECK-NEXT: [[CB_PTR:%.*]] = call {{.*}} ptr addrspace([[CONST_ADDR_SPACE]]) @hlsl::ConstantBuffer<MyConstants>::operator MyConstants const AS[[CONST_ADDR_SPACE]]&() const(ptr {{.*}} @CB) +// CHECK-NEXT: [[CB_S_PTR:%.*]] = getelementptr inbounds nuw %MyConstants, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_PTR]], i32 0, i32 11 +// CHECK-NEXT: [[CB_S_F3_PTR:%.*]] = getelementptr inbounds %S, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_S_PTR]], i32 0, i32 0 +// CHECK-NEXT: [[S_F3_PTR:%.*]] = getelementptr inbounds %struct.S, ptr %s, i32 0, i32 0 +// CHECK-NEXT: [[CB_S_F3:%.*]] = load <3 x float>, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_S_F3_PTR]], align 4 +// CHECK-NEXT: store <3 x float> [[CB_S_F3]], ptr [[S_F3_PTR]], align 4 +// CHECK-NEXT: [[CB_S_A_PTR:%.*]] = getelementptr inbounds %S, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_S_PTR]], i32 0, i32 1 +// CHECK-NEXT: [[S_A_PTR:%.*]] = getelementptr inbounds %struct.S, ptr %s, i32 0, i32 1 +// CHECK-NEXT: [[CB_S_A:%.*]] = load i32, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_S_A_PTR]], align 4 +// CHECK-NEXT: store i32 [[CB_S_A]], ptr [[S_A_PTR]], align 4 + S s = CB.s; + +// CHECK-NEXT: [[CB_PTR:%.*]] = call {{.*}} ptr addrspace([[CONST_ADDR_SPACE]]) @hlsl::ConstantBuffer<MyConstants>::operator MyConstants const AS[[CONST_ADDR_SPACE]]&() const(ptr {{.*}} @CB) +// CHECK-NEXT: [[CB_S_PTR:%.*]] = getelementptr inbounds nuw %MyConstants, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_PTR]], i32 0, i32 11 +// CHECK-NEXT: [[CB_S_F3_PTR:%.*]] = getelementptr inbounds nuw %S, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_S_PTR]], i32 0, i32 0 +// CHECK-NEXT: [[CB_S_F:%.*]] = load <3 x float>, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_S_F3_PTR]], align 4 +// CHECK-NEXT: store <3 x float> [[CB_S_F]], ptr %f3, align 4 + float3 f3 = CB.s.f3; +} + +// CHECK: define {{.*}} ptr addrspace([[CONST_ADDR_SPACE]]) @hlsl::ConstantBuffer<MyConstants>::operator MyConstants const AS[[CONST_ADDR_SPACE]]&() const(ptr {{.*}}) +// CHECK: [[HANDLE_PTR:%.*]] = getelementptr inbounds nuw %"class.hlsl::ConstantBuffer", ptr %{{.*}}, i32 0, i32 0 +// CHECK-DXIL: [[HANDLE:%.*]] = load target("dx.CBuffer", %MyConstants), ptr [[HANDLE_PTR]], align 4 +// CHECK-DXIL: [[BASE_PTR:%.*]] = call ptr addrspace([[CONST_ADDR_SPACE]]) @llvm.dx.resource.getbasepointer.p2.tdx.CBuffer_s_MyConstantsst(target("dx.CBuffer", %MyConstants) [[HANDLE]]) +// CHECK-SPV: [[HANDLE:%.*]] = load target("spirv.VulkanBuffer", %MyConstants, 2, 0), ptr [[HANDLE_PTR]], align 8 +// CHECK-SPV: [[BASE_PTR:%.*]] = call ptr addrspace([[CONST_ADDR_SPACE]]) @llvm.spv.resource.getbasepointer.p12.tspirv.VulkanBuffer_s_MyConstantss_2_0t(target("spirv.VulkanBuffer", %MyConstants, 2, 0) [[HANDLE]]) +// CHECK: ret ptr addrspace([[CONST_ADDR_SPACE]]) [[BASE_PTR]] + +// CHECK-LABEL: TestArrayAccess +void TestArrayAccess() { +// CHECK: [[TMP0:%.*]] = alloca %"class.hlsl::ConstantBuffer.0", align {{(4|8)}} +// CHECK: [[TMP1:%.*]] = alloca %"class.hlsl::ConstantBuffer.0", align {{(4|8)}} + +// CHECK: call void @hlsl::ConstantBuffer<S>::__createFromImplicitBinding({{.*}})(ptr {{.*}} sret(%"class.hlsl::ConstantBuffer.0") align {{(4|8)}} [[TMP0]], +// CHECK-SAME: i32 noundef 1, i32 noundef 0, i32 noundef 2, i32 noundef 1, ptr noundef [[CBArrayStr]]) +// CHECK-NEXT: [[CB_1_PTR:%.*]] = call {{.*}} ptr addrspace([[CONST_ADDR_SPACE]]) @hlsl::ConstantBuffer<S>::operator S const AS[[CONST_ADDR_SPACE]]&() const(ptr{{.*}} [[TMP0]]) +// CHECK-NEXT: [[CB_1_F3_PTR:%.*]] = getelementptr inbounds nuw %S, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_1_PTR]], i32 0, i32 0 +// CHECK-NEXT: [[CB_1_F3:%.*]] = load <3 x float>, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_1_F3_PTR]], align 4 +// CHECK-NEXT: store <3 x float> [[CB_1_F3]], ptr %f3, align 4 + float3 f3 = CBArray[1].f3; + +// CHECK: call void @hlsl::ConstantBuffer<S>::__createFromImplicitBinding({{.*}})(ptr {{.*}} sret(%"class.hlsl::ConstantBuffer.0") align {{(4|8)}} [[TMP1]], +// CHECK-SAME: i32 noundef 1, i32 noundef 0, i32 noundef 2, i32 noundef 0, ptr noundef [[CBArrayStr]]) +// CHECK-NEXT: [[CB_0_PTR:%.*]] = call {{.*}} ptr addrspace([[CONST_ADDR_SPACE]]) @hlsl::ConstantBuffer<S>::operator S const AS[[CONST_ADDR_SPACE]]&() const(ptr{{.*}} [[TMP1]]) +// CHECK-NEXT: [[CB_0_A_PTR:%.*]] = getelementptr inbounds nuw %S, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_0_PTR]], i32 0, i32 1 +// CHECK-NEXT: [[CB_0_A:%.*]] = load i32, ptr addrspace([[CONST_ADDR_SPACE]]) [[CB_0_A_PTR]], align 4 +// CHECK-NEXT: store i32 [[CB_0_A]], ptr %a, align 4 + int a = CBArray[0].a; +} + +// CHECK-DXIL: declare ptr addrspace([[CONST_ADDR_SPACE]]) @llvm.dx.resource.getbasepointer.p2.tdx.CBuffer_s_MyConstantsst(target("dx.CBuffer", %MyConstants)) +// CHECK-SPV: declare ptr addrspace([[CONST_ADDR_SPACE]]) @llvm.spv.resource.getbasepointer.p12.tspirv.VulkanBuffer_s_MyConstantss_2_0t(target("spirv.VulkanBuffer", %MyConstants, 2, 0)) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
