| ; RUN: opt -S -dxil-resource-access %s | FileCheck %s | |
| target triple = "dxil-pc-shadermodel6.6-library" | |
| ; 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; | |
| %MyConstants = type <{ float, <2 x i32>, target("dx.Padding", 4), <3 x half>, | |
| target("dx.Padding", 2), double, <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }>, | |
| target("dx.Padding", 12), <{ [1 x <{ <2 x float>, target("dx.Padding", 8) }>], <2 x float> }>, | |
| target("dx.Padding", 8), %S }> | |
| %S = type <{ <3 x float>, i32 }> | |
| ; CHECK: define void @f | |
| define void @f(ptr %dst) { | |
| entry: | |
| %CB_handle = call target("dx.CBuffer", %MyConstants) | |
| @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s_MyConstantsst(i32 0, i32 5, i32 1, i32 0, ptr null) | |
| ; CB.f | |
| ; | |
| ; CHECK: [[CBLOAD0:%.*]] = call { float, float, float, float } | |
| ; CHECK-SAME: @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_s_MyConstantsst( | |
| ; CHECK-SAME: target("dx.CBuffer", %MyConstants) %CB_handle, i32 0) | |
| ; CHECK-NEXT: [[CB_F:%.*]] = extractvalue { float, float, float, float } [[CBLOAD0]], 0 | |
| ; CHECK-NEXT: store float [[CB_F]], ptr %dst, align 4 | |
| %CB_ptr0 = call noundef align 1 dereferenceable(72) ptr addrspace(2) | |
| @llvm.dx.resource.getbasepointer.p2.tdx.CBuffer_s_MyConstantsst(target("dx.CBuffer", %MyConstants) %CB_handle) | |
| %f_ptr = getelementptr inbounds nuw %MyConstants, ptr addrspace(2) %CB_ptr0, i32 0, i32 0 | |
| %f = load float, ptr addrspace(2) %f_ptr, align 4 | |
| store float %f, ptr %dst, align 4 | |
| ; CB.i2 | |
| ; | |
| ; CHECK: [[CBLOAD1:%.*]] = call { i32, i32, i32, i32 } | |
| ; CHECK-SAME: @llvm.dx.resource.load.cbufferrow.4.i32.i32.i32.i32.tdx.CBuffer_s_MyConstantsst( | |
| ; CHECK-SAME: target("dx.CBuffer", %MyConstants) %CB_handle, i32 0) | |
| ; CHECK-NEXT: [[CB_I2_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[CBLOAD1]], 1 | |
| ; CHECK-NEXT: [[CB_I2_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[CBLOAD1]], 2 | |
| ; CHECK-NEXT: [[VEC0:%.*]] = insertelement <2 x i32> poison, i32 [[CB_I2_0]], i32 0 | |
| ; CHECK-NEXT: [[VEC1:%.*]] = insertelement <2 x i32> [[VEC0]], i32 [[CB_I2_1]], i32 1 | |
| ; CHECK-NEXT: [[DST_PTR:%.*]] = getelementptr inbounds nuw i8, ptr %dst, i32 8 | |
| ; CHECK-NEXT: store <2 x i32> [[VEC1]], ptr [[DST_PTR]], align 4 | |
| %CB_ptr1 = call noundef align 1 dereferenceable(72) ptr addrspace(2) | |
| @llvm.dx.resource.getbasepointer.p2.tdx.CBuffer_s_MyConstantsst(target("dx.CBuffer", %MyConstants) %CB_handle) | |
| %i2_ptr = getelementptr inbounds nuw %MyConstants, ptr addrspace(2) %CB_ptr1, i32 0, i32 1 | |
| %i2 = load <2 x i32>, ptr addrspace(2) %i2_ptr, align 4 | |
| %dst1 = getelementptr inbounds nuw i8, ptr %dst, i32 8 | |
| store <2 x i32> %i2, ptr %dst1, align 4 | |
| ; CB.h3 | |
| ; | |
| ; CHECK: [[CBLOAD2:%.*]] = call { half, half, half, half, half, half, half, half } | |
| ; CHECK-SAME: @llvm.dx.resource.load.cbufferrow.8.f16.f16.f16.f16.f16.f16.f16.f16.tdx.CBuffer_s_MyConstantsst( | |
| ; CHECK-SAME: target("dx.CBuffer", %MyConstants) %CB_handle, i32 1) | |
| ; CHECK-NEXT: [[CB_H3_0:%.*]] = extractvalue { half, half, half, half, half, half, half, half } [[CBLOAD2]], 0 | |
| ; CHECK-NEXT: [[CB_H3_1:%.*]] = extractvalue { half, half, half, half, half, half, half, half } [[CBLOAD2]], 1 | |
| ; CHECK-NEXT: [[CB_H3_2:%.*]] = extractvalue { half, half, half, half, half, half, half, half } [[CBLOAD2]], 2 | |
| ; CHECK-NEXT: [[VEC0:%.*]] = insertelement <3 x half> poison, half [[CB_H3_0]], i32 0 | |
| ; CHECK-NEXT: [[VEC1:%.*]] = insertelement <3 x half> [[VEC0]], half [[CB_H3_1]], i32 1 | |
| ; CHECK-NEXT: [[VEC2:%.*]] = insertelement <3 x half> [[VEC1]], half [[CB_H3_2]], i32 2 | |
| ; CHECK-NEXT: [[DST_PTR:%.*]] = getelementptr inbounds nuw i8, ptr %dst, i32 16 | |
| ; CHECK-NEXT: store <3 x half> [[VEC2]], ptr [[DST_PTR]], align 2 | |
| %CB_ptr2 = call noundef align 1 dereferenceable(72) ptr addrspace(2) | |
| @llvm.dx.resource.getbasepointer.p2.tdx.CBuffer_s_MyConstantsst(target("dx.CBuffer", %MyConstants) %CB_handle) | |
| %h3_ptr = getelementptr inbounds nuw %MyConstants, ptr addrspace(2) %CB_ptr2, i32 0, i32 3 | |
| %h3 = load <3 x half>, ptr addrspace(2) %h3_ptr, align 2 | |
| %dst2 = getelementptr inbounds nuw i8, ptr %dst, i32 16 | |
| store <3 x half> %h3, ptr %dst2, align 2 | |
| ; CB.d | |
| ; | |
| ; CHECK: [[CBLOAD3:%.*]] = call { double, double } | |
| ; CHECK-SAME: @llvm.dx.resource.load.cbufferrow.2.f64.f64.tdx.CBuffer_s_MyConstantsst( | |
| ; CHECK-SAME: target("dx.CBuffer", %MyConstants) %CB_handle, i32 1) | |
| ; CHECK-NEXT: [[CB_D3:%.*]] = extractvalue { double, double } [[CBLOAD3]], 1 | |
| ; CHECK-NEXT: [[DST_PTR:%.*]] = getelementptr inbounds nuw i8, ptr %dst, i32 32 | |
| ; CHECK-NEXT: store double [[CB_D3]], ptr [[DST_PTR]], align 8 | |
| %CB_ptr3 = call noundef align 1 dereferenceable(72) ptr addrspace(2) | |
| @llvm.dx.resource.getbasepointer.p2.tdx.CBuffer_s_MyConstantsst(target("dx.CBuffer", %MyConstants) %CB_handle) | |
| %d_ptr = getelementptr inbounds nuw %MyConstants, ptr addrspace(2) %CB_ptr3, i32 0, i32 5 | |
| %d = load double, ptr addrspace(2) %d_ptr, align 8 | |
| %dst3 = getelementptr inbounds nuw i8, ptr %dst, i32 32 | |
| store double %d, ptr %dst3, align 8 | |
| ; CB.array[1] | |
| ; - reusing %CB_ptr3 from previous case | |
| ; | |
| ; CHECK: [[CBLOAD4:%.*]] = call { i32, i32, i32, i32 } | |
| ; CHECK-SAME: @llvm.dx.resource.load.cbufferrow.4.i32.i32.i32.i32.tdx.CBuffer_s_MyConstantsst( | |
| ; CHECK-SAME: target("dx.CBuffer", %MyConstants) %CB_handle, i32 3) | |
| ; CHECK-NEXT: [[ARRAY_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[CBLOAD4]], 0 | |
| ; CHECK-NEXT: [[DST_PTR:%.*]] = getelementptr inbounds nuw i8, ptr %dst, i32 40 | |
| ; CHECK-NEXT: store i32 [[ARRAY_1]], ptr [[DST_PTR]], align 4 | |
| %array = getelementptr inbounds nuw %MyConstants, ptr addrspace(2) %CB_ptr3, i32 0, i32 6 | |
| %arraydecay = getelementptr inbounds [2 x i32], ptr addrspace(2) %array, i32 0, i32 0 | |
| %array_1_ptr = getelementptr <{ i32, target("dx.Padding", 12) }>, ptr addrspace(2) %arraydecay, i32 1, i32 0 | |
| %array_1 = load i32, ptr addrspace(2) %array_1_ptr, align 16 | |
| %dst4 = getelementptr inbounds nuw i8, ptr %dst, i32 40 | |
| store i32 %array_1, ptr %dst4, align 4 | |
| ; CB.m | |
| ; - reusing %CB_ptr3 from previous case | |
| ; | |
| ; CHECK: [[CBLOAD5:%.*]] = call { float, float, float, float } | |
| ; CHECK-SAME: @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_s_MyConstantsst( | |
| ; CHECK-SAME: target("dx.CBuffer", %MyConstants) %CB_handle, i32 4) | |
| ; CHECK-NEXT: [[M00:%.*]] = extractvalue { float, float, float, float } %m.load, 0 | |
| ; CHECK-NEXT: [[M10:%.*]] = extractvalue { float, float, float, float } %m.load, 1 | |
| ; CHECK-NEXT: [[M01:%.*]] = extractvalue { float, float, float, float } %m.load, 2 | |
| ; CHECK-NEXT: [[M11:%.*]] = extractvalue { float, float, float, float } %m.load, 3 | |
| ; CHECK-NEXT: [[MAT0:%.*]] = insertelement <4 x float> poison, float [[M00]], i32 0 | |
| ; CHECK-NEXT: [[MAT1:%.*]] = insertelement <4 x float> [[MAT0]], float [[M10]], i32 1 | |
| ; CHECK-NEXT: [[MAT2:%.*]] = insertelement <4 x float> [[MAT1]], float [[M01]], i32 2 | |
| ; CHECK-NEXT: [[MAT3:%.*]] = insertelement <4 x float> [[MAT2]], float [[M11]], i32 3 | |
| ; CHECK-NEXT: [[DST_PTR:%.*]] = getelementptr inbounds nuw i8, ptr %dst, i32 56 | |
| ; CHECK-NEXT: store <4 x float> [[MAT3]], ptr [[DST_PTR]], align 4 | |
| %m_ptr = getelementptr inbounds nuw %MyConstants, ptr addrspace(2) %CB_ptr3, i32 0, i32 8 | |
| %m = load <4 x float>, ptr addrspace(2) %m_ptr, align 4 | |
| %dst5 = getelementptr inbounds nuw i8, ptr %dst, i32 56 | |
| store <4 x float> %m, ptr %dst5, align 4 | |
| ; CB.s | |
| ; - reusing %CB_ptr3 from previous case | |
| ; CHECK-NEXT: [[DST_PTR1:%.*]] = getelementptr inbounds nuw i8, ptr %dst, i32 72 | |
| ; CHECK-NEXT: [[CBLOAD6:%.*]] = call { float, float, float, float } | |
| ; CHECK-SAME: @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_s_MyConstantsst | |
| ; CHECK-SAME: target("dx.CBuffer", %MyConstants) %CB_handle, i32 5) | |
| ; CHECK-NEXT: [[F3_0:%.*]] = extractvalue { float, float, float, float } [[CBLOAD6]], 0 | |
| ; CHECK-NEXT: [[F3_1:%.*]] = extractvalue { float, float, float, float } [[CBLOAD6]], 1 | |
| ; CHECK-NEXT: [[F3_2:%.*]] = extractvalue { float, float, float, float } [[CBLOAD6]], 2 | |
| ; CHECK-NEXT: [[VEC0:%.*]] = insertelement <3 x float> poison, float [[F3_0]], i32 0 | |
| ; CHECK-NEXT: [[VEC1:%.*]] = insertelement <3 x float> [[VEC0]], float [[F3_1]], i32 1 | |
| ; CHECK-NEXT: [[VEC2:%.*]] = insertelement <3 x float> [[VEC1]], float [[F3_2]], i32 2 | |
| ; CHECK-NEXT: store <3 x float> [[VEC2]], ptr [[DST_PTR1]], align 4 | |
| ; CHECK-NEXT: [[DST_PTR2:%.*]] = getelementptr inbounds nuw i8, ptr %dst, i32 84 | |
| ; CHECK-NEXT: [[CBLOAD7:%.*]] = call { i32, i32, i32, i32 } | |
| ; CHECK-SAME: @llvm.dx.resource.load.cbufferrow.4.i32.i32.i32.i32.tdx.CBuffer_s_MyConstantsst | |
| ; CHECK-SAME: target("dx.CBuffer", %MyConstants) %CB_handle, i32 5) | |
| ; CHECK-NEXT: [[A:%.*]] = extractvalue { i32, i32, i32, i32 } [[CBLOAD7]], 3 | |
| ; CHECK-NEXT: store i32 [[A]], ptr [[DST_PTR2]], align 4 | |
| %CB_ptr4 = call noundef align 1 dereferenceable(72) ptr addrspace(2) | |
| @llvm.dx.resource.getbasepointer.p2.tdx.CBuffer_s_MyConstantsst(target("dx.CBuffer", %MyConstants) %CB_handle) | |
| %s_ptr = getelementptr inbounds nuw %MyConstants, ptr addrspace(2) %CB_ptr4, i32 0, i32 9 | |
| %s_f3_ptr = getelementptr inbounds %S, ptr addrspace(2) %s_ptr, i32 0, i32 0 | |
| %dst6 = getelementptr inbounds nuw i8, ptr %dst, i32 72 | |
| %s_f3 = load <3 x float>, ptr addrspace(2) %s_f3_ptr, align 4 | |
| store <3 x float> %s_f3, ptr %dst6, align 4 | |
| %s_a_ptr = getelementptr inbounds %S, ptr addrspace(2) %s_ptr, i32 0, i32 1 | |
| %dst7 = getelementptr inbounds nuw i8, ptr %dst, i32 84 | |
| %s_a = load i32, ptr addrspace(2) %s_a_ptr, align 4 | |
| store i32 %s_a, ptr %dst7, align 4 | |
| ; - CB.s.a | |
| ; | |
| ; CHECK: [[CBLOAD8:%.*]] = call { i32, i32, i32, i32 } | |
| ; CHECK-SAME: @llvm.dx.resource.load.cbufferrow.4.i32.i32.i32.i32.tdx.CBuffer_s_MyConstantsst( | |
| ; CHECK-SAME: target("dx.CBuffer", %MyConstants) %CB_handle, i32 5) | |
| ; CHECK-NEXT: [[S_A:%.*]] = extractvalue { i32, i32, i32, i32 } [[CBLOAD8]], 3 | |
| ; CHECK-NEXT: [[DST_PTR:%.*]] = getelementptr inbounds nuw i8, ptr %dst, i32 88 | |
| ; CHECK-NEXT: store i32 [[S_A]], ptr [[DST_PTR]], align 4 | |
| %CB_ptr5 = call noundef align 1 dereferenceable(72) ptr addrspace(2) | |
| @llvm.dx.resource.getbasepointer.p2.tdx.CBuffer_s_MyConstantsst(target("dx.CBuffer", %MyConstants) %CB_handle) | |
| %s1_ptr = getelementptr inbounds nuw %MyConstants, ptr addrspace(2) %CB_ptr5, i32 0, i32 9 | |
| %s1_a_ptr = getelementptr inbounds nuw %S, ptr addrspace(2) %s_ptr, i32 0, i32 1 | |
| %s1_a = load i32, ptr addrspace(2) %s1_a_ptr, align 4 | |
| %dst8 = getelementptr inbounds nuw i8, ptr %dst, i32 88 | |
| store i32 %s1_a, ptr %dst8, align 4 | |
| ret void | |
| } | |
| ; CHECK-NOT: call {{.*}} @llvm.dx.resource.getbasepointer |