Files
TheRock/compiler/amd-llvm/clang/test/CodeGenHLSL/builtins/mul.hlsl
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

191 lines
12 KiB
HLSL

// RUN: %clang_cc1 -finclude-default-header -O1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -emit-llvm -fmatrix-memory-layout=column-major -o - %s | FileCheck %s --check-prefixes=CHECK,COLMAJOR,DXIL
// RUN: %clang_cc1 -finclude-default-header -O1 -triple spirv-unknown-vulkan1.3-library -fnative-half-type -emit-llvm -fmatrix-memory-layout=column-major -o - %s | FileCheck %s --check-prefixes=CHECK,COLMAJOR,SPIRV
// RUN: %clang_cc1 -finclude-default-header -O1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -emit-llvm -fmatrix-memory-layout=row-major -o - %s | FileCheck %s --check-prefixes=CHECK,ROWMAJOR,DXIL
// RUN: %clang_cc1 -finclude-default-header -O1 -triple spirv-unknown-vulkan1.3-library -fnative-half-type -emit-llvm -fmatrix-memory-layout=row-major -o - %s | FileCheck %s --check-prefixes=CHECK,ROWMAJOR,SPIRV
// XFAIL: *
// -- Case 1: scalar * scalar -> scalar --
// CHECK-LABEL: test_scalar_mulf
// CHECK: %mul.i = fmul {{.*}} float %b, %a
// CHECK: ret float %mul.i
export float test_scalar_mulf(float a, float b) { return mul(a, b); }
// CHECK-LABEL: test_scalar_muli
// CHECK: %mul.i = mul {{.*}} i32 %b, %a
// CHECK: ret i32 %mul.i
export int test_scalar_muli(int a, int b) { return mul(a, b); }
// -- Case 2: scalar * vector -> vector --
// CHECK-LABEL: test_scalar_vec_mul
// CHECK: %splat.splatinsert.i = insertelement <3 x float> poison, float %a, i64 0
// CHECK: %splat.splat.i = shufflevector <3 x float> %splat.splatinsert.i, <3 x float> poison, <3 x i32> zeroinitializer
// CHECK: %mul.i = fmul {{.*}} <3 x float> %splat.splat.i, %b
// CHECK: ret <3 x float> %mul.i
export float3 test_scalar_vec_mul(float a, float3 b) { return mul(a, b); }
// -- Case 3: scalar * matrix -> matrix --
// CHECK-LABEL: test_scalar_mat_mul
// CHECK: %scalar.splat.splatinsert.i = insertelement <6 x float> poison, float %a, i64 0
// CHECK: %scalar.splat.splat.i = shufflevector <6 x float> %scalar.splat.splatinsert.i, <6 x float> poison, <6 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul {{.*}} <6 x float> %scalar.splat.splat.i, %b
// CHECK: ret <6 x float> [[MUL]]
export float2x3 test_scalar_mat_mul(float a, float2x3 b) { return mul(a, b); }
// -- Case 4: vector * scalar -> vector --
// CHECK-LABEL: test_vec_scalar_mul
// CHECK: %splat.splatinsert.i = insertelement <3 x float> poison, float %b, i64 0
// CHECK: %splat.splat.i = shufflevector <3 x float> %splat.splatinsert.i, <3 x float> poison, <3 x i32> zeroinitializer
// CHECK: %mul.i = fmul {{.*}} <3 x float> %splat.splat.i, %a
// CHECK: ret <3 x float> %mul.i
export float3 test_vec_scalar_mul(float3 a, float b) { return mul(a, b); }
// -- Case 5: vector * vector -> scalar (dot product) --
// CHECK-LABEL: test_vec_vec_mul
// DXIL: %hlsl.dot.i = {{.*}} call {{.*}} float @llvm.dx.fdot.v3f32(<3 x float> {{.*}} %a, <3 x float> {{.*}} %b)
// SPIRV: %hlsl.dot.i = {{.*}} call {{.*}} float @llvm.spv.fdot.v3f32(<3 x float> {{.*}} %a, <3 x float> {{.*}} %b)
// CHECK: ret float %hlsl.dot.i
export float test_vec_vec_mul(float3 a, float3 b) { return mul(a, b); }
// CHECK-LABEL: test_vec_vec_muli
// DXIL: %hlsl.dot.i = {{.*}} call {{.*}} i32 @llvm.dx.sdot.v3i32(<3 x i32> %a, <3 x i32> %b)
// SPIRV: %hlsl.dot.i = {{.*}} call {{.*}} i32 @llvm.spv.sdot.v3i32(<3 x i32> %a, <3 x i32> %b)
// CHECK: ret i32 %hlsl.dot.i
export int test_vec_vec_muli(int3 a, int3 b) { return mul(a, b); }
// CHECK-LABEL: test_vec_vec_mulu
// DXIL: %hlsl.dot.i = {{.*}} call {{.*}} i32 @llvm.dx.udot.v3i32(<3 x i32> %a, <3 x i32> %b)
// SPIRV: %hlsl.dot.i = {{.*}} call {{.*}} i32 @llvm.spv.udot.v3i32(<3 x i32> %a, <3 x i32> %b)
// CHECK: ret i32 %hlsl.dot.i
export uint test_vec_vec_mulu(uint3 a, uint3 b) { return mul(a, b); }
// Double vector dot product: uses fmul + fmuladd.
// The initial fmul may be vectorized by VectorCombine depending on build configuration.
// CHECK-LABEL: test_vec_vec_muld
// CHECK-NOT: @llvm.dx.fdot
// CHECK-NOT: @llvm.spv.fdot
// CHECK: fmul {{.*}} double
// CHECK: %hlsl.fmad.i = {{.*}}call {{.*}} double @llvm.fmuladd.f64(double %{{.*}}, double %{{.*}}, double %{{.*}})
// CHECK: %hlsl.fmad.i.1 = {{.*}}call {{.*}} double @llvm.fmuladd.f64(double %{{.*}}, double %{{.*}}, double %hlsl.fmad.i)
// CHECK: ret double %hlsl.fmad.i.1
export double test_vec_vec_muld(double3 a, double3 b) { return mul(a, b); }
// -- Case 6: vector * matrix -> vector --
// CHECK-LABEL: test_vec_mat_mul
// ROWMAJOR: %[[TRANSPOSE:.*]] = {{.*}} call {{.*}} <6 x float> @llvm.matrix.transpose.v6f32(<6 x float> %m, i32 3, i32 2)
// ROWMAJOR: %hlsl.mul = {{.*}} call {{.*}} <3 x float> @llvm.matrix.multiply.v3f32.v2f32.v6f32(<2 x float> %v, <6 x float> %[[TRANSPOSE]], i32 1, i32 2, i32 3)
// COLMAJOR: %hlsl.mul = {{.*}} call {{.*}} <3 x float> @llvm.matrix.multiply.v3f32.v2f32.v6f32(<2 x float> %v, <6 x float> %m, i32 1, i32 2, i32 3)
// CHECK: ret <3 x float> %hlsl.mul
export float3 test_vec_mat_mul(float2 v, float2x3 m) { return mul(v, m); }
// -- Case 7: matrix * scalar -> matrix --
// CHECK-LABEL: test_mat_scalar_mul
// CHECK: %scalar.splat.splatinsert.i = insertelement <6 x float> poison, float %b, i64 0
// CHECK: %scalar.splat.splat.i = shufflevector <6 x float> %scalar.splat.splatinsert.i, <6 x float> poison, <6 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul {{.*}} <6 x float> %scalar.splat.splat.i, %a
// CHECK: ret <6 x float> [[MUL]]
export float2x3 test_mat_scalar_mul(float2x3 a, float b) { return mul(a, b); }
// -- Case 8: matrix * vector -> vector --
// CHECK-LABEL: test_mat_vec_mul
// ROWMAJOR: %[[TRANSPOSE:.*]] = {{.*}} call {{.*}} <6 x float> @llvm.matrix.transpose.v6f32(<6 x float> %m, i32 3, i32 2)
// ROWMAJOR: %hlsl.mul = {{.*}} call {{.*}} <2 x float> @llvm.matrix.multiply.v2f32.v6f32.v3f32(<6 x float> %[[TRANSPOSE]], <3 x float> %v, i32 2, i32 3, i32 1)
// COLMAJOR: %hlsl.mul = {{.*}} call {{.*}} <2 x float> @llvm.matrix.multiply.v2f32.v6f32.v3f32(<6 x float> %m, <3 x float> %v, i32 2, i32 3, i32 1)
// CHECK: ret <2 x float> %hlsl.mul
export float2 test_mat_vec_mul(float2x3 m, float3 v) { return mul(m, v); }
// -- Case 9: matrix * matrix -> matrix --
// CHECK-LABEL: test_mat_mat_mul
// ROWMAJOR: %[[TRANSPOSE_A:.*]] = {{.*}} call {{.*}} <6 x float> @llvm.matrix.transpose.v6f32(<6 x float> %a, i32 3, i32 2)
// ROWMAJOR: %[[TRANSPOSE_B:.*]] = {{.*}} call {{.*}} <12 x float> @llvm.matrix.transpose.v12f32(<12 x float> %b, i32 4, i32 3)
// ROWMAJOR: %hlsl.mul = {{.*}} call {{.*}} <8 x float> @llvm.matrix.multiply.v8f32.v6f32.v12f32(<6 x float> %[[TRANSPOSE_A]], <12 x float> %[[TRANSPOSE_B]], i32 2, i32 3, i32 4)
// COLMAJOR: %hlsl.mul = {{.*}} call {{.*}} <8 x float> @llvm.matrix.multiply.v8f32.v6f32.v12f32(<6 x float> %a, <12 x float> %b, i32 2, i32 3, i32 4)
// COLMAJOR: ret <8 x float> %hlsl.mul
// ROWMAJOR: %[[TRANSPOSE_RES:.*]] = {{.*}} call {{.*}} <8 x float> @llvm.matrix.transpose.v8f32(<8 x float> %hlsl.mul, i32 2, i32 4)
// ROWMAJOR: ret <8 x float> %[[TRANSPOSE_RES]]
export float2x4 test_mat_mat_mul(float2x3 a, float3x4 b) { return mul(a, b); }
// -- Integer matrix multiply --
// CHECK-LABEL: test_mat_mat_muli
// ROWMAJOR: %[[TRANSPOSE_A:.*]] = {{.*}} call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> %a, i32 3, i32 2)
// ROWMAJOR: %[[TRANSPOSE_B:.*]] = {{.*}} call <12 x i32> @llvm.matrix.transpose.v12i32(<12 x i32> %b, i32 4, i32 3)
// ROWMAJOR: %hlsl.mul = {{.*}} call <8 x i32> @llvm.matrix.multiply.v8i32.v6i32.v12i32(<6 x i32> %[[TRANSPOSE_A]], <12 x i32> %[[TRANSPOSE_B]], i32 2, i32 3, i32 4)
// COLMAJOR: %hlsl.mul = {{.*}} call <8 x i32> @llvm.matrix.multiply.v8i32.v6i32.v12i32(<6 x i32> %a, <12 x i32> %b, i32 2, i32 3, i32 4)
// COLMAJOR: ret <8 x i32> %hlsl.mul
// ROWMAJOR: %[[TRANSPOSE_RES:.*]] = {{.*}} call <8 x i32> @llvm.matrix.transpose.v8i32(<8 x i32> %hlsl.mul, i32 2, i32 4)
// ROWMAJOR: ret <8 x i32> %[[TRANSPOSE_RES]]
export int2x4 test_mat_mat_muli(int2x3 a, int3x4 b) { return mul(a, b); }
// -- Half-type overloads (native half) --
// CHECK-LABEL: test_scalar_mulh
// CHECK: %mul.i = fmul {{.*}} half %b, %a
// CHECK: ret half %mul.i
export half test_scalar_mulh(half a, half b) { return mul(a, b); }
// CHECK-LABEL: test_scalar_vec_mulh
// CHECK: %splat.splatinsert.i = insertelement <3 x half> poison, half %a, i64 0
// CHECK: %splat.splat.i = shufflevector <3 x half> %splat.splatinsert.i, <3 x half> poison, <3 x i32> zeroinitializer
// CHECK: %mul.i = fmul {{.*}} <3 x half> %splat.splat.i, %b
// CHECK: ret <3 x half> %mul.i
export half3 test_scalar_vec_mulh(half a, half3 b) { return mul(a, b); }
// CHECK-LABEL: test_scalar_mat_mulh
// CHECK: %scalar.splat.splatinsert.i = insertelement <6 x half> poison, half %a, i64 0
// CHECK: %scalar.splat.splat.i = shufflevector <6 x half> %scalar.splat.splatinsert.i, <6 x half> poison, <6 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul {{.*}} <6 x half> %scalar.splat.splat.i, %b
// CHECK: ret <6 x half> [[MUL]]
export half2x3 test_scalar_mat_mulh(half a, half2x3 b) { return mul(a, b); }
// CHECK-LABEL: test_vec_scalar_mulh
// CHECK: %splat.splatinsert.i = insertelement <3 x half> poison, half %b, i64 0
// CHECK: %splat.splat.i = shufflevector <3 x half> %splat.splatinsert.i, <3 x half> poison, <3 x i32> zeroinitializer
// CHECK: %mul.i = fmul {{.*}} <3 x half> %splat.splat.i, %a
// CHECK: ret <3 x half> %mul.i
export half3 test_vec_scalar_mulh(half3 a, half b) { return mul(a, b); }
// CHECK-LABEL: test_vec_vec_mulh
// DXIL: %hlsl.dot.i = {{.*}}call {{.*}} half @llvm.dx.fdot.v3f16(<3 x half> {{.*}} %a, <3 x half> {{.*}} %b)
// SPIRV: %hlsl.dot.i = {{.*}}call {{.*}} half @llvm.spv.fdot.v3f16(<3 x half> {{.*}} %a, <3 x half> {{.*}} %b)
// CHECK: ret half %hlsl.dot.i
export half test_vec_vec_mulh(half3 a, half3 b) { return mul(a, b); }
// CHECK-LABEL: test_mat_scalar_mulh
// CHECK: %scalar.splat.splatinsert.i = insertelement <6 x half> poison, half %b, i64 0
// CHECK: %scalar.splat.splat.i = shufflevector <6 x half> %scalar.splat.splatinsert.i, <6 x half> poison, <6 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul {{.*}} <6 x half> %scalar.splat.splat.i, %a
// CHECK: ret <6 x half> [[MUL]]
export half2x3 test_mat_scalar_mulh(half2x3 a, half b) { return mul(a, b); }
// CHECK-LABEL: test_vec_mat_mulh
// ROWMAJOR: %[[TRANSPOSE:.*]] = {{.*}} call {{.*}} <6 x half> @llvm.matrix.transpose.v6f16(<6 x half> %m, i32 3, i32 2)
// ROWMAJOR: %hlsl.mul = {{.*}}call {{.*}} <3 x half> @llvm.matrix.multiply.v3f16.v2f16.v6f16(<2 x half> %v, <6 x half> %[[TRANSPOSE]], i32 1, i32 2, i32 3)
// COLMAJOR: %hlsl.mul = {{.*}}call {{.*}} <3 x half> @llvm.matrix.multiply.v3f16.v2f16.v6f16(<2 x half> %v, <6 x half> %m, i32 1, i32 2, i32 3)
// CHECK: ret <3 x half> %hlsl.mul
export half3 test_vec_mat_mulh(half2 v, half2x3 m) { return mul(v, m); }
// CHECK-LABEL: test_mat_vec_mulh
// ROWMAJOR: %[[TRANSPOSE:.*]] = {{.*}} call {{.*}} <6 x half> @llvm.matrix.transpose.v6f16(<6 x half> %m, i32 3, i32 2)
// ROWMAJOR: %hlsl.mul = {{.*}}call {{.*}} <2 x half> @llvm.matrix.multiply.v2f16.v6f16.v3f16(<6 x half> %[[TRANSPOSE]], <3 x half> %v, i32 2, i32 3, i32 1)
// COLMAJOR: %hlsl.mul = {{.*}}call {{.*}} <2 x half> @llvm.matrix.multiply.v2f16.v6f16.v3f16(<6 x half> %m, <3 x half> %v, i32 2, i32 3, i32 1)
// CHECK: ret <2 x half> %hlsl.mul
export half2 test_mat_vec_mulh(half2x3 m, half3 v) { return mul(m, v); }
// CHECK-LABEL: test_mat_mat_mulh
// ROWMAJOR: %[[TRANSPOSE_A:.*]] = {{.*}} call {{.*}} <6 x half> @llvm.matrix.transpose.v6f16(<6 x half> %a, i32 3, i32 2)
// ROWMAJOR: %[[TRANSPOSE_B:.*]] = {{.*}} call {{.*}} <12 x half> @llvm.matrix.transpose.v12f16(<12 x half> %b, i32 4, i32 3)
// ROWMAJOR: %hlsl.mul = {{.*}}call {{.*}} <8 x half> @llvm.matrix.multiply.v8f16.v6f16.v12f16(<6 x half> %[[TRANSPOSE_A]], <12 x half> %[[TRANSPOSE_B]], i32 2, i32 3, i32 4)
// COLMAJOR: %hlsl.mul = {{.*}}call {{.*}} <8 x half> @llvm.matrix.multiply.v8f16.v6f16.v12f16(<6 x half> %a, <12 x half> %b, i32 2, i32 3, i32 4)
// COLMAJOR: ret <8 x half> %hlsl.mul
// ROWMAJOR: %[[TRANSPOSE_RES:.*]] = {{.*}} call {{.*}} <8 x half> @llvm.matrix.transpose.v8f16(<8 x half> %hlsl.mul, i32 2, i32 4)
// ROWMAJOR: ret <8 x half> %[[TRANSPOSE_RES]]
export half2x4 test_mat_mat_mulh(half2x3 a, half3x4 b) { return mul(a, b); }