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/6] [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/6] [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/6] [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/6] [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/6] [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/6] [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>
 

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

Reply via email to