Sarah Spall 7f34d3acba
[DirectX] Add support for typedBufferLoad and Store for RWBuffer<double2> and RWBuffer<double> (#139996)
typedBufferLoad of double/double2 is expanded to a typedBufferLoad of a
<2 x i32>/<4 x i32> and asdouble
typedBufferStore of a double/double2 is expanded to a splitdouble and a
typedBufferStore of a <2 x i32>/<4 x i32>
Add tests showing result of intrinsic expansion for typedBufferLoad and
typedBufferStore
Add tests showing dxil op lowering can handle typedBufferLoad and
typedBufferStore where the target type doesn't match the typedBufferLoad
and typedBufferStore type
Closes #104423
2025-05-30 08:16:19 -07:00

205 lines
9.8 KiB
LLVM

; RUN: opt -S -dxil-op-lower %s | FileCheck %s
target triple = "dxil-pc-shadermodel6.6-compute"
; CHECK-LABEL: define void @storefloats
define void @storefloats(<4 x float> %data, i32 %index) {
; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
%buffer = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_1_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false, ptr null)
; The temporary casts should all have been cleaned up
; CHECK-NOT: %dx.resource.casthandle
; CHECK: [[DATA0_0:%.*]] = extractelement <4 x float> %data, i32 0
; CHECK: [[DATA0_1:%.*]] = extractelement <4 x float> %data, i32 1
; CHECK: [[DATA0_2:%.*]] = extractelement <4 x float> %data, i32 2
; CHECK: [[DATA0_3:%.*]] = extractelement <4 x float> %data, i32 3
; CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, float [[DATA0_0]], float [[DATA0_1]], float [[DATA0_2]], float [[DATA0_3]], i8 15){{$}}
call void @llvm.dx.resource.store.typedbuffer(
target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %buffer,
i32 %index, <4 x float> %data)
ret void
}
; CHECK-LABEL: define void @storeonefloat
define void @storeonefloat(float %data, i32 %index) {
; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
%buffer = call target("dx.TypedBuffer", float, 1, 0, 0)
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false, ptr null)
; The temporary casts should all have been cleaned up
; CHECK-NOT: %dx.resource.casthandle
; CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, float %data, float %data, float %data, float %data, i8 15){{$}}
call void @llvm.dx.resource.store.typedbuffer(
target("dx.TypedBuffer", float, 1, 0, 0) %buffer,
i32 %index, float %data)
ret void
}
; CHECK-LABEL: define void @storetwofloat
define void @storetwofloat(<2 x float> %data, i32 %index) {
; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
%buffer = call target("dx.TypedBuffer", <2 x float>, 1, 0, 0)
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v2f32_1_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false, ptr null)
; The temporary casts should all have been cleaned up
; CHECK-NOT: %dx.resource.casthandle
; CHECK: [[DATA0_0:%.*]] = extractelement <2 x float> %data, i32 0
; CHECK: [[DATA0_1:%.*]] = extractelement <2 x float> %data, i32 1
; CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, float [[DATA0_0]], float [[DATA0_1]], float [[DATA0_0]], float [[DATA0_0]], i8 15){{$}}
call void @llvm.dx.resource.store.typedbuffer(
target("dx.TypedBuffer", <2 x float>, 1, 0, 0) %buffer,
i32 %index, <2 x float> %data)
ret void
}
; CHECK-LABEL: define void @storeint
define void @storeint(<4 x i32> %data, i32 %index) {
; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
%buffer = call target("dx.TypedBuffer", <4 x i32>, 1, 0, 0)
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4i32_1_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false, ptr null)
; CHECK: [[DATA0_0:%.*]] = extractelement <4 x i32> %data, i32 0
; CHECK: [[DATA0_1:%.*]] = extractelement <4 x i32> %data, i32 1
; CHECK: [[DATA0_2:%.*]] = extractelement <4 x i32> %data, i32 2
; CHECK: [[DATA0_3:%.*]] = extractelement <4 x i32> %data, i32 3
; CHECK: call void @dx.op.bufferStore.i32(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, i32 [[DATA0_0]], i32 [[DATA0_1]], i32 [[DATA0_2]], i32 [[DATA0_3]], i8 15){{$}}
call void @llvm.dx.resource.store.typedbuffer(
target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %buffer,
i32 %index, <4 x i32> %data)
ret void
}
; CHECK-LABEL: define void @storehalf
define void @storehalf(<4 x half> %data, i32 %index) {
; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
%buffer = call target("dx.TypedBuffer", <4 x half>, 1, 0, 0)
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f16_1_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false, ptr null)
; The temporary casts should all have been cleaned up
; CHECK-NOT: %dx.resource.casthandle
; CHECK: [[DATA0_0:%.*]] = extractelement <4 x half> %data, i32 0
; CHECK: [[DATA0_1:%.*]] = extractelement <4 x half> %data, i32 1
; CHECK: [[DATA0_2:%.*]] = extractelement <4 x half> %data, i32 2
; CHECK: [[DATA0_3:%.*]] = extractelement <4 x half> %data, i32 3
; CHECK: call void @dx.op.bufferStore.f16(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, half [[DATA0_0]], half [[DATA0_1]], half [[DATA0_2]], half [[DATA0_3]], i8 15){{$}}
call void @llvm.dx.resource.store.typedbuffer(
target("dx.TypedBuffer", <4 x half>, 1, 0, 0) %buffer,
i32 %index, <4 x half> %data)
ret void
}
; CHECK-LABEL: define void @storei16
define void @storei16(<4 x i16> %data, i32 %index) {
; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
%buffer = call target("dx.TypedBuffer", <4 x i16>, 1, 0, 0)
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4i16_1_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false, ptr null)
; The temporary casts should all have been cleaned up
; CHECK-NOT: %dx.resource.casthandle
; CHECK: [[DATA0_0:%.*]] = extractelement <4 x i16> %data, i32 0
; CHECK: [[DATA0_1:%.*]] = extractelement <4 x i16> %data, i32 1
; CHECK: [[DATA0_2:%.*]] = extractelement <4 x i16> %data, i32 2
; CHECK: [[DATA0_3:%.*]] = extractelement <4 x i16> %data, i32 3
; CHECK: call void @dx.op.bufferStore.i16(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, i16 [[DATA0_0]], i16 [[DATA0_1]], i16 [[DATA0_2]], i16 [[DATA0_3]], i8 15){{$}}
call void @llvm.dx.resource.store.typedbuffer(
target("dx.TypedBuffer", <4 x i16>, 1, 0, 0) %buffer,
i32 %index, <4 x i16> %data)
ret void
}
; CHECK-LABEL: define void @store_scalarized_floats
define void @store_scalarized_floats(float %data0, float %data1, float %data2, float %data3, i32 %index) {
; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
%buffer = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_1_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false, ptr null)
; We shouldn't end up with any inserts/extracts.
; CHECK-NOT: insertelement
; CHECK-NOT: extractelement
; CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, float %data0, float %data1, float %data2, float %data3, i8 15)
%vec.upto0 = insertelement <4 x float> poison, float %data0, i64 0
%vec.upto1 = insertelement <4 x float> %vec.upto0, float %data1, i64 1
%vec.upto2 = insertelement <4 x float> %vec.upto1, float %data2, i64 2
%vec = insertelement <4 x float> %vec.upto2, float %data3, i64 3
call void @llvm.dx.resource.store.typedbuffer(
target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %buffer,
i32 %index, <4 x float> %vec)
ret void
}
define void @storef64(<2 x i32> %0) {
; CHECK: [[B1:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
; CHECK: [[BA:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[B1]]
%buffer = tail call target("dx.TypedBuffer", double, 1, 0, 0)
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f64_1_0_0t(
i32 0, i32 0, i32 1, i32 0, i1 false, ptr null)
; The temporary casts should all have been cleaned up
; CHECK-NOT: %dx.resource.casthandle
; CHECK: [[D0:%.*]] = extractelement <2 x i32> %0, i32 0
; CHECK: [[D1:%.*]] = extractelement <2 x i32> %0, i32 1
; CHECK: call void @dx.op.bufferStore.i32(i32 69, %dx.types.Handle [[BA]], i32 0, i32 undef, i32 %2, i32 %3, i32 %2, i32 %2, i8 15)
call void @llvm.dx.resource.store.typedbuffer(
target("dx.TypedBuffer", double, 1, 0, 0) %buffer, i32 0, <2 x i32> %0)
ret void
}
define void @storev2f64(<4 x i32> %0) {
; CHECK: [[B1:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
; CHECK: [[BA:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[B1]]
%buffer = tail call target("dx.TypedBuffer", <2 x double>, 1, 0, 0)
@llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v2f64_1_0_0t(
i32 0, i32 0, i32 1, i32 0, i1 false, ptr null)
; The temporary casts should all have been cleaned up
; CHECK-NOT: %dx.resource.casthandle
; CHECK: [[D0:%.*]] = extractelement <4 x i32> %0, i32 0
; CHECK: [[D1:%.*]] = extractelement <4 x i32> %0, i32 1
; CHECK: [[D2:%.*]] = extractelement <4 x i32> %0, i32 2
; CHECK: [[D3:%.*]] = extractelement <4 x i32> %0, i32 3
; CHECK: call void @dx.op.bufferStore.i32(i32 69, %dx.types.Handle [[BA]], i32 0, i32 undef, i32 [[D0]], i32 [[D1]], i32 [[D2]], i32 [[D3]], i8 15)
call void @llvm.dx.resource.store.typedbuffer(
target("dx.TypedBuffer", <2 x double>, 1, 0, 0) %buffer, i32 0,
<4 x i32> %0)
ret void
}