https://github.com/yairbenavraham created https://github.com/llvm/llvm-project/pull/218307
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 >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] [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); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
