[clang] [CIR][AArch64] Migrate strict vector FMA tests (PR #232660)

Yair Ben Avraham via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 16 03:04:29 PDT 2026


https://github.com/yairbenavraham created https://github.com/llvm/llvm-project/pull/232660

The strict-FP tests for vfma_f32, vfmaq_f32, and vfmaq_f64 currently cover classic Clang but lack CIR coverage. Move them from
clang/test/CodeGen/AArch64/neon-intrinsics-constrained.c into clang/test/CodeGen/AArch64/neon/fused-multiply-constrained.c, whose existing RUN lines exercise classic CodeGen, CIR, and CIR-to-LLVM lowering.

Preserve operand tracking, strict FP metadata, and returned-result checks, following the destination file's FileCheck style. Remove the complete original test blocks; their unconstrained coverage already exists in neon/fused-multiply.c.

Assisted-by: Codex
Follow-up to #218307

>From 1b303321515dbe86266f8ef22a130280f3309766 Mon Sep 17 00:00:00 2001
From: Yair Ben Avraham <yairba at protonmail.com>
Date: Fri, 16 Oct 2026 12:54:21 +0300
Subject: [PATCH] [CIR][AArch64] Migrate strict vector FMA tests

Move test_vfma_f32, test_vfmaq_f32, and test_vfmaq_f64 from
neon-intrinsics-constrained.c to neon/fused-multiply-constrained.c.
The existing RUN lines cover classic CodeGen, CIR, and CIR-to-LLVM
under strict floating-point exception handling.

Preserve operand tracking and constrained FMA result checks, and match
the destination file's FileCheck style. Remove the superseded legacy
blocks; unconstrained coverage already lives in neon/fused-multiply.c.

Follow-up to #218307.

Assisted-by: Codex
---
 .../AArch64/neon-intrinsics-constrained.c     | 102 ------------------
 .../AArch64/neon/fused-multiply-constrained.c |  60 +++++++++++
 2 files changed, 60 insertions(+), 102 deletions(-)

diff --git a/clang/test/CodeGen/AArch64/neon-intrinsics-constrained.c b/clang/test/CodeGen/AArch64/neon-intrinsics-constrained.c
index 09f2aec4176b42..0e34273ff24d6b 100644
--- a/clang/test/CodeGen/AArch64/neon-intrinsics-constrained.c
+++ b/clang/test/CodeGen/AArch64/neon-intrinsics-constrained.c
@@ -251,108 +251,6 @@ float64x2_t test_vmlsq_f64(float64x2_t v1, float64x2_t v2, float64x2_t v3) {
   return vmlsq_f64(v1, v2, v3);
 }
 
-// UNCONSTRAINED-LABEL: define dso_local <2 x float> @test_vfma_f32(
-// UNCONSTRAINED-SAME: <2 x float> noundef [[V1:%.*]], <2 x float> noundef [[V2:%.*]], <2 x float> noundef [[V3:%.*]]) #[[ATTR0]] {
-// UNCONSTRAINED-NEXT:  [[ENTRY:.*:]]
-// UNCONSTRAINED-NEXT:    [[TMP0:%.*]] = bitcast <2 x float> [[V1]] to <2 x i32>
-// UNCONSTRAINED-NEXT:    [[TMP1:%.*]] = bitcast <2 x float> [[V2]] to <2 x i32>
-// UNCONSTRAINED-NEXT:    [[TMP2:%.*]] = bitcast <2 x float> [[V3]] to <2 x i32>
-// UNCONSTRAINED-NEXT:    [[TMP3:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8>
-// UNCONSTRAINED-NEXT:    [[TMP4:%.*]] = bitcast <2 x i32> [[TMP1]] to <8 x i8>
-// UNCONSTRAINED-NEXT:    [[TMP5:%.*]] = bitcast <2 x i32> [[TMP2]] to <8 x i8>
-// UNCONSTRAINED-NEXT:    [[TMP6:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x float>
-// UNCONSTRAINED-NEXT:    [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float>
-// UNCONSTRAINED-NEXT:    [[TMP8:%.*]] = bitcast <8 x i8> [[TMP5]] to <2 x float>
-// UNCONSTRAINED-NEXT:    [[TMP9:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[TMP7]], <2 x float> [[TMP8]], <2 x float> [[TMP6]])
-// UNCONSTRAINED-NEXT:    ret <2 x float> [[TMP9]]
-//
-// CONSTRAINED-LABEL: define dso_local <2 x float> @test_vfma_f32(
-// CONSTRAINED-SAME: <2 x float> noundef [[V1:%.*]], <2 x float> noundef [[V2:%.*]], <2 x float> noundef [[V3:%.*]]) #[[ATTR0]] {
-// CONSTRAINED-NEXT:  [[ENTRY:.*:]]
-// CONSTRAINED-NEXT:    [[TMP0:%.*]] = bitcast <2 x float> [[V1]] to <2 x i32>
-// CONSTRAINED-NEXT:    [[TMP1:%.*]] = bitcast <2 x float> [[V2]] to <2 x i32>
-// CONSTRAINED-NEXT:    [[TMP2:%.*]] = bitcast <2 x float> [[V3]] to <2 x i32>
-// CONSTRAINED-NEXT:    [[TMP3:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8>
-// CONSTRAINED-NEXT:    [[TMP4:%.*]] = bitcast <2 x i32> [[TMP1]] to <8 x i8>
-// CONSTRAINED-NEXT:    [[TMP5:%.*]] = bitcast <2 x i32> [[TMP2]] to <8 x i8>
-// CONSTRAINED-NEXT:    [[TMP6:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x float>
-// CONSTRAINED-NEXT:    [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float>
-// CONSTRAINED-NEXT:    [[TMP8:%.*]] = bitcast <8 x i8> [[TMP5]] to <2 x float>
-// CONSTRAINED-NEXT:    [[TMP9:%.*]] = call <2 x float> @llvm.experimental.constrained.fma.v2f32(<2 x float> [[TMP7]], <2 x float> [[TMP8]], <2 x float> [[TMP6]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR3]]
-// CONSTRAINED-NEXT:    ret <2 x float> [[TMP9]]
-//
-float32x2_t test_vfma_f32(float32x2_t v1, float32x2_t v2, float32x2_t v3) {
-  return vfma_f32(v1, v2, v3);
-}
-
-// UNCONSTRAINED-LABEL: define dso_local <4 x float> @test_vfmaq_f32(
-// UNCONSTRAINED-SAME: <4 x float> noundef [[V1:%.*]], <4 x float> noundef [[V2:%.*]], <4 x float> noundef [[V3:%.*]]) #[[ATTR0]] {
-// UNCONSTRAINED-NEXT:  [[ENTRY:.*:]]
-// UNCONSTRAINED-NEXT:    [[TMP0:%.*]] = bitcast <4 x float> [[V1]] to <4 x i32>
-// UNCONSTRAINED-NEXT:    [[TMP1:%.*]] = bitcast <4 x float> [[V2]] to <4 x i32>
-// UNCONSTRAINED-NEXT:    [[TMP2:%.*]] = bitcast <4 x float> [[V3]] to <4 x i32>
-// UNCONSTRAINED-NEXT:    [[TMP3:%.*]] = bitcast <4 x i32> [[TMP0]] to <16 x i8>
-// UNCONSTRAINED-NEXT:    [[TMP4:%.*]] = bitcast <4 x i32> [[TMP1]] to <16 x i8>
-// UNCONSTRAINED-NEXT:    [[TMP5:%.*]] = bitcast <4 x i32> [[TMP2]] to <16 x i8>
-// UNCONSTRAINED-NEXT:    [[TMP6:%.*]] = bitcast <16 x i8> [[TMP3]] to <4 x float>
-// UNCONSTRAINED-NEXT:    [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float>
-// UNCONSTRAINED-NEXT:    [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x float>
-// UNCONSTRAINED-NEXT:    [[TMP9:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> [[TMP7]], <4 x float> [[TMP8]], <4 x float> [[TMP6]])
-// UNCONSTRAINED-NEXT:    ret <4 x float> [[TMP9]]
-//
-// CONSTRAINED-LABEL: define dso_local <4 x float> @test_vfmaq_f32(
-// CONSTRAINED-SAME: <4 x float> noundef [[V1:%.*]], <4 x float> noundef [[V2:%.*]], <4 x float> noundef [[V3:%.*]]) #[[ATTR0]] {
-// CONSTRAINED-NEXT:  [[ENTRY:.*:]]
-// CONSTRAINED-NEXT:    [[TMP0:%.*]] = bitcast <4 x float> [[V1]] to <4 x i32>
-// CONSTRAINED-NEXT:    [[TMP1:%.*]] = bitcast <4 x float> [[V2]] to <4 x i32>
-// CONSTRAINED-NEXT:    [[TMP2:%.*]] = bitcast <4 x float> [[V3]] to <4 x i32>
-// CONSTRAINED-NEXT:    [[TMP3:%.*]] = bitcast <4 x i32> [[TMP0]] to <16 x i8>
-// CONSTRAINED-NEXT:    [[TMP4:%.*]] = bitcast <4 x i32> [[TMP1]] to <16 x i8>
-// CONSTRAINED-NEXT:    [[TMP5:%.*]] = bitcast <4 x i32> [[TMP2]] to <16 x i8>
-// CONSTRAINED-NEXT:    [[TMP6:%.*]] = bitcast <16 x i8> [[TMP3]] to <4 x float>
-// CONSTRAINED-NEXT:    [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float>
-// CONSTRAINED-NEXT:    [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x float>
-// CONSTRAINED-NEXT:    [[TMP9:%.*]] = call <4 x float> @llvm.experimental.constrained.fma.v4f32(<4 x float> [[TMP7]], <4 x float> [[TMP8]], <4 x float> [[TMP6]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR3]]
-// CONSTRAINED-NEXT:    ret <4 x float> [[TMP9]]
-//
-float32x4_t test_vfmaq_f32(float32x4_t v1, float32x4_t v2, float32x4_t v3) {
-  return vfmaq_f32(v1, v2, v3);
-}
-
-// UNCONSTRAINED-LABEL: define dso_local <2 x double> @test_vfmaq_f64(
-// UNCONSTRAINED-SAME: <2 x double> noundef [[V1:%.*]], <2 x double> noundef [[V2:%.*]], <2 x double> noundef [[V3:%.*]]) #[[ATTR0]] {
-// UNCONSTRAINED-NEXT:  [[ENTRY:.*:]]
-// UNCONSTRAINED-NEXT:    [[TMP0:%.*]] = bitcast <2 x double> [[V1]] to <2 x i64>
-// UNCONSTRAINED-NEXT:    [[TMP1:%.*]] = bitcast <2 x double> [[V2]] to <2 x i64>
-// UNCONSTRAINED-NEXT:    [[TMP2:%.*]] = bitcast <2 x double> [[V3]] to <2 x i64>
-// UNCONSTRAINED-NEXT:    [[TMP3:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8>
-// UNCONSTRAINED-NEXT:    [[TMP4:%.*]] = bitcast <2 x i64> [[TMP1]] to <16 x i8>
-// UNCONSTRAINED-NEXT:    [[TMP5:%.*]] = bitcast <2 x i64> [[TMP2]] to <16 x i8>
-// UNCONSTRAINED-NEXT:    [[TMP6:%.*]] = bitcast <16 x i8> [[TMP3]] to <2 x double>
-// UNCONSTRAINED-NEXT:    [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x double>
-// UNCONSTRAINED-NEXT:    [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <2 x double>
-// UNCONSTRAINED-NEXT:    [[TMP9:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 x double> [[TMP7]], <2 x double> [[TMP8]], <2 x double> [[TMP6]])
-// UNCONSTRAINED-NEXT:    ret <2 x double> [[TMP9]]
-//
-// CONSTRAINED-LABEL: define dso_local <2 x double> @test_vfmaq_f64(
-// CONSTRAINED-SAME: <2 x double> noundef [[V1:%.*]], <2 x double> noundef [[V2:%.*]], <2 x double> noundef [[V3:%.*]]) #[[ATTR0]] {
-// CONSTRAINED-NEXT:  [[ENTRY:.*:]]
-// CONSTRAINED-NEXT:    [[TMP0:%.*]] = bitcast <2 x double> [[V1]] to <2 x i64>
-// CONSTRAINED-NEXT:    [[TMP1:%.*]] = bitcast <2 x double> [[V2]] to <2 x i64>
-// CONSTRAINED-NEXT:    [[TMP2:%.*]] = bitcast <2 x double> [[V3]] to <2 x i64>
-// CONSTRAINED-NEXT:    [[TMP3:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8>
-// CONSTRAINED-NEXT:    [[TMP4:%.*]] = bitcast <2 x i64> [[TMP1]] to <16 x i8>
-// CONSTRAINED-NEXT:    [[TMP5:%.*]] = bitcast <2 x i64> [[TMP2]] to <16 x i8>
-// CONSTRAINED-NEXT:    [[TMP6:%.*]] = bitcast <16 x i8> [[TMP3]] to <2 x double>
-// CONSTRAINED-NEXT:    [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x double>
-// CONSTRAINED-NEXT:    [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <2 x double>
-// CONSTRAINED-NEXT:    [[TMP9:%.*]] = call <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double> [[TMP7]], <2 x double> [[TMP8]], <2 x double> [[TMP6]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR3]]
-// CONSTRAINED-NEXT:    ret <2 x double> [[TMP9]]
-//
-float64x2_t test_vfmaq_f64(float64x2_t v1, float64x2_t v2, float64x2_t v3) {
-  return vfmaq_f64(v1, v2, v3);
-}
-
 // UNCONSTRAINED-LABEL: define dso_local <2 x float> @test_vfms_f32(
 // UNCONSTRAINED-SAME: <2 x float> noundef [[V1:%.*]], <2 x float> noundef [[V2:%.*]], <2 x float> noundef [[V3:%.*]]) #[[ATTR0]] {
 // UNCONSTRAINED-NEXT:  [[ENTRY:.*:]]
diff --git a/clang/test/CodeGen/AArch64/neon/fused-multiply-constrained.c b/clang/test/CodeGen/AArch64/neon/fused-multiply-constrained.c
index 52ee3f20628511..a782c835a2fdab 100644
--- a/clang/test/CodeGen/AArch64/neon/fused-multiply-constrained.c
+++ b/clang/test/CodeGen/AArch64/neon/fused-multiply-constrained.c
@@ -6,6 +6,26 @@
 
 #include <arm_neon.h>
 
+// LLVM-LABEL: @test_vfma_f32(
+// CIR-LABEL: @vfma_f32(
+float32x2_t test_vfma_f32(float32x2_t a, float32x2_t b, float32x2_t c) {
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.float> fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, strict_except = true>
+
+// LLVM-SAME: <2 x float> {{.*}} [[A:%.*]], <2 x float> {{.*}} [[B:%.*]], <2 x float> {{.*}} [[C:%.*]]) {{.*}} {
+// LLVM: [[A_I:%.*]] = bitcast <2 x float> [[A]] to <2 x i32>
+// LLVM: [[B_I:%.*]] = bitcast <2 x float> [[B]] to <2 x i32>
+// LLVM: [[C_I:%.*]] = bitcast <2 x float> [[C]] to <2 x i32>
+// LLVM: [[A_BYTES:%.*]] = bitcast <2 x i32> [[A_I]] to <8 x i8>
+// LLVM: [[B_BYTES:%.*]] = bitcast <2 x i32> [[B_I]] to <8 x i8>
+// LLVM: [[C_BYTES:%.*]] = bitcast <2 x i32> [[C_I]] to <8 x i8>
+// LLVM: [[A_CAST:%.*]] = bitcast <8 x i8> [[A_BYTES]] to <2 x float>
+// LLVM: [[B_CAST:%.*]] = bitcast <8 x i8> [[B_BYTES]] to <2 x float>
+// LLVM: [[C_CAST:%.*]] = bitcast <8 x i8> [[C_BYTES]] to <2 x float>
+// LLVM: [[FMA:%.*]] = call <2 x float> @llvm.experimental.constrained.fma.v2f32(<2 x float> [[B_CAST]], <2 x float> [[C_CAST]], <2 x float> [[A_CAST]], metadata !"round.tonearest", metadata !"fpexcept.strict")
+// LLVM: ret <2 x float> [[FMA]]
+  return vfma_f32(a, b, c);
+}
+
 // LLVM-LABEL: @test_vfma_f64(
 // CIR-LABEL: @vfma_f64(
 float64x1_t test_vfma_f64(float64x1_t a, float64x1_t b, float64x1_t c) {
@@ -29,6 +49,46 @@ float64x1_t test_vfma_f64(float64x1_t a, float64x1_t b, float64x1_t c) {
   return vfma_f64(a, b, c);
 }
 
+// LLVM-LABEL: @test_vfmaq_f32(
+// CIR-LABEL: @vfmaq_f32(
+float32x4_t test_vfmaq_f32(float32x4_t a, float32x4_t b, float32x4_t c) {
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<4 x !cir.float> fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, strict_except = true>
+
+// LLVM-SAME: <4 x float> {{.*}} [[A:%.*]], <4 x float> {{.*}} [[B:%.*]], <4 x float> {{.*}} [[C:%.*]]) {{.*}} {
+// LLVM: [[A_I:%.*]] = bitcast <4 x float> [[A]] to <4 x i32>
+// LLVM: [[B_I:%.*]] = bitcast <4 x float> [[B]] to <4 x i32>
+// LLVM: [[C_I:%.*]] = bitcast <4 x float> [[C]] to <4 x i32>
+// LLVM: [[A_BYTES:%.*]] = bitcast <4 x i32> [[A_I]] to <16 x i8>
+// LLVM: [[B_BYTES:%.*]] = bitcast <4 x i32> [[B_I]] to <16 x i8>
+// LLVM: [[C_BYTES:%.*]] = bitcast <4 x i32> [[C_I]] to <16 x i8>
+// LLVM: [[A_CAST:%.*]] = bitcast <16 x i8> [[A_BYTES]] to <4 x float>
+// LLVM: [[B_CAST:%.*]] = bitcast <16 x i8> [[B_BYTES]] to <4 x float>
+// LLVM: [[C_CAST:%.*]] = bitcast <16 x i8> [[C_BYTES]] to <4 x float>
+// LLVM: [[FMA:%.*]] = call <4 x float> @llvm.experimental.constrained.fma.v4f32(<4 x float> [[B_CAST]], <4 x float> [[C_CAST]], <4 x float> [[A_CAST]], metadata !"round.tonearest", metadata !"fpexcept.strict")
+// LLVM: ret <4 x float> [[FMA]]
+  return vfmaq_f32(a, b, c);
+}
+
+// LLVM-LABEL: @test_vfmaq_f64(
+// CIR-LABEL: @vfmaq_f64(
+float64x2_t test_vfmaq_f64(float64x2_t a, float64x2_t b, float64x2_t c) {
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.double> fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, strict_except = true>
+
+// LLVM-SAME: <2 x double> {{.*}} [[A:%.*]], <2 x double> {{.*}} [[B:%.*]], <2 x double> {{.*}} [[C:%.*]]) {{.*}} {
+// LLVM: [[A_I:%.*]] = bitcast <2 x double> [[A]] to <2 x i64>
+// LLVM: [[B_I:%.*]] = bitcast <2 x double> [[B]] to <2 x i64>
+// LLVM: [[C_I:%.*]] = bitcast <2 x double> [[C]] to <2 x i64>
+// LLVM: [[A_BYTES:%.*]] = bitcast <2 x i64> [[A_I]] to <16 x i8>
+// LLVM: [[B_BYTES:%.*]] = bitcast <2 x i64> [[B_I]] to <16 x i8>
+// LLVM: [[C_BYTES:%.*]] = bitcast <2 x i64> [[C_I]] to <16 x i8>
+// LLVM: [[A_CAST:%.*]] = bitcast <16 x i8> [[A_BYTES]] to <2 x double>
+// LLVM: [[B_CAST:%.*]] = bitcast <16 x i8> [[B_BYTES]] to <2 x double>
+// LLVM: [[C_CAST:%.*]] = bitcast <16 x i8> [[C_BYTES]] to <2 x double>
+// LLVM: [[FMA:%.*]] = call <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double> [[B_CAST]], <2 x double> [[C_CAST]], <2 x double> [[A_CAST]], metadata !"round.tonearest", metadata !"fpexcept.strict")
+// LLVM: ret <2 x double> [[FMA]]
+  return vfmaq_f64(a, b, c);
+}
+
 // ALL-LABEL: @test_vfma_laneq_f64(
 float64x1_t test_vfma_laneq_f64(float64x1_t a, float64x1_t b,
                                  float64x2_t v) {



More information about the cfe-commits mailing list