https://github.com/yairbenavraham updated 
https://github.com/llvm/llvm-project/pull/218307

>From fb3a027ecef08e1740ed35a91d8d1978c1154a74 Mon Sep 17 00:00:00 2001
From: Yair Ben Avraham <[email protected]>
Date: Thu, 20 Aug 2026 07:38:56 +0300
Subject: [PATCH 1/7] [CIR][AArch64] Handle constrained Neon FMA and sqrt

Propagate expression FP options through AArch64 builtin emission and
attach the active constrained FP environment to CIR FMA and sqrt
operations.

Unconstrained FMA/sqrt coverage already lives under CodeGen/AArch64/neon.
Add command-line strict coverage there, plus CIR and CIR-to-LLVM coverage
to the existing test where a pragma overrides a command-line maytrap
setting.

Check that lowering does not fall back to generic CIR calls or
unconstrained LLVM intrinsics.

Assisted-by: Codex
Follow-up to #213800
---
 .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp  | 13 +++++-
 clang/test/CodeGen/AArch64/neon/fullfp16.c    | 10 +++++
 .../AArch64/neon/fused-multiple-fullfp16.c    |  2 +-
 .../CodeGen/AArch64/neon/fused-multiply.c     | 18 ++++++++
 clang/test/CodeGen/AArch64/neon/intrinsics.c  |  6 +++
 .../v8.2a-neon-intrinsics-constrained.c       | 41 +++++++++++++++++++
 6 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 7f504c3f717f2..e71c3e24af2a3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -204,6 +204,16 @@ emitNeonCallToOp(CIRGenModule &cgm, CIRGenBuilderTy 
&builder,
                              builder.getStringAttr(intrinsicName.value()),
                              funcResTy, args)
         .getResult();
+  } else if constexpr (std::is_same_v<Operation, cir::FMAOp>) {
+    assert(args.size() == 3 && "fma expects three operands");
+    return Operation::create(builder, loc, funcResTy, args[0], args[1], 
args[2],
+                             builder.getConstrainedFPAttr())
+        .getResult();
+  } else if constexpr (std::is_same_v<Operation, cir::SqrtOp>) {
+    assert(args.size() == 1 && "sqrt expects one operand");
+    return Operation::create(builder, loc, funcResTy, args[0],
+                             builder.getConstrainedFPAttr())
+        .getResult();
   } else {
     return Operation::create(builder, loc, funcResTy, args).getResult();
   }
@@ -2487,6 +2497,8 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
   // evaluation.
   assert(!cir::MissingFeatures::msvcBuiltins());
 
+  CIRGenFPOptionsRAII fpOptsRAII(*this, expr);
+
   // Some intrinsics are equivalent - if they are use the base intrinsic ID.
   auto it = llvm::find_if(neonEquivalentIntrinsicMap, [builtinID](auto &p) {
     return p.first == builtinID;
@@ -3386,7 +3398,6 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
   }
   case NEON::BI__builtin_neon_vsqrt_v:
   case NEON::BI__builtin_neon_vsqrtq_v:
-    assert(!cir::MissingFeatures::emitConstrainedFPCall());
     return emitNeonCallToOp<cir::SqrtOp>(cgm, builder, {ty}, ops, std::nullopt,
                                          ty, loc);
   case NEON::BI__builtin_neon_vrbit_v:
diff --git a/clang/test/CodeGen/AArch64/neon/fullfp16.c 
b/clang/test/CodeGen/AArch64/neon/fullfp16.c
index c17518eb813de..ffab85ee93fbb 100644
--- a/clang/test/CodeGen/AArch64/neon/fullfp16.c
+++ b/clang/test/CodeGen/AArch64/neon/fullfp16.c
@@ -3,6 +3,8 @@
 // RUN:                   %clang_cc1_cg_arm64_neon -target-feature +fullfp16   
        -emit-llvm  %s -disable-O0-optnone | opt -S -passes=mem2reg             
| FileCheck %s --check-prefixes=ALL,LLVM
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 
-fclangir -emit-llvm  %s -disable-O0-optnone | opt -S 
-passes=mem2reg,simplifycfg | FileCheck %s --check-prefixes=ALL,LLVM %}
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 
-fclangir -emit-cir   %s -disable-O0-optnone |                                  
    FileCheck %s --check-prefixes=ALL,CIR %}
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,simplifycfg | 
FileCheck %s --check-prefix=LLVM-STRICT --implicit-check-not=' @llvm.fma.' 
--implicit-check-not=' @llvm.sqrt.' %}
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-cir  %s -disable-O0-optnone |                                      
FileCheck %s --check-prefix=CIR-STRICT 
--implicit-check-not='cir.call_llvm_intrinsic "fma"' 
--implicit-check-not='cir.call_llvm_intrinsic "sqrt"' %}
 
 //=============================================================================
 // NOTES
@@ -309,6 +311,10 @@ float16_t test_vrndxh_f16(float16_t a) {
 //===------------------------------------------------------===//
 // 2.5.1.4.  Square root
 //===------------------------------------------------------===//
+// LLVM-STRICT-LABEL: @test_vsqrth_f16(
+// LLVM-STRICT: call half @llvm.experimental.constrained.sqrt.f16({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
+// CIR-STRICT-LABEL: cir.func {{.*}}@test_vsqrth_f16(
+// CIR-STRICT: cir.sqrt %{{.*}} : !cir.f16 {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
 // ALL-LABEL: test_vsqrth_f16
 float16_t test_vsqrth_f16(float16_t a) {
 // CIR:  cir.sqrt
@@ -335,6 +341,10 @@ float16_t test_vnegh_f16(float16_t a) {
 //===------------------------------------------------------===//
 // 2.5.1.9.3 Fused multiply-accumulate
 //===------------------------------------------------------===//
+// LLVM-STRICT-LABEL: @test_vfmah_f16(
+// LLVM-STRICT: call half @llvm.experimental.constrained.fma.f16({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
+// CIR-STRICT-LABEL: cir.func {{.*}}@test_vfmah_f16(
+// CIR-STRICT: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.f16 {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
 // ALL-LABEL: test_vfmah_f16
 float16_t test_vfmah_f16(float16_t a, float16_t b, float16_t c) {
 // CIR: cir.fma {{.*}} : !cir.f16
diff --git a/clang/test/CodeGen/AArch64/neon/fused-multiple-fullfp16.c 
b/clang/test/CodeGen/AArch64/neon/fused-multiple-fullfp16.c
index 7231a1108a94f..30188ad3517b9 100644
--- a/clang/test/CodeGen/AArch64/neon/fused-multiple-fullfp16.c
+++ b/clang/test/CodeGen/AArch64/neon/fused-multiple-fullfp16.c
@@ -2,7 +2,7 @@
 
 // RUN:                   %clang_cc1_cg_arm64_neon -target-feature +fullfp16   
        -emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa | 
FileCheck %s --check-prefixes=ALL,LLVM
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 
-fclangir -emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa | 
FileCheck %s --check-prefixes=ALL,LLVM %}
-// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 
-fclangir -emit-cir  %s -disable-O0-optnone |                               
FileCheck %s --check-prefixes=ALL,CIR %}
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 
-fclangir -emit-cir  %s -disable-O0-optnone |                               
FileCheck %s --check-prefixes=ALL,CIR 
--implicit-check-not='cir.call_llvm_intrinsic "fma"' %}
 
 // ALL: {{[Mm]}}odule
 
diff --git a/clang/test/CodeGen/AArch64/neon/fused-multiply.c 
b/clang/test/CodeGen/AArch64/neon/fused-multiply.c
index 5d501d3f61734..bd1d842d7868a 100644
--- a/clang/test/CodeGen/AArch64/neon/fused-multiply.c
+++ b/clang/test/CodeGen/AArch64/neon/fused-multiply.c
@@ -3,6 +3,8 @@
 // RUN:                   %clang_cc1_cg_arm64_neon           -emit-llvm %s 
-disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefixes=ALL,LLVM
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -fclangir -emit-llvm %s 
-disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefixes=ALL,LLVM %}
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -fclangir -emit-cir  %s 
-disable-O0-optnone |                               FileCheck %s 
--check-prefixes=ALL,CIR %}
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefix=LLVM-STRICT --implicit-check-not=' @llvm.fma.' %}
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-cir  %s -disable-O0-optnone |                               FileCheck %s 
--check-prefix=CIR-STRICT --implicit-check-not='cir.call_llvm_intrinsic "fma"' 
%}
 
 // ALL: {{[Mm]}}odule
 
@@ -50,7 +52,11 @@ float32x2_t test_vfma_f32(float32x2_t a, float32x2_t b, 
float32x2_t c) {
 }
 
 // LLVM-LABEL: @test_vfma_f64(
+// LLVM-STRICT-LABEL: @test_vfma_f64(
+// LLVM-STRICT: call <1 x double> 
@llvm.experimental.constrained.fma.v1f64({{.*}}, metadata !"round.tonearest", 
metadata !"fpexcept.strict")
 // CIR-LABEL: @vfma_f64(
+// CIR-STRICT-LABEL: cir.func {{.*}}@vfma_f64(
+// CIR-STRICT: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<1 x 
!cir.double> {fenv = #cir.fenv<dynamic_rounding_mode = tonearest, except_mode = 
unknown, strict_except = true>}
 float64x1_t test_vfma_f64(float64x1_t a, float64x1_t b, float64x1_t c) {
 // CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<1 x !cir.double>
 
@@ -222,6 +228,10 @@ float32x2_t test_vfma_laneq_f32(float32x2_t a, float32x2_t 
b, float32x4_t v) {
 }
 
 // ALL-LABEL: @test_vfma_laneq_f64(
+// LLVM-STRICT-LABEL: @test_vfma_laneq_f64(
+// LLVM-STRICT: call double @llvm.experimental.constrained.fma.f64({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
+// CIR-STRICT-LABEL: cir.func {{.*}}@test_vfma_laneq_f64(
+// CIR-STRICT: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.double {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
 float64x1_t test_vfma_laneq_f64(float64x1_t a, float64x1_t b,
                                  float64x2_t v) {
 // CIR: [[LANE:%.*]] = cir.vec.extract %{{.*}}[%{{.*}} : !u64i] : 
!cir.vector<2 x !cir.double>
@@ -291,6 +301,10 @@ float32x4_t test_vfmaq_laneq_f32(float32x4_t a, 
float32x4_t b,
 }
 
 // ALL-LABEL: @test_vfmaq_laneq_f64(
+// LLVM-STRICT-LABEL: @test_vfmaq_laneq_f64(
+// LLVM-STRICT: call <2 x double> 
@llvm.experimental.constrained.fma.v2f64({{.*}}, metadata !"round.tonearest", 
metadata !"fpexcept.strict")
+// CIR-STRICT-LABEL: cir.func {{.*}}@test_vfmaq_laneq_f64(
+// CIR-STRICT: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<2 x 
!cir.double> {fenv = #cir.fenv<dynamic_rounding_mode = tonearest, except_mode = 
unknown, strict_except = true>}
 float64x2_t test_vfmaq_laneq_f64(float64x2_t a, float64x2_t b,
                                   float64x2_t v) {
 // CIR: [[LANE:%.*]] = cir.vec.shuffle(%{{.*}}, %{{.*}} : !cir.vector<2 x 
!cir.double>) [#cir.int<1> : !s32i, #cir.int<1> : !s32i] : !cir.vector<2 x 
!cir.double>
@@ -357,6 +371,10 @@ float64x2_t test_vfmaq_laneq_f64_0(float64x2_t a, 
float64x2_t b,
 }
 
 // ALL-LABEL: @test_vfmas_lane_f32(
+// LLVM-STRICT-LABEL: @test_vfmas_lane_f32(
+// LLVM-STRICT: call float @llvm.experimental.constrained.fma.f32({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
+// CIR-STRICT-LABEL: cir.func {{.*}}@test_vfmas_lane_f32(
+// CIR-STRICT: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.float {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
 float32_t test_vfmas_lane_f32(float32_t a, float32_t b, float32x2_t c) {
 // CIR: [[LANE:%.*]] = cir.vec.extract %{{.*}}[%{{.*}} : !u64i] : 
!cir.vector<2 x !cir.float>
 // CIR: cir.fma %{{.*}}, [[LANE]], %{{.*}} : !cir.float
diff --git a/clang/test/CodeGen/AArch64/neon/intrinsics.c 
b/clang/test/CodeGen/AArch64/neon/intrinsics.c
index 1393296648283..862572501eba1 100644
--- a/clang/test/CodeGen/AArch64/neon/intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c
@@ -3,6 +3,8 @@
 // RUN:                   %clang_cc1_cg_arm64_neon           -emit-llvm %s 
-disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefixes=ALL,LLVM
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -fclangir -emit-llvm %s 
-disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefixes=ALL,LLVM %}
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -fclangir -emit-cir  %s 
-disable-O0-optnone |                               FileCheck %s 
--check-prefixes=ALL,CIR %}
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefix=LLVM-STRICT --implicit-check-not=' @llvm.sqrt.' %}
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-cir  %s -disable-O0-optnone |                               FileCheck %s 
--check-prefix=CIR-STRICT --implicit-check-not='cir.call_llvm_intrinsic "sqrt"' 
%}
 
 //=============================================================================
 // NOTES
@@ -1790,7 +1792,11 @@ float64x1_t test_vsqrt_f64(float64x1_t a) {
 }
 
 // LLVM-LABEL: @test_vsqrtq_f64(
+// LLVM-STRICT-LABEL: @test_vsqrtq_f64(
+// LLVM-STRICT: call <2 x double> 
@llvm.experimental.constrained.sqrt.v2f64({{.*}}, metadata !"round.tonearest", 
metadata !"fpexcept.strict")
 // CIR-LABEL: @vsqrtq_f64(
+// CIR-STRICT-LABEL: cir.func {{.*}}@vsqrtq_f64(
+// CIR-STRICT: cir.sqrt %{{.*}} : !cir.vector<2 x !cir.double> {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
 float64x2_t test_vsqrtq_f64(float64x2_t a) {
 // CIR: cir.sqrt %{{.*}} : !cir.vector<2 x !cir.double>
 
diff --git a/clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics-constrained.c 
b/clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics-constrained.c
index dac8b931ff210..fb41b7012cf8f 100644
--- a/clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics-constrained.c
+++ b/clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics-constrained.c
@@ -8,6 +8,15 @@
 // RUN: -flax-vector-conversions=none -disable-O0-optnone -emit-llvm -o - %s \
 // RUN: | opt -S -passes=mem2reg,sroa \
 // RUN: | FileCheck --check-prefix=CONSTRAINED 
--implicit-check-not=fpexcept.maytrap %s
+// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu 
-target-feature +neon -target-feature +fullfp16 -target-feature +v8.2a \
+// RUN: -fexperimental-strict-floating-point -ffp-exception-behavior=maytrap 
-DEXCEPT=1 \
+// RUN: -flax-vector-conversions=none -disable-O0-optnone -fclangir -emit-cir 
-o - %s \
+// RUN: | FileCheck --check-prefix=CIR 
--implicit-check-not='cir.call_llvm_intrinsic "fma"' 
--implicit-check-not='cir.call_llvm_intrinsic "sqrt"' %s %}
+// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu 
-target-feature +neon -target-feature +fullfp16 -target-feature +v8.2a \
+// RUN: -fexperimental-strict-floating-point -ffp-exception-behavior=maytrap 
-DEXCEPT=1 \
+// RUN: -flax-vector-conversions=none -disable-O0-optnone -fclangir -emit-llvm 
-o - %s \
+// RUN: | opt -S -passes=mem2reg,sroa \
+// RUN: | FileCheck --check-prefix=LLVM --implicit-check-not=fpexcept.maytrap 
--implicit-check-not=' @llvm.fma.' --implicit-check-not=' @llvm.sqrt.' %s %}
 
 // REQUIRES: aarch64-registered-target
 
@@ -39,6 +48,10 @@
 // CONSTRAINED-NEXT:    [[VSQRT_I:%.*]] = call <4 x half> 
@llvm.experimental.constrained.sqrt.v4f16(<4 x half> [[TMP2]], metadata 
!"round.tonearest", metadata !"fpexcept.strict") #[[ATTR2:[0-9]+]]
 // CONSTRAINED-NEXT:    ret <4 x half> [[VSQRT_I]]
 //
+// CIR-LABEL: cir.func {{.*}}@vsqrt_f16(
+// CIR: cir.sqrt %{{.*}} : !cir.vector<4 x !cir.f16> {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vsqrt_f16(
+// LLVM: call <4 x half> @llvm.experimental.constrained.sqrt.v4f16({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
 float16x4_t test_vsqrt_f16(float16x4_t a) {
   return vsqrt_f16(a);
 }
@@ -61,6 +74,10 @@ float16x4_t test_vsqrt_f16(float16x4_t a) {
 // CONSTRAINED-NEXT:    [[VSQRT_I:%.*]] = call <8 x half> 
@llvm.experimental.constrained.sqrt.v8f16(<8 x half> [[TMP2]], metadata 
!"round.tonearest", metadata !"fpexcept.strict") #[[ATTR2]]
 // CONSTRAINED-NEXT:    ret <8 x half> [[VSQRT_I]]
 //
+// CIR-LABEL: cir.func {{.*}}@vsqrtq_f16(
+// CIR: cir.sqrt %{{.*}} : !cir.vector<8 x !cir.f16> {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vsqrtq_f16(
+// LLVM: call <8 x half> @llvm.experimental.constrained.sqrt.v8f16({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
 float16x8_t test_vsqrtq_f16(float16x8_t a) {
   return vsqrtq_f16(a);
 }
@@ -95,6 +112,10 @@ float16x8_t test_vsqrtq_f16(float16x8_t a) {
 // CONSTRAINED-NEXT:    [[TMP9:%.*]] = call <4 x half> 
@llvm.experimental.constrained.fma.v4f16(<4 x half> [[TMP7]], <4 x half> 
[[TMP8]], <4 x half> [[TMP6]], metadata !"round.tonearest", metadata 
!"fpexcept.strict") #[[ATTR2]]
 // CONSTRAINED-NEXT:    ret <4 x half> [[TMP9]]
 //
+// CIR-LABEL: cir.func {{.*}}@vfma_f16(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<4 x !cir.f16> {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfma_f16(
+// LLVM: call <4 x half> @llvm.experimental.constrained.fma.v4f16({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
 float16x4_t test_vfma_f16(float16x4_t a, float16x4_t b, float16x4_t c) {
   return vfma_f16(a, b, c);
 }
@@ -129,6 +150,10 @@ float16x4_t test_vfma_f16(float16x4_t a, float16x4_t b, 
float16x4_t c) {
 // CONSTRAINED-NEXT:    [[TMP9:%.*]] = call <8 x half> 
@llvm.experimental.constrained.fma.v8f16(<8 x half> [[TMP7]], <8 x half> 
[[TMP8]], <8 x half> [[TMP6]], metadata !"round.tonearest", metadata 
!"fpexcept.strict") #[[ATTR2]]
 // CONSTRAINED-NEXT:    ret <8 x half> [[TMP9]]
 //
+// CIR-LABEL: cir.func {{.*}}@vfmaq_f16(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<8 x !cir.f16> {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfmaq_f16(
+// LLVM: call <8 x half> @llvm.experimental.constrained.fma.v8f16({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
 float16x8_t test_vfmaq_f16(float16x8_t a, float16x8_t b, float16x8_t c) {
   return vfmaq_f16(a, b, c);
 }
@@ -237,6 +262,10 @@ float16x8_t test_vfmsq_f16(float16x8_t a, float16x8_t b, 
float16x8_t c) {
 // CONSTRAINED-NEXT:    [[FMLA2:%.*]] = call <4 x half> 
@llvm.experimental.constrained.fma.v4f16(<4 x half> [[FMLA]], <4 x half> 
[[LANE]], <4 x half> [[FMLA1]], metadata !"round.tonearest", metadata 
!"fpexcept.strict") #[[ATTR2]]
 // CONSTRAINED-NEXT:    ret <4 x half> [[FMLA2]]
 //
+// CIR-LABEL: cir.func {{.*}}@test_vfma_lane_f16(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<4 x !cir.f16> {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfma_lane_f16(
+// LLVM: call <4 x half> @llvm.experimental.constrained.fma.v4f16({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
 float16x4_t test_vfma_lane_f16(float16x4_t a, float16x4_t b, float16x4_t c) {
   return vfma_lane_f16(a, b, c, 3);
 }
@@ -309,6 +338,10 @@ float16x8_t test_vfmaq_lane_f16(float16x8_t a, float16x8_t 
b, float16x4_t c) {
 // CONSTRAINED-NEXT:    [[TMP9:%.*]] = call <4 x half> 
@llvm.experimental.constrained.fma.v4f16(<4 x half> [[LANE]], <4 x half> 
[[TMP7]], <4 x half> [[TMP6]], metadata !"round.tonearest", metadata 
!"fpexcept.strict") #[[ATTR2]]
 // CONSTRAINED-NEXT:    ret <4 x half> [[TMP9]]
 //
+// CIR-LABEL: cir.func {{.*}}@test_vfma_laneq_f16(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<4 x !cir.f16> {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfma_laneq_f16(
+// LLVM: call <4 x half> @llvm.experimental.constrained.fma.v4f16({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
 float16x4_t test_vfma_laneq_f16(float16x4_t a, float16x4_t b, float16x8_t c) {
   return vfma_laneq_f16(a, b, c, 7);
 }
@@ -345,6 +378,10 @@ float16x4_t test_vfma_laneq_f16(float16x4_t a, float16x4_t 
b, float16x8_t c) {
 // CONSTRAINED-NEXT:    [[TMP9:%.*]] = call <8 x half> 
@llvm.experimental.constrained.fma.v8f16(<8 x half> [[LANE]], <8 x half> 
[[TMP7]], <8 x half> [[TMP6]], metadata !"round.tonearest", metadata 
!"fpexcept.strict") #[[ATTR2]]
 // CONSTRAINED-NEXT:    ret <8 x half> [[TMP9]]
 //
+// CIR-LABEL: cir.func {{.*}}@test_vfmaq_laneq_f16(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<8 x !cir.f16> {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfmaq_laneq_f16(
+// LLVM: call <8 x half> @llvm.experimental.constrained.fma.v8f16({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
 float16x8_t test_vfmaq_laneq_f16(float16x8_t a, float16x8_t b, float16x8_t c) {
   return vfmaq_laneq_f16(a, b, c, 7);
 }
@@ -455,6 +492,10 @@ float16x8_t test_vfmaq_n_f16(float16x8_t a, float16x8_t b, 
float16_t c) {
 // CONSTRAINED-NEXT:    [[TMP0:%.*]] = call half 
@llvm.experimental.constrained.fma.f16(half [[B]], half [[EXTRACT]], half 
[[A]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR2]]
 // CONSTRAINED-NEXT:    ret half [[TMP0]]
 //
+// CIR-LABEL: cir.func {{.*}}@test_vfmah_lane_f16(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.f16 {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfmah_lane_f16(
+// LLVM: call half @llvm.experimental.constrained.fma.f16({{.*}}, metadata 
!"round.tonearest", metadata !"fpexcept.strict")
 float16_t test_vfmah_lane_f16(float16_t a, float16_t b, float16x4_t c) {
   return vfmah_lane_f16(a, b, c, 3);
 }

>From 2b220b7c2d1cce3cbdda8820f9ceb2acd50065ad Mon Sep 17 00:00:00 2001
From: Yair Ben Avraham <[email protected]>
Date: Wed, 26 Aug 2026 10:40:03 +0300
Subject: [PATCH 2/7] [CIR][AArch64] Avoid else after return

---
 clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index e71c3e24af2a3..63013e0163f0f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -204,19 +204,23 @@ emitNeonCallToOp(CIRGenModule &cgm, CIRGenBuilderTy 
&builder,
                              builder.getStringAttr(intrinsicName.value()),
                              funcResTy, args)
         .getResult();
-  } else if constexpr (std::is_same_v<Operation, cir::FMAOp>) {
+  }
+  if constexpr (std::is_same_v<Operation, cir::FMAOp>) {
     assert(args.size() == 3 && "fma expects three operands");
     return Operation::create(builder, loc, funcResTy, args[0], args[1], 
args[2],
                              builder.getConstrainedFPAttr())
         .getResult();
-  } else if constexpr (std::is_same_v<Operation, cir::SqrtOp>) {
+  }
+  if constexpr (std::is_same_v<Operation, cir::SqrtOp>) {
     assert(args.size() == 1 && "sqrt expects one operand");
     return Operation::create(builder, loc, funcResTy, args[0],
                              builder.getConstrainedFPAttr())
         .getResult();
-  } else {
-    return Operation::create(builder, loc, funcResTy, args).getResult();
   }
+  if constexpr (!std::is_same_v<Operation, cir::LLVMIntrinsicCallOp> &&
+                !std::is_same_v<Operation, cir::FMAOp> &&
+                !std::is_same_v<Operation, cir::SqrtOp>)
+    return Operation::create(builder, loc, funcResTy, args).getResult();
 }
 
 // TODO(cir): Remove `cgm` from the list of arguments once all NYI(s) are gone.

>From 2e3b3dc80d1e175cf0d292acaef62765569d5b54 Mon Sep 17 00:00:00 2001
From: Yair Ben Avraham <[email protected]>
Date: Wed, 26 Aug 2026 10:47:40 +0300
Subject: [PATCH 3/7] [CIR][AArch64] Move vfmas_lane_f32 constrained coverage

Reuse the existing scalar indexed constrained test for CIR coverage.
---
 .../AArch64/neon-scalar-x-indexed-elem-constrained.c | 12 ++++++++++++
 clang/test/CodeGen/AArch64/neon/fused-multiply.c     |  4 ----
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git 
a/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c 
b/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c
index 944929ccb5f42..e4e16e4f9876c 100644
--- a/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c
+++ b/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c
@@ -6,6 +6,14 @@
 // RUN: -ffp-exception-behavior=strict \
 // RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -passes=mem2reg,sroa \
 // RUN: | FileCheck --check-prefix=CONSTRAINED %s
+// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu 
-target-feature +neon -target-cpu cyclone \
+// RUN: -fexperimental-strict-floating-point -ffp-exception-behavior=strict \
+// RUN: -disable-O0-optnone -fclangir -emit-llvm -o - %s | opt -S 
-passes=mem2reg,sroa \
+// RUN: | FileCheck --check-prefix=LLVM --implicit-check-not=' @llvm.fma.' %s 
%}
+// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu 
-target-feature +neon -target-cpu cyclone \
+// RUN: -fexperimental-strict-floating-point -ffp-exception-behavior=strict \
+// RUN: -disable-O0-optnone -fclangir -emit-cir -o - %s \
+// RUN: | FileCheck --check-prefix=CIR 
--implicit-check-not='cir.call_llvm_intrinsic "fma"' %s %}
 
 // REQUIRES: aarch64-registered-target
 
@@ -27,6 +35,10 @@
 // CONSTRAINED-NEXT:    [[TMP0:%.*]] = call float 
@llvm.experimental.constrained.fma.f32(float [[B]], float [[EXTRACT]], float 
[[A]], metadata !"round.tonearest", metadata !"fpexcept.strict") 
#[[ATTR2:[0-9]+]]
 // CONSTRAINED-NEXT:    ret float [[TMP0]]
 //
+// CIR-LABEL: cir.func {{.*}}@test_vfmas_lane_f32(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.float {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfmas_lane_f32(
+// LLVM: call float @llvm.experimental.constrained.fma.f32({{.*}}, metadata 
!"round.tonearest", metadata !"fpexcept.strict")
 float32_t test_vfmas_lane_f32(float32_t a, float32_t b, float32x2_t c) {
   return vfmas_lane_f32(a, b, c, 1);
 }
diff --git a/clang/test/CodeGen/AArch64/neon/fused-multiply.c 
b/clang/test/CodeGen/AArch64/neon/fused-multiply.c
index bd1d842d7868a..e5320d7172353 100644
--- a/clang/test/CodeGen/AArch64/neon/fused-multiply.c
+++ b/clang/test/CodeGen/AArch64/neon/fused-multiply.c
@@ -371,10 +371,6 @@ float64x2_t test_vfmaq_laneq_f64_0(float64x2_t a, 
float64x2_t b,
 }
 
 // ALL-LABEL: @test_vfmas_lane_f32(
-// LLVM-STRICT-LABEL: @test_vfmas_lane_f32(
-// LLVM-STRICT: call float @llvm.experimental.constrained.fma.f32({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
-// CIR-STRICT-LABEL: cir.func {{.*}}@test_vfmas_lane_f32(
-// CIR-STRICT: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.float {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
 float32_t test_vfmas_lane_f32(float32_t a, float32_t b, float32x2_t c) {
 // CIR: [[LANE:%.*]] = cir.vec.extract %{{.*}}[%{{.*}} : !u64i] : 
!cir.vector<2 x !cir.float>
 // CIR: cir.fma %{{.*}}, [[LANE]], %{{.*}} : !cir.float

>From fece847dd13c3396c92953fcfd619484f20e6e5e Mon Sep 17 00:00:00 2001
From: Yair Ben Avraham <[email protected]>
Date: Fri, 28 Aug 2026 13:20:46 +0300
Subject: [PATCH 4/7] [CIR][AArch64] Move laneq FMA constrained coverage

Reuse the existing scalar indexed constrained test for the remaining
f64 laneq FMA coverage.
---
 .../neon-scalar-x-indexed-elem-constrained.c  | 46 ++++++++++++++++++-
 .../CodeGen/AArch64/neon/fused-multiply.c     |  8 ----
 2 files changed, 45 insertions(+), 9 deletions(-)

diff --git 
a/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c 
b/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c
index e4e16e4f9876c..c8aab578b110a 100644
--- a/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c
+++ b/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c
@@ -223,10 +223,55 @@ float64x1_t test_vfms_lane_f64(float64x1_t a, float64x1_t 
b, float64x1_t v) {
 // CONSTRAINED-NEXT:    [[TMP10:%.*]] = bitcast double [[TMP9]] to <1 x double>
 // CONSTRAINED-NEXT:    ret <1 x double> [[TMP10]]
 //
+// CIR-LABEL: cir.func {{.*}}@test_vfma_laneq_f64(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.double {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfma_laneq_f64(
+// LLVM: call double @llvm.experimental.constrained.fma.f64({{.*}}, metadata 
!"round.tonearest", metadata !"fpexcept.strict")
 float64x1_t test_vfma_laneq_f64(float64x1_t a, float64x1_t b, float64x2_t v) {
   return vfma_laneq_f64(a, b, v, 0);
 }
 
+// UNCONSTRAINED-LABEL: define dso_local <2 x double> @test_vfmaq_laneq_f64(
+// UNCONSTRAINED-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef 
[[B:%.*]], <2 x double> noundef [[V:%.*]]) #[[ATTR0]] {
+// UNCONSTRAINED-NEXT:  [[ENTRY:.*:]]
+// UNCONSTRAINED-NEXT:    [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x 
i64>
+// UNCONSTRAINED-NEXT:    [[TMP1:%.*]] = bitcast <2 x double> [[B]] to <2 x 
i64>
+// UNCONSTRAINED-NEXT:    [[TMP2:%.*]] = bitcast <2 x double> [[V]] 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:    [[LANE:%.*]] = shufflevector <2 x double> [[TMP8]], 
<2 x double> [[TMP8]], <2 x i32> <i32 1, i32 1>
+// UNCONSTRAINED-NEXT:    [[TMP9:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 
x double> [[LANE]], <2 x double> [[TMP7]], <2 x double> [[TMP6]])
+// UNCONSTRAINED-NEXT:    ret <2 x double> [[TMP9]]
+//
+// CONSTRAINED-LABEL: define dso_local <2 x double> @test_vfmaq_laneq_f64(
+// CONSTRAINED-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef 
[[B:%.*]], <2 x double> noundef [[V:%.*]]) #[[ATTR0]] {
+// CONSTRAINED-NEXT:  [[ENTRY:.*:]]
+// CONSTRAINED-NEXT:    [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x i64>
+// CONSTRAINED-NEXT:    [[TMP1:%.*]] = bitcast <2 x double> [[B]] to <2 x i64>
+// CONSTRAINED-NEXT:    [[TMP2:%.*]] = bitcast <2 x double> [[V]] 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:    [[LANE:%.*]] = shufflevector <2 x double> [[TMP8]], <2 
x double> [[TMP8]], <2 x i32> <i32 1, i32 1>
+// CONSTRAINED-NEXT:    [[TMP9:%.*]] = call <2 x double> 
@llvm.experimental.constrained.fma.v2f64(<2 x double> [[LANE]], <2 x double> 
[[TMP7]], <2 x double> [[TMP6]], metadata !"round.tonearest", metadata 
!"fpexcept.strict") #[[ATTR2]]
+// CONSTRAINED-NEXT:    ret <2 x double> [[TMP9]]
+//
+// CIR-LABEL: cir.func {{.*}}@test_vfmaq_laneq_f64(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.double> {fenv 
= #cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfmaq_laneq_f64(
+// LLVM: call <2 x double> @llvm.experimental.constrained.fma.v2f64({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
+float64x2_t test_vfmaq_laneq_f64(float64x2_t a, float64x2_t b,
+                                 float64x2_t v) {
+  return vfmaq_laneq_f64(a, b, v, 1);
+}
+
 // UNCONSTRAINED-LABEL: define dso_local <1 x double> @test_vfms_laneq_f64(
 // UNCONSTRAINED-SAME: <1 x double> noundef [[A:%.*]], <1 x double> noundef 
[[B:%.*]], <2 x double> noundef [[V:%.*]]) #[[ATTR0]] {
 // UNCONSTRAINED-NEXT:  [[ENTRY:.*:]]
@@ -270,4 +315,3 @@ float64x1_t test_vfma_laneq_f64(float64x1_t a, float64x1_t 
b, float64x2_t v) {
 float64x1_t test_vfms_laneq_f64(float64x1_t a, float64x1_t b, float64x2_t v) {
   return vfms_laneq_f64(a, b, v, 0);
 }
-
diff --git a/clang/test/CodeGen/AArch64/neon/fused-multiply.c 
b/clang/test/CodeGen/AArch64/neon/fused-multiply.c
index e5320d7172353..4873abfd96eab 100644
--- a/clang/test/CodeGen/AArch64/neon/fused-multiply.c
+++ b/clang/test/CodeGen/AArch64/neon/fused-multiply.c
@@ -228,10 +228,6 @@ float32x2_t test_vfma_laneq_f32(float32x2_t a, float32x2_t 
b, float32x4_t v) {
 }
 
 // ALL-LABEL: @test_vfma_laneq_f64(
-// LLVM-STRICT-LABEL: @test_vfma_laneq_f64(
-// LLVM-STRICT: call double @llvm.experimental.constrained.fma.f64({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
-// CIR-STRICT-LABEL: cir.func {{.*}}@test_vfma_laneq_f64(
-// CIR-STRICT: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.double {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
 float64x1_t test_vfma_laneq_f64(float64x1_t a, float64x1_t b,
                                  float64x2_t v) {
 // CIR: [[LANE:%.*]] = cir.vec.extract %{{.*}}[%{{.*}} : !u64i] : 
!cir.vector<2 x !cir.double>
@@ -301,10 +297,6 @@ float32x4_t test_vfmaq_laneq_f32(float32x4_t a, 
float32x4_t b,
 }
 
 // ALL-LABEL: @test_vfmaq_laneq_f64(
-// LLVM-STRICT-LABEL: @test_vfmaq_laneq_f64(
-// LLVM-STRICT: call <2 x double> 
@llvm.experimental.constrained.fma.v2f64({{.*}}, metadata !"round.tonearest", 
metadata !"fpexcept.strict")
-// CIR-STRICT-LABEL: cir.func {{.*}}@test_vfmaq_laneq_f64(
-// CIR-STRICT: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<2 x 
!cir.double> {fenv = #cir.fenv<dynamic_rounding_mode = tonearest, except_mode = 
unknown, strict_except = true>}
 float64x2_t test_vfmaq_laneq_f64(float64x2_t a, float64x2_t b,
                                   float64x2_t v) {
 // CIR: [[LANE:%.*]] = cir.vec.shuffle(%{{.*}}, %{{.*}} : !cir.vector<2 x 
!cir.double>) [#cir.int<1> : !s32i, #cir.int<1> : !s32i] : !cir.vector<2 x 
!cir.double>

>From 771593b25077966836baea86ddc794f6fc351e1c Mon Sep 17 00:00:00 2001
From: Yair Ben Avraham <[email protected]>
Date: Fri, 28 Aug 2026 13:33:51 +0300
Subject: [PATCH 5/7] [CIR][AArch64] Move scalar FP16 constrained coverage

Reuse the existing v8.2a Neon constrained test for strict scalar FP16
FMA and square-root coverage.
---
 clang/test/CodeGen/AArch64/neon/fullfp16.c    | 10 ----
 .../v8.2a-neon-intrinsics-constrained.c       | 50 +++++++++++++++++++
 2 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/clang/test/CodeGen/AArch64/neon/fullfp16.c 
b/clang/test/CodeGen/AArch64/neon/fullfp16.c
index ffab85ee93fbb..c17518eb813de 100644
--- a/clang/test/CodeGen/AArch64/neon/fullfp16.c
+++ b/clang/test/CodeGen/AArch64/neon/fullfp16.c
@@ -3,8 +3,6 @@
 // RUN:                   %clang_cc1_cg_arm64_neon -target-feature +fullfp16   
        -emit-llvm  %s -disable-O0-optnone | opt -S -passes=mem2reg             
| FileCheck %s --check-prefixes=ALL,LLVM
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 
-fclangir -emit-llvm  %s -disable-O0-optnone | opt -S 
-passes=mem2reg,simplifycfg | FileCheck %s --check-prefixes=ALL,LLVM %}
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 
-fclangir -emit-cir   %s -disable-O0-optnone |                                  
    FileCheck %s --check-prefixes=ALL,CIR %}
-// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,simplifycfg | 
FileCheck %s --check-prefix=LLVM-STRICT --implicit-check-not=' @llvm.fma.' 
--implicit-check-not=' @llvm.sqrt.' %}
-// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-cir  %s -disable-O0-optnone |                                      
FileCheck %s --check-prefix=CIR-STRICT 
--implicit-check-not='cir.call_llvm_intrinsic "fma"' 
--implicit-check-not='cir.call_llvm_intrinsic "sqrt"' %}
 
 //=============================================================================
 // NOTES
@@ -311,10 +309,6 @@ float16_t test_vrndxh_f16(float16_t a) {
 //===------------------------------------------------------===//
 // 2.5.1.4.  Square root
 //===------------------------------------------------------===//
-// LLVM-STRICT-LABEL: @test_vsqrth_f16(
-// LLVM-STRICT: call half @llvm.experimental.constrained.sqrt.f16({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
-// CIR-STRICT-LABEL: cir.func {{.*}}@test_vsqrth_f16(
-// CIR-STRICT: cir.sqrt %{{.*}} : !cir.f16 {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
 // ALL-LABEL: test_vsqrth_f16
 float16_t test_vsqrth_f16(float16_t a) {
 // CIR:  cir.sqrt
@@ -341,10 +335,6 @@ float16_t test_vnegh_f16(float16_t a) {
 //===------------------------------------------------------===//
 // 2.5.1.9.3 Fused multiply-accumulate
 //===------------------------------------------------------===//
-// LLVM-STRICT-LABEL: @test_vfmah_f16(
-// LLVM-STRICT: call half @llvm.experimental.constrained.fma.f16({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
-// CIR-STRICT-LABEL: cir.func {{.*}}@test_vfmah_f16(
-// CIR-STRICT: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.f16 {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
 // ALL-LABEL: test_vfmah_f16
 float16_t test_vfmah_f16(float16_t a, float16_t b, float16_t c) {
 // CIR: cir.fma {{.*}} : !cir.f16
diff --git a/clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics-constrained.c 
b/clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics-constrained.c
index fb41b7012cf8f..e9aece9dfa75f 100644
--- a/clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics-constrained.c
+++ b/clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics-constrained.c
@@ -17,6 +17,15 @@
 // RUN: -flax-vector-conversions=none -disable-O0-optnone -fclangir -emit-llvm 
-o - %s \
 // RUN: | opt -S -passes=mem2reg,sroa \
 // RUN: | FileCheck --check-prefix=LLVM --implicit-check-not=fpexcept.maytrap 
--implicit-check-not=' @llvm.fma.' --implicit-check-not=' @llvm.sqrt.' %s %}
+// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu 
-target-feature +neon -target-feature +fullfp16 -target-feature +v8.2a \
+// RUN: -fexperimental-strict-floating-point -ffp-exception-behavior=strict \
+// RUN: -flax-vector-conversions=none -disable-O0-optnone -fclangir -emit-cir 
-o - %s \
+// RUN: | FileCheck --check-prefix=CIR 
--implicit-check-not='cir.call_llvm_intrinsic "fma"' 
--implicit-check-not='cir.call_llvm_intrinsic "sqrt"' %s %}
+// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu 
-target-feature +neon -target-feature +fullfp16 -target-feature +v8.2a \
+// RUN: -fexperimental-strict-floating-point -ffp-exception-behavior=strict \
+// RUN: -flax-vector-conversions=none -disable-O0-optnone -fclangir -emit-llvm 
-o - %s \
+// RUN: | opt -S -passes=mem2reg,sroa \
+// RUN: | FileCheck --check-prefix=LLVM --implicit-check-not=' @llvm.fma.' 
--implicit-check-not=' @llvm.sqrt.' %s %}
 
 // REQUIRES: aarch64-registered-target
 
@@ -28,8 +37,29 @@
 #pragma float_control(except, on)
 #endif
 
+#include <arm_fp16.h>
 #include <arm_neon.h>
 
+// UNCONSTRAINED-LABEL: define dso_local half @test_vsqrth_f16(
+// UNCONSTRAINED-SAME: half noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+// UNCONSTRAINED-NEXT:  [[ENTRY:.*:]]
+// UNCONSTRAINED-NEXT:    [[SQR:%.*]] = call half @llvm.sqrt.f16(half [[A]])
+// UNCONSTRAINED-NEXT:    ret half [[SQR]]
+//
+// CONSTRAINED-LABEL: define dso_local half @test_vsqrth_f16(
+// CONSTRAINED-SAME: half noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+// CONSTRAINED-NEXT:  [[ENTRY:.*:]]
+// CONSTRAINED-NEXT:    [[SQR:%.*]] = call half 
@llvm.experimental.constrained.sqrt.f16(half [[A]], metadata 
!"round.tonearest", metadata !"fpexcept.strict") #[[ATTR2:[0-9]+]]
+// CONSTRAINED-NEXT:    ret half [[SQR]]
+//
+// CIR-LABEL: cir.func {{.*}}@test_vsqrth_f16(
+// CIR: cir.sqrt %{{.*}} : !cir.f16 {fenv = #cir.fenv<dynamic_rounding_mode = 
tonearest, except_mode = unknown, strict_except = true>}
+// LLVM-LABEL: @test_vsqrth_f16(
+// LLVM: call half @llvm.experimental.constrained.sqrt.f16({{.*}}, metadata 
!"round.tonearest", metadata !"fpexcept.strict")
+float16_t test_vsqrth_f16(float16_t a) {
+  return vsqrth_f16(a);
+}
+
 // UNCONSTRAINED-LABEL: define dso_local <4 x half> @test_vsqrt_f16(
 // UNCONSTRAINED-SAME: <4 x half> noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] {
 // UNCONSTRAINED-NEXT:  [[ENTRY:.*:]]
@@ -158,6 +188,26 @@ float16x8_t test_vfmaq_f16(float16x8_t a, float16x8_t b, 
float16x8_t c) {
   return vfmaq_f16(a, b, c);
 }
 
+// UNCONSTRAINED-LABEL: define dso_local half @test_vfmah_f16(
+// UNCONSTRAINED-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]], half 
noundef [[C:%.*]]) #[[ATTR0]] {
+// UNCONSTRAINED-NEXT:  [[ENTRY:.*:]]
+// UNCONSTRAINED-NEXT:    [[FMA:%.*]] = call half @llvm.fma.f16(half [[B]], 
half [[C]], half [[A]])
+// UNCONSTRAINED-NEXT:    ret half [[FMA]]
+//
+// CONSTRAINED-LABEL: define dso_local half @test_vfmah_f16(
+// CONSTRAINED-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]], half 
noundef [[C:%.*]]) #[[ATTR0]] {
+// CONSTRAINED-NEXT:  [[ENTRY:.*:]]
+// CONSTRAINED-NEXT:    [[FMA:%.*]] = call half 
@llvm.experimental.constrained.fma.f16(half [[B]], half [[C]], half [[A]], 
metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR2]]
+// CONSTRAINED-NEXT:    ret half [[FMA]]
+//
+// CIR-LABEL: cir.func {{.*}}@test_vfmah_f16(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.f16 {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfmah_f16(
+// LLVM: call half @llvm.experimental.constrained.fma.f16({{.*}}, metadata 
!"round.tonearest", metadata !"fpexcept.strict")
+float16_t test_vfmah_f16(float16_t a, float16_t b, float16_t c) {
+  return vfmah_f16(a, b, c);
+}
+
 // UNCONSTRAINED-LABEL: define dso_local <4 x half> @test_vfms_f16(
 // UNCONSTRAINED-SAME: <4 x half> noundef [[A:%.*]], <4 x half> noundef 
[[B:%.*]], <4 x half> noundef [[C:%.*]]) #[[ATTR0]] {
 // UNCONSTRAINED-NEXT:  [[ENTRY:.*:]]

>From 8cbe19fc19d2490e2c362f568e695cbfeacc8590 Mon Sep 17 00:00:00 2001
From: Yair Ben Avraham <[email protected]>
Date: Fri, 28 Aug 2026 13:48:02 +0300
Subject: [PATCH 6/7] [CIR][AArch64] Move FMA and sqrt constrained coverage

Move strict vfma_f64 and vsqrtq_f64 CIR coverage out of the ordinary
Neon tests and into a focused constrained test.

The existing legacy constrained files cannot run through CIR as a whole
because they contain unrelated AArch64 builtins that CIR does not yet lower.
---
 .../AArch64/neon/fma-sqrt-constrained.c       | 22 +++++++++++++++++++
 .../CodeGen/AArch64/neon/fused-multiply.c     |  6 -----
 clang/test/CodeGen/AArch64/neon/intrinsics.c  |  6 -----
 3 files changed, 22 insertions(+), 12 deletions(-)
 create mode 100644 clang/test/CodeGen/AArch64/neon/fma-sqrt-constrained.c

diff --git a/clang/test/CodeGen/AArch64/neon/fma-sqrt-constrained.c 
b/clang/test/CodeGen/AArch64/neon/fma-sqrt-constrained.c
new file mode 100644
index 0000000000000..8665bc39226d7
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/neon/fma-sqrt-constrained.c
@@ -0,0 +1,22 @@
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefix=LLVM --implicit-check-not=' @llvm.fma.' --implicit-check-not=' 
@llvm.sqrt.' %}
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-cir  %s -disable-O0-optnone |                               FileCheck %s 
--check-prefix=CIR --implicit-check-not='cir.call_llvm_intrinsic "fma"' 
--implicit-check-not='cir.call_llvm_intrinsic "sqrt"' %}
+
+// REQUIRES: aarch64-registered-target
+
+#include <arm_neon.h>
+
+// LLVM-LABEL: @test_vfma_f64(
+// LLVM: call <1 x double> @llvm.experimental.constrained.fma.v1f64({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
+// CIR-LABEL: cir.func {{.*}}@test_vfma_f64(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<1 x !cir.double> {fenv 
= #cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+float64x1_t test_vfma_f64(float64x1_t a, float64x1_t b, float64x1_t c) {
+  return vfma_f64(a, b, c);
+}
+
+// LLVM-LABEL: @test_vsqrtq_f64(
+// LLVM: call <2 x double> @llvm.experimental.constrained.sqrt.v2f64({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
+// CIR-LABEL: cir.func {{.*}}@test_vsqrtq_f64(
+// CIR: cir.sqrt %{{.*}} : !cir.vector<2 x !cir.double> {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+float64x2_t test_vsqrtq_f64(float64x2_t a) {
+  return vsqrtq_f64(a);
+}
diff --git a/clang/test/CodeGen/AArch64/neon/fused-multiply.c 
b/clang/test/CodeGen/AArch64/neon/fused-multiply.c
index 4873abfd96eab..5d501d3f61734 100644
--- a/clang/test/CodeGen/AArch64/neon/fused-multiply.c
+++ b/clang/test/CodeGen/AArch64/neon/fused-multiply.c
@@ -3,8 +3,6 @@
 // RUN:                   %clang_cc1_cg_arm64_neon           -emit-llvm %s 
-disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefixes=ALL,LLVM
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -fclangir -emit-llvm %s 
-disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefixes=ALL,LLVM %}
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -fclangir -emit-cir  %s 
-disable-O0-optnone |                               FileCheck %s 
--check-prefixes=ALL,CIR %}
-// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefix=LLVM-STRICT --implicit-check-not=' @llvm.fma.' %}
-// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-cir  %s -disable-O0-optnone |                               FileCheck %s 
--check-prefix=CIR-STRICT --implicit-check-not='cir.call_llvm_intrinsic "fma"' 
%}
 
 // ALL: {{[Mm]}}odule
 
@@ -52,11 +50,7 @@ float32x2_t test_vfma_f32(float32x2_t a, float32x2_t b, 
float32x2_t c) {
 }
 
 // LLVM-LABEL: @test_vfma_f64(
-// LLVM-STRICT-LABEL: @test_vfma_f64(
-// LLVM-STRICT: call <1 x double> 
@llvm.experimental.constrained.fma.v1f64({{.*}}, metadata !"round.tonearest", 
metadata !"fpexcept.strict")
 // CIR-LABEL: @vfma_f64(
-// CIR-STRICT-LABEL: cir.func {{.*}}@vfma_f64(
-// CIR-STRICT: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<1 x 
!cir.double> {fenv = #cir.fenv<dynamic_rounding_mode = tonearest, except_mode = 
unknown, strict_except = true>}
 float64x1_t test_vfma_f64(float64x1_t a, float64x1_t b, float64x1_t c) {
 // CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<1 x !cir.double>
 
diff --git a/clang/test/CodeGen/AArch64/neon/intrinsics.c 
b/clang/test/CodeGen/AArch64/neon/intrinsics.c
index 862572501eba1..1393296648283 100644
--- a/clang/test/CodeGen/AArch64/neon/intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c
@@ -3,8 +3,6 @@
 // RUN:                   %clang_cc1_cg_arm64_neon           -emit-llvm %s 
-disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefixes=ALL,LLVM
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -fclangir -emit-llvm %s 
-disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefixes=ALL,LLVM %}
 // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -fclangir -emit-cir  %s 
-disable-O0-optnone |                               FileCheck %s 
--check-prefixes=ALL,CIR %}
-// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefix=LLVM-STRICT --implicit-check-not=' @llvm.sqrt.' %}
-// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-cir  %s -disable-O0-optnone |                               FileCheck %s 
--check-prefix=CIR-STRICT --implicit-check-not='cir.call_llvm_intrinsic "sqrt"' 
%}
 
 //=============================================================================
 // NOTES
@@ -1792,11 +1790,7 @@ float64x1_t test_vsqrt_f64(float64x1_t a) {
 }
 
 // LLVM-LABEL: @test_vsqrtq_f64(
-// LLVM-STRICT-LABEL: @test_vsqrtq_f64(
-// LLVM-STRICT: call <2 x double> 
@llvm.experimental.constrained.sqrt.v2f64({{.*}}, metadata !"round.tonearest", 
metadata !"fpexcept.strict")
 // CIR-LABEL: @vsqrtq_f64(
-// CIR-STRICT-LABEL: cir.func {{.*}}@vsqrtq_f64(
-// CIR-STRICT: cir.sqrt %{{.*}} : !cir.vector<2 x !cir.double> {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
 float64x2_t test_vsqrtq_f64(float64x2_t a) {
 // CIR: cir.sqrt %{{.*}} : !cir.vector<2 x !cir.double>
 

>From b5f0796081b97d4e234124bc799f3732e3742a53 Mon Sep 17 00:00:00 2001
From: Yair Ben Avraham <[email protected]>
Date: Sun, 30 Aug 2026 07:05:55 +0300
Subject: [PATCH 7/7] [CIR][AArch64] Co-locate constrained FMA and sqrt tests

Place constrained FMA and sqrt coverage in files matching their regular
Neon counterparts. Move the new indexed FMA CIR coverage from the legacy
scalar indexed test and preserve the direct vfmaq_laneq_f64 checks.

Assisted-by: Codex
---
 .../neon-scalar-x-indexed-elem-constrained.c  | 57 --------------
 .../AArch64/neon/fused-multiply-constrained.c | 75 +++++++++++++++++++
 ...constrained.c => intrinsics-constrained.c} | 12 +--
 3 files changed, 77 insertions(+), 67 deletions(-)
 create mode 100644 clang/test/CodeGen/AArch64/neon/fused-multiply-constrained.c
 rename clang/test/CodeGen/AArch64/neon/{fma-sqrt-constrained.c => 
intrinsics-constrained.c} (62%)

diff --git 
a/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c 
b/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c
index c8aab578b110a..54930d384e247 100644
--- a/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c
+++ b/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c
@@ -6,14 +6,6 @@
 // RUN: -ffp-exception-behavior=strict \
 // RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -passes=mem2reg,sroa \
 // RUN: | FileCheck --check-prefix=CONSTRAINED %s
-// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu 
-target-feature +neon -target-cpu cyclone \
-// RUN: -fexperimental-strict-floating-point -ffp-exception-behavior=strict \
-// RUN: -disable-O0-optnone -fclangir -emit-llvm -o - %s | opt -S 
-passes=mem2reg,sroa \
-// RUN: | FileCheck --check-prefix=LLVM --implicit-check-not=' @llvm.fma.' %s 
%}
-// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu 
-target-feature +neon -target-cpu cyclone \
-// RUN: -fexperimental-strict-floating-point -ffp-exception-behavior=strict \
-// RUN: -disable-O0-optnone -fclangir -emit-cir -o - %s \
-// RUN: | FileCheck --check-prefix=CIR 
--implicit-check-not='cir.call_llvm_intrinsic "fma"' %s %}
 
 // REQUIRES: aarch64-registered-target
 
@@ -35,10 +27,6 @@
 // CONSTRAINED-NEXT:    [[TMP0:%.*]] = call float 
@llvm.experimental.constrained.fma.f32(float [[B]], float [[EXTRACT]], float 
[[A]], metadata !"round.tonearest", metadata !"fpexcept.strict") 
#[[ATTR2:[0-9]+]]
 // CONSTRAINED-NEXT:    ret float [[TMP0]]
 //
-// CIR-LABEL: cir.func {{.*}}@test_vfmas_lane_f32(
-// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.float {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
-// LLVM-LABEL: @test_vfmas_lane_f32(
-// LLVM: call float @llvm.experimental.constrained.fma.f32({{.*}}, metadata 
!"round.tonearest", metadata !"fpexcept.strict")
 float32_t test_vfmas_lane_f32(float32_t a, float32_t b, float32x2_t c) {
   return vfmas_lane_f32(a, b, c, 1);
 }
@@ -223,55 +211,10 @@ float64x1_t test_vfms_lane_f64(float64x1_t a, float64x1_t 
b, float64x1_t v) {
 // CONSTRAINED-NEXT:    [[TMP10:%.*]] = bitcast double [[TMP9]] to <1 x double>
 // CONSTRAINED-NEXT:    ret <1 x double> [[TMP10]]
 //
-// CIR-LABEL: cir.func {{.*}}@test_vfma_laneq_f64(
-// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.double {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
-// LLVM-LABEL: @test_vfma_laneq_f64(
-// LLVM: call double @llvm.experimental.constrained.fma.f64({{.*}}, metadata 
!"round.tonearest", metadata !"fpexcept.strict")
 float64x1_t test_vfma_laneq_f64(float64x1_t a, float64x1_t b, float64x2_t v) {
   return vfma_laneq_f64(a, b, v, 0);
 }
 
-// UNCONSTRAINED-LABEL: define dso_local <2 x double> @test_vfmaq_laneq_f64(
-// UNCONSTRAINED-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef 
[[B:%.*]], <2 x double> noundef [[V:%.*]]) #[[ATTR0]] {
-// UNCONSTRAINED-NEXT:  [[ENTRY:.*:]]
-// UNCONSTRAINED-NEXT:    [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x 
i64>
-// UNCONSTRAINED-NEXT:    [[TMP1:%.*]] = bitcast <2 x double> [[B]] to <2 x 
i64>
-// UNCONSTRAINED-NEXT:    [[TMP2:%.*]] = bitcast <2 x double> [[V]] 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:    [[LANE:%.*]] = shufflevector <2 x double> [[TMP8]], 
<2 x double> [[TMP8]], <2 x i32> <i32 1, i32 1>
-// UNCONSTRAINED-NEXT:    [[TMP9:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 
x double> [[LANE]], <2 x double> [[TMP7]], <2 x double> [[TMP6]])
-// UNCONSTRAINED-NEXT:    ret <2 x double> [[TMP9]]
-//
-// CONSTRAINED-LABEL: define dso_local <2 x double> @test_vfmaq_laneq_f64(
-// CONSTRAINED-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef 
[[B:%.*]], <2 x double> noundef [[V:%.*]]) #[[ATTR0]] {
-// CONSTRAINED-NEXT:  [[ENTRY:.*:]]
-// CONSTRAINED-NEXT:    [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x i64>
-// CONSTRAINED-NEXT:    [[TMP1:%.*]] = bitcast <2 x double> [[B]] to <2 x i64>
-// CONSTRAINED-NEXT:    [[TMP2:%.*]] = bitcast <2 x double> [[V]] 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:    [[LANE:%.*]] = shufflevector <2 x double> [[TMP8]], <2 
x double> [[TMP8]], <2 x i32> <i32 1, i32 1>
-// CONSTRAINED-NEXT:    [[TMP9:%.*]] = call <2 x double> 
@llvm.experimental.constrained.fma.v2f64(<2 x double> [[LANE]], <2 x double> 
[[TMP7]], <2 x double> [[TMP6]], metadata !"round.tonearest", metadata 
!"fpexcept.strict") #[[ATTR2]]
-// CONSTRAINED-NEXT:    ret <2 x double> [[TMP9]]
-//
-// CIR-LABEL: cir.func {{.*}}@test_vfmaq_laneq_f64(
-// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.double> {fenv 
= #cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
-// LLVM-LABEL: @test_vfmaq_laneq_f64(
-// LLVM: call <2 x double> @llvm.experimental.constrained.fma.v2f64({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
-float64x2_t test_vfmaq_laneq_f64(float64x2_t a, float64x2_t b,
-                                 float64x2_t v) {
-  return vfmaq_laneq_f64(a, b, v, 1);
-}
-
 // UNCONSTRAINED-LABEL: define dso_local <1 x double> @test_vfms_laneq_f64(
 // UNCONSTRAINED-SAME: <1 x double> noundef [[A:%.*]], <1 x double> noundef 
[[B:%.*]], <2 x double> noundef [[V:%.*]]) #[[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
new file mode 100644
index 0000000000000..25bc87b376e42
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/neon/fused-multiply-constrained.c
@@ -0,0 +1,75 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 5
+// RUN: %clang_cc1_cg_arm64_neon -target-cpu cyclone -emit-llvm %s 
-disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefix=UNCONSTRAINED
+// RUN: %clang_cc1_cg_arm64_neon -target-cpu cyclone 
-ffp-exception-behavior=strict -emit-llvm %s -disable-O0-optnone | opt -S 
-passes=mem2reg,sroa | FileCheck %s --check-prefix=CONSTRAINED
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefix=LLVM --implicit-check-not=' @llvm.fma.' %}
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-cir  %s -disable-O0-optnone |                               FileCheck %s 
--check-prefix=CIR --implicit-check-not='cir.call_llvm_intrinsic "fma"' %}
+
+// REQUIRES: aarch64-registered-target
+
+#include <arm_neon.h>
+
+// LLVM-LABEL: @test_vfma_f64(
+// LLVM: call <1 x double> @llvm.experimental.constrained.fma.v1f64({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
+// CIR-LABEL: cir.func {{.*}}@test_vfma_f64(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<1 x !cir.double> {fenv 
= #cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+float64x1_t test_vfma_f64(float64x1_t a, float64x1_t b, float64x1_t c) {
+  return vfma_f64(a, b, c);
+}
+
+// CIR-LABEL: cir.func {{.*}}@test_vfma_laneq_f64(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.double {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfma_laneq_f64(
+// LLVM: call double @llvm.experimental.constrained.fma.f64({{.*}}, metadata 
!"round.tonearest", metadata !"fpexcept.strict")
+float64x1_t test_vfma_laneq_f64(float64x1_t a, float64x1_t b,
+                                float64x2_t v) {
+  return vfma_laneq_f64(a, b, v, 0);
+}
+
+// UNCONSTRAINED-LABEL: define dso_local <2 x double> @test_vfmaq_laneq_f64(
+// UNCONSTRAINED-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef 
[[B:%.*]], <2 x double> noundef [[V:%.*]]) #[[ATTR0:[0-9]+]] {
+// UNCONSTRAINED-NEXT:  [[ENTRY:.*:]]
+// UNCONSTRAINED-NEXT:    [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x 
i64>
+// UNCONSTRAINED-NEXT:    [[TMP1:%.*]] = bitcast <2 x double> [[B]] to <2 x 
i64>
+// UNCONSTRAINED-NEXT:    [[TMP2:%.*]] = bitcast <2 x double> [[V]] 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:    [[LANE:%.*]] = shufflevector <2 x double> [[TMP8]], 
<2 x double> [[TMP8]], <2 x i32> <i32 1, i32 1>
+// UNCONSTRAINED-NEXT:    [[TMP9:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 
x double> [[LANE]], <2 x double> [[TMP7]], <2 x double> [[TMP6]])
+// UNCONSTRAINED-NEXT:    ret <2 x double> [[TMP9]]
+//
+// CONSTRAINED-LABEL: define dso_local <2 x double> @test_vfmaq_laneq_f64(
+// CONSTRAINED-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef 
[[B:%.*]], <2 x double> noundef [[V:%.*]]) #[[ATTR0:[0-9]+]] {
+// CONSTRAINED-NEXT:  [[ENTRY:.*:]]
+// CONSTRAINED-NEXT:    [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x i64>
+// CONSTRAINED-NEXT:    [[TMP1:%.*]] = bitcast <2 x double> [[B]] to <2 x i64>
+// CONSTRAINED-NEXT:    [[TMP2:%.*]] = bitcast <2 x double> [[V]] 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:    [[LANE:%.*]] = shufflevector <2 x double> [[TMP8]], <2 
x double> [[TMP8]], <2 x i32> <i32 1, i32 1>
+// CONSTRAINED-NEXT:    [[TMP9:%.*]] = call <2 x double> 
@llvm.experimental.constrained.fma.v2f64(<2 x double> [[LANE]], <2 x double> 
[[TMP7]], <2 x double> [[TMP6]], metadata !"round.tonearest", metadata 
!"fpexcept.strict") #[[ATTR2:[0-9]+]]
+// CONSTRAINED-NEXT:    ret <2 x double> [[TMP9]]
+//
+// CIR-LABEL: cir.func {{.*}}@test_vfmaq_laneq_f64(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<2 x !cir.double> {fenv 
= #cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfmaq_laneq_f64(
+// LLVM: call <2 x double> @llvm.experimental.constrained.fma.v2f64({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
+float64x2_t test_vfmaq_laneq_f64(float64x2_t a, float64x2_t b,
+                                 float64x2_t v) {
+  return vfmaq_laneq_f64(a, b, v, 1);
+}
+
+// CIR-LABEL: cir.func {{.*}}@test_vfmas_lane_f32(
+// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.float {fenv = 
#cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
+// LLVM-LABEL: @test_vfmas_lane_f32(
+// LLVM: call float @llvm.experimental.constrained.fma.f32({{.*}}, metadata 
!"round.tonearest", metadata !"fpexcept.strict")
+float32_t test_vfmas_lane_f32(float32_t a, float32_t b, float32x2_t c) {
+  return vfmas_lane_f32(a, b, c, 1);
+}
diff --git a/clang/test/CodeGen/AArch64/neon/fma-sqrt-constrained.c 
b/clang/test/CodeGen/AArch64/neon/intrinsics-constrained.c
similarity index 62%
rename from clang/test/CodeGen/AArch64/neon/fma-sqrt-constrained.c
rename to clang/test/CodeGen/AArch64/neon/intrinsics-constrained.c
index 8665bc39226d7..d63f6a3373ebb 100644
--- a/clang/test/CodeGen/AArch64/neon/fma-sqrt-constrained.c
+++ b/clang/test/CodeGen/AArch64/neon/intrinsics-constrained.c
@@ -1,18 +1,10 @@
-// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefix=LLVM --implicit-check-not=' @llvm.fma.' --implicit-check-not=' 
@llvm.sqrt.' %}
-// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-cir  %s -disable-O0-optnone |                               FileCheck %s 
--check-prefix=CIR --implicit-check-not='cir.call_llvm_intrinsic "fma"' 
--implicit-check-not='cir.call_llvm_intrinsic "sqrt"' %}
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s 
--check-prefix=LLVM --implicit-check-not=' @llvm.sqrt.' %}
+// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon 
-fexperimental-strict-floating-point -ffp-exception-behavior=strict -fclangir 
-emit-cir  %s -disable-O0-optnone |                               FileCheck %s 
--check-prefix=CIR --implicit-check-not='cir.call_llvm_intrinsic "sqrt"' %}
 
 // REQUIRES: aarch64-registered-target
 
 #include <arm_neon.h>
 
-// LLVM-LABEL: @test_vfma_f64(
-// LLVM: call <1 x double> @llvm.experimental.constrained.fma.v1f64({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
-// CIR-LABEL: cir.func {{.*}}@test_vfma_f64(
-// CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<1 x !cir.double> {fenv 
= #cir.fenv<dynamic_rounding_mode = tonearest, except_mode = unknown, 
strict_except = true>}
-float64x1_t test_vfma_f64(float64x1_t a, float64x1_t b, float64x1_t c) {
-  return vfma_f64(a, b, c);
-}
-
 // LLVM-LABEL: @test_vsqrtq_f64(
 // LLVM: call <2 x double> @llvm.experimental.constrained.sqrt.v2f64({{.*}}, 
metadata !"round.tonearest", metadata !"fpexcept.strict")
 // CIR-LABEL: cir.func {{.*}}@test_vsqrtq_f64(

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to