llvm-project/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptDynamicSwizzle.hlsl
Farzon Lotfi 88788dcd5b
[HLSL][Matrix] Implement dynamic single subscript swizzle (#173201)
fixes #170777

If we don't use vector type and instead continue to pass on the matrix
type when we enter `EmitExtVectorElementExpr` Then we don't need to
store the row and column length on the LValue.

Using the Matrix type means we can reuse the isMatrixRow() cases in
EmitLoadOfLValue and EmitStoreThroughLValue and not have to support a
new lValue that is a hybrid between the ExtVectorElt and MatrixRow
cases.

All we need to do to support this is pass the list of column indices as
a `ConstantDataVector` and check the size of this Vector to know how
many column iterations we need to do. Further just index into the vector
to fetch the right encoded element index value.
2026-01-07 11:57:04 -05:00

154 lines
9.6 KiB
HLSL

// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.7-library -disable-llvm-passes -emit-llvm -finclude-default-header -o - %s | FileCheck %s
// CHECK-LABEL: define hidden void @_Z9setMatrixRu11matrix_typeILm4ELm4EfEiDv4_f(
// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[M:%.*]], i32 noundef [[INDEX:%.*]], <4 x float> noundef nofpclass(nan inf) [[V:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[M_ADDR:%.*]] = alloca ptr, align 4
// CHECK-NEXT: [[INDEX_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[V_ADDR:%.*]] = alloca <4 x float>, align 16
// CHECK-NEXT: store ptr [[M]], ptr [[M_ADDR]], align 4
// CHECK-NEXT: store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
// CHECK-NEXT: store <4 x float> [[V]], ptr [[V_ADDR]], align 16
// CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[V_ADDR]], align 16
// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[M_ADDR]], align 4, !nonnull [[META3:![0-9]+]], !align [[META4:![0-9]+]]
// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
// CHECK-NEXT: [[MATRIX_LOAD:%.*]] = load <16 x float>, ptr [[TMP1]], align 4
// CHECK-NEXT: [[TMP3:%.*]] = add i32 12, [[TMP2]]
// CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
// CHECK-NEXT: [[TMP5:%.*]] = insertelement <16 x float> [[MATRIX_LOAD]], float [[TMP4]], i32 [[TMP3]]
// CHECK-NEXT: [[TMP6:%.*]] = add i32 8, [[TMP2]]
// CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
// CHECK-NEXT: [[TMP8:%.*]] = insertelement <16 x float> [[TMP5]], float [[TMP7]], i32 [[TMP6]]
// CHECK-NEXT: [[TMP9:%.*]] = add i32 4, [[TMP2]]
// CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
// CHECK-NEXT: [[TMP11:%.*]] = insertelement <16 x float> [[TMP8]], float [[TMP10]], i32 [[TMP9]]
// CHECK-NEXT: [[TMP12:%.*]] = add i32 0, [[TMP2]]
// CHECK-NEXT: [[TMP13:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
// CHECK-NEXT: [[TMP14:%.*]] = insertelement <16 x float> [[TMP11]], float [[TMP13]], i32 [[TMP12]]
// CHECK-NEXT: store <16 x float> [[TMP14]], ptr [[TMP1]], align 4
// CHECK-NEXT: ret void
//
void setMatrix(out float4x4 M, int index, float4 V) {
M[index].abgr = V;
}
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> @_Z9getMatrixu11matrix_typeILm4ELm4EfEi(
// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[M:%.*]], i32 noundef [[INDEX:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[M_ADDR:%.*]] = alloca [16 x float], align 4
// CHECK-NEXT: [[INDEX_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store <16 x float> [[M]], ptr [[M_ADDR]], align 4
// CHECK-NEXT: store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, ptr [[M_ADDR]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = add i32 0, [[TMP0]]
// CHECK-NEXT: [[TMP3:%.*]] = extractelement <16 x float> [[TMP1]], i32 [[TMP2]]
// CHECK-NEXT: [[TMP4:%.*]] = insertelement <3 x float> poison, float [[TMP3]], i32 0
// CHECK-NEXT: [[TMP5:%.*]] = add i32 4, [[TMP0]]
// CHECK-NEXT: [[TMP6:%.*]] = extractelement <16 x float> [[TMP1]], i32 [[TMP5]]
// CHECK-NEXT: [[TMP7:%.*]] = insertelement <3 x float> [[TMP4]], float [[TMP6]], i32 1
// CHECK-NEXT: [[TMP8:%.*]] = add i32 8, [[TMP0]]
// CHECK-NEXT: [[TMP9:%.*]] = extractelement <16 x float> [[TMP1]], i32 [[TMP8]]
// CHECK-NEXT: [[TMP10:%.*]] = insertelement <3 x float> [[TMP7]], float [[TMP9]], i32 2
// CHECK-NEXT: ret <3 x float> [[TMP10]]
//
float3 getMatrix(float4x4 M, int index) {
return M[index].rgb;
}
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> @_Z9getMatrixu11matrix_typeILm3ELm3EfEi(
// CHECK-SAME: <9 x float> noundef nofpclass(nan inf) [[M:%.*]], i32 noundef [[INDEX:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[M_ADDR:%.*]] = alloca [9 x float], align 4
// CHECK-NEXT: [[INDEX_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store <9 x float> [[M]], ptr [[M_ADDR]], align 4
// CHECK-NEXT: store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load <9 x float>, ptr [[M_ADDR]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = add i32 0, [[TMP0]]
// CHECK-NEXT: [[TMP3:%.*]] = extractelement <9 x float> [[TMP1]], i32 [[TMP2]]
// CHECK-NEXT: [[TMP4:%.*]] = insertelement <4 x float> poison, float [[TMP3]], i32 0
// CHECK-NEXT: [[TMP5:%.*]] = add i32 3, [[TMP0]]
// CHECK-NEXT: [[TMP6:%.*]] = extractelement <9 x float> [[TMP1]], i32 [[TMP5]]
// CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[TMP4]], float [[TMP6]], i32 1
// CHECK-NEXT: [[TMP8:%.*]] = add i32 6, [[TMP0]]
// CHECK-NEXT: [[TMP9:%.*]] = extractelement <9 x float> [[TMP1]], i32 [[TMP8]]
// CHECK-NEXT: [[TMP10:%.*]] = insertelement <4 x float> [[TMP7]], float [[TMP9]], i32 2
// CHECK-NEXT: [[TMP11:%.*]] = add i32 0, [[TMP0]]
// CHECK-NEXT: [[TMP12:%.*]] = extractelement <9 x float> [[TMP1]], i32 [[TMP11]]
// CHECK-NEXT: [[TMP13:%.*]] = insertelement <4 x float> [[TMP10]], float [[TMP12]], i32 3
// CHECK-NEXT: ret <4 x float> [[TMP13]]
//
float4 getMatrix(float3x3 M, int index) {
return M[index].rgbr;
}
// CHECK-LABEL: define hidden noundef <3 x i32> @_Z19getMatrixSwizzle2x3Ru11matrix_typeILm2ELm3EiEi(
// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(24) [[M:%.*]], i32 noundef [[INDEX:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[M_ADDR:%.*]] = alloca ptr, align 4
// CHECK-NEXT: [[INDEX_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store ptr [[M]], ptr [[M_ADDR]], align 4
// CHECK-NEXT: store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[M_ADDR]], align 4, !nonnull [[META3]], !align [[META4]]
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = load <6 x i32>, ptr [[TMP0]], align 4
// CHECK-NEXT: [[TMP3:%.*]] = add i32 4, [[TMP1]]
// CHECK-NEXT: [[TMP4:%.*]] = extractelement <6 x i32> [[TMP2]], i32 [[TMP3]]
// CHECK-NEXT: [[TMP5:%.*]] = insertelement <3 x i32> poison, i32 [[TMP4]], i32 0
// CHECK-NEXT: [[TMP6:%.*]] = add i32 0, [[TMP1]]
// CHECK-NEXT: [[TMP7:%.*]] = extractelement <6 x i32> [[TMP2]], i32 [[TMP6]]
// CHECK-NEXT: [[TMP8:%.*]] = insertelement <3 x i32> [[TMP5]], i32 [[TMP7]], i32 1
// CHECK-NEXT: [[TMP9:%.*]] = add i32 2, [[TMP1]]
// CHECK-NEXT: [[TMP10:%.*]] = extractelement <6 x i32> [[TMP2]], i32 [[TMP9]]
// CHECK-NEXT: [[TMP11:%.*]] = insertelement <3 x i32> [[TMP8]], i32 [[TMP10]], i32 2
// CHECK-NEXT: ret <3 x i32> [[TMP11]]
//
int3 getMatrixSwizzle2x3(out int2x3 M, int index) {
return M[index].brg;
}
// CHECK-LABEL: define hidden void @_Z26setMatrixSwizzleFromMatrixRu11matrix_typeILm2ELm3EiES_i(
// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(24) [[M:%.*]], <6 x i32> noundef [[N:%.*]], i32 noundef [[INDEX:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[M_ADDR:%.*]] = alloca ptr, align 4
// CHECK-NEXT: [[N_ADDR:%.*]] = alloca [6 x i32], align 4
// CHECK-NEXT: [[INDEX_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store ptr [[M]], ptr [[M_ADDR]], align 4
// CHECK-NEXT: store <6 x i32> [[N]], ptr [[N_ADDR]], align 4
// CHECK-NEXT: store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load <6 x i32>, ptr [[N_ADDR]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = add i32 0, [[TMP0]]
// CHECK-NEXT: [[MATRIX_ELEM:%.*]] = extractelement <6 x i32> [[TMP1]], i32 [[TMP2]]
// CHECK-NEXT: [[MATRIX_ROW_INS:%.*]] = insertelement <3 x i32> poison, i32 [[MATRIX_ELEM]], i32 0
// CHECK-NEXT: [[TMP3:%.*]] = add i32 2, [[TMP0]]
// CHECK-NEXT: [[MATRIX_ELEM1:%.*]] = extractelement <6 x i32> [[TMP1]], i32 [[TMP3]]
// CHECK-NEXT: [[MATRIX_ROW_INS2:%.*]] = insertelement <3 x i32> [[MATRIX_ROW_INS]], i32 [[MATRIX_ELEM1]], i32 1
// CHECK-NEXT: [[TMP4:%.*]] = add i32 4, [[TMP0]]
// CHECK-NEXT: [[MATRIX_ELEM3:%.*]] = extractelement <6 x i32> [[TMP1]], i32 [[TMP4]]
// CHECK-NEXT: [[MATRIX_ROW_INS4:%.*]] = insertelement <3 x i32> [[MATRIX_ROW_INS2]], i32 [[MATRIX_ELEM3]], i32 2
// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[M_ADDR]], align 4, !nonnull [[META3]], !align [[META4]]
// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
// CHECK-NEXT: [[MATRIX_LOAD:%.*]] = load <6 x i32>, ptr [[TMP5]], align 4
// CHECK-NEXT: [[TMP7:%.*]] = add i32 4, [[TMP6]]
// CHECK-NEXT: [[TMP8:%.*]] = extractelement <3 x i32> [[MATRIX_ROW_INS4]], i32 0
// CHECK-NEXT: [[TMP9:%.*]] = insertelement <6 x i32> [[MATRIX_LOAD]], i32 [[TMP8]], i32 [[TMP7]]
// CHECK-NEXT: [[TMP10:%.*]] = add i32 0, [[TMP6]]
// CHECK-NEXT: [[TMP11:%.*]] = extractelement <3 x i32> [[MATRIX_ROW_INS4]], i32 1
// CHECK-NEXT: [[TMP12:%.*]] = insertelement <6 x i32> [[TMP9]], i32 [[TMP11]], i32 [[TMP10]]
// CHECK-NEXT: [[TMP13:%.*]] = add i32 2, [[TMP6]]
// CHECK-NEXT: [[TMP14:%.*]] = extractelement <3 x i32> [[MATRIX_ROW_INS4]], i32 2
// CHECK-NEXT: [[TMP15:%.*]] = insertelement <6 x i32> [[TMP12]], i32 [[TMP14]], i32 [[TMP13]]
// CHECK-NEXT: store <6 x i32> [[TMP15]], ptr [[TMP5]], align 4
// CHECK-NEXT: ret void
//
void setMatrixSwizzleFromMatrix(out int2x3 M, int2x3 N, int index) {
M[index].brg = N[index];
}
//.
// CHECK: [[META3]] = !{}
// CHECK: [[META4]] = !{i64 4}
//.