> On 11 Nov 2026, at 19:28, Karl Meakin <[email protected]> wrote:
> 
> Ports the NEON fused-multiple-add (vfma) and fused-multiply-subtract (vfms)
> intrinsics to the pragma-based framework, and adds corresponding
> assembly tests for each.
> 
> Some fnma insns had to have their patterns adjusted to match the RTL
> produced by the FNMA IFN (the negated input should always be the first
> input operand). Also reformat the insns for consistency.
> 
> Also added comments above each fma/fnma insn explaining which intrinsics
> they cover, because there are 3 different insns for each intrinsic and
> it can be non-obvious which intrinsic maps to which insn (especially
> insns that take `float64x1_t` or `float64_t` as arguments).
> 
> The `__builtin_aarch64_fma` and `__builtin_aarch64_fnma` builtin
> functions were deleted because they are no longer used - except for the
> scalar HF variants, which are still used by `arm_f16.h`
> 

Ok.
Thanks,
Kyrill

> gcc/ChangeLog:
> 
> * config/aarch64/aarch64-neon-builtins-base.cc
> (build_ifn_call): New function.
> (gimple_ifn::fold): Call `build_ifn_call`.
> (struct gimple_fused_mla): New struct.
> * config/aarch64/aarch64-neon-builtins-base.def
> (vfma, vfmaq, vfma_n, vfmaq_n, vfma_lane, vfma_laneq,
> vfmaq_lane, vfmaq_laneq, vfmas_lane, vfmas_laneq, vfmad_lane,
> vfmad_laneq, vfms, vfmsq, vfms_n, vfmsq_n, vfms_lane,
> vfms_laneq, vfmsq_lane, vfmsq_laneq, vfmss_lane, vfmss_laneq,
> vfmsd_lane, vfmsd_laneq, and the FP16 forms of each): New
> intrinsic function declarations.
> * config/aarch64/aarch64-simd-builtins.def
> (fma, fnma): Delete `__builtin_aarch64` function declarations.
> * config/aarch64/aarch64-simd.md
> (fma<mode>4<vczle><vczbe>,
> *aarch64_fma4_elt<mode><vczle><vczbe>,
> *aarch64_fma4_elt_<vswap_width_name><mode><vczle><vczbe>,
> *aarch64_fma4_elt_from_dup<mode><vczle><vczbe>,
> *aarch64_fma<mode>4_elt_to_scalar): Extend to cover HF vector
> modes, reformat, add comments.
> (fnma<mode>4<vczle><vczbe>,
> *aarch64_fnma4_elt<mode><vczle><vczbe>
> *aarch64_fnma4_elt_<vswap_width_name><mode><vczle><vczbe>
> *aarch64_fnma4_elt_from_dup<mode><vczle><vczbe>
> *aarch64_fnma<mode>4_elt_from_to_scalar):
> Likewise.
> (*aarch64_fma4_elt_to_64v2df, *aarch64_fnma4_elt_to_64v2df):
> Rename to ...
> (*aarch64_fma<mode>4_elt_to_scalar,
> *aarch64_fnma<mode>4_elt_to_scalar): ...these.
> (*aarch64_fnma4_elt<mode><vczle><vczbe>_alt,
> *aarch64_fnma4_elt_<vswap_width_name><mode><vczle><vczbe>_alt,
> *aarch64_fnma4_elt_from_dup<mode><cvzle><vczbe>_alt,
> *aarch64_fnma4<mode>4_elt_to_scalar_alt): New insns to match
> permuted variants.
> * config/aarch64/arm_neon.h
> (vfma_f64, vfma_f32, vfmaq_f32, vfmaq_f64, vfma_n_f32,
> vfma_n_f64, vfmaq_n_f32, vfmaq_n_f64, vfma_lane_f32,
> vfma_lane_f64, vfma_laneq_f32, vfma_laneq_f64,
> vfmaq_lane_f32, vfmaq_lane_f64, vfmaq_laneq_f32,
> vfmaq_laneq_f64, vfms_f64, vfms_f32, vfmsq_f32, vfmsq_f64,
> vfms_n_f32, vfms_n_f64, vfmsq_n_f32, vfmsq_n_f64,
> vfms_lane_f32, vfms_lane_f64, vfms_laneq_f32, vfms_laneq_f64,
> vfmsq_lane_f32, vfmsq_lane_f64, vfmsq_laneq_f32,
> vfmsq_laneq_f64, vfma_f16, vfmaq_f16, vfms_f16, vfmsq_f16,
> vfma_lane_f16, vfmaq_lane_f16, vfma_laneq_f16,
> vfmaq_laneq_f16, vfma_n_f16, vfmaq_n_f16, vfms_lane_f16,
> vfmsq_lane_f16, vfms_laneq_f16, vfmsq_laneq_f16, vfms_n_f16,
> vfmsq_n_f16): Delete function definitions.
> * config/aarch64/iterators.md (VDQHSF): New mode iterator.
> 
> gcc/testsuite/ChangeLog:
> 
> * gcc.target/aarch64/fmla_intrinsic_1.c: Rewrite `TEST_VMLA`
> so the lane choice is always valid and doesn't cause a compiler
> error when trying to call `vfma`. Also remove excessive
> backslashes from dejagnu directives.
> * gcc.target/aarch64/fmls_intrinsic_1.c: Likewise.
> * gcc.target/aarch64/simd/pr99195_3.c: Add
> `-fno-trapping-math` to prevent the optimization barrier being
> introduced and generating unnecessary `fmov`s.
> * gcc.target/aarch64/neon/vfma.c: New test.
> * gcc.target/aarch64/neon/vfms.c: New test.
> ---
> .../aarch64/aarch64-neon-builtins-base.cc     | 122 ++++-
> .../aarch64/aarch64-neon-builtins-base.def    |  54 ++
> gcc/config/aarch64/aarch64-simd-builtins.def  |   2 -
> gcc/config/aarch64/aarch64-simd.md            | 244 ++++++---
> gcc/config/aarch64/arm_neon.h                 | 500 ------------------
> gcc/config/aarch64/iterators.md               |   7 +
> .../gcc.target/aarch64/fmla_intrinsic_1.c     |  25 +-
> .../gcc.target/aarch64/fmls_intrinsic_1.c     |  25 +-
> gcc/testsuite/gcc.target/aarch64/neon/vfma.c  | 220 ++++++++
> gcc/testsuite/gcc.target/aarch64/neon/vfms.c  | 220 ++++++++
> .../gcc.target/aarch64/simd/pr99195_3.c       |   3 +-
> 11 files changed, 780 insertions(+), 642 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vfma.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vfms.c
> 
> diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.cc 
> b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
> index bdb14273f5f..f96b3332dc4 100644
> --- a/gcc/config/aarch64/aarch64-neon-builtins-base.cc
> +++ b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
> @@ -176,6 +176,36 @@ one_element_vector_type_p (tree type)
>   return VECTOR_TYPE_P (type) && known_eq (TYPE_VECTOR_SUBPARTS (type), 1U);
> }
> 
> +/* Build a call to the internal function IFN.
> +   Handles singleton vector arguments specially: they are cast to their
> +   inner element type before the function is called, and then the return 
> value
> +   is cast back to the expected singleton vector type.  */
> +tree
> +build_ifn_call (gimple_folder &f, internal_fn ifn, tree ret_type,
> + vec<tree> &args)
> +{
> +  for (auto &arg : args)
> +    if (one_element_vector_type_p (TREE_TYPE (arg)))
> +      arg = f.force_val (build_cast (TREE_TYPE (TREE_TYPE (arg)), arg));
> +
> +  auto call = gimple_build_call_internal_vec (ifn, args);
> +  gimple_seq_add_stmt_without_update (&f.stmts, call);
> +
> +  if (!one_element_vector_type_p (ret_type))
> +    {
> +      auto ret = is_gimple_reg_type (ret_type) ? make_ssa_name (ret_type)
> +       : create_tmp_var (ret_type);
> +      gimple_call_set_lhs (call, ret);
> +      return ret;
> +    }
> +  else
> +    {
> +      auto ret = create_tmp_var (TREE_TYPE (ret_type));
> +      gimple_call_set_lhs (call, ret);
> +      return build_vec_dup (ret_type, ret);
> +    }
> +}
> +
> /* Base class for all function expanders.
>    At least one of `expand` or `fold` must be overriden by derived classes.  
> */
> class gimple_function_base : public function_base
> @@ -644,44 +674,19 @@ public:
>   gimple *fold (gimple_folder &f) const override
>   {
>     tree lhs_type = TREE_TYPE (f.lhs);
> -    /* There are no instructions that handle V1DI or V1DF modes for these
> -       operations.  They need to be specially handled by casting the vector 
> to
> -       its element type and using it to feed the scalar version of the
> -       operation.  The scalar result is then cast back to a vector and 
> returned.
> -       This matches the prior implementation that arm_neon.h used for these
> -       operations.  */
> -    bool scalar_lhs = one_element_vector_type_p (lhs_type);
> -
>     vec<tree> args{};
>     for (unsigned i = 0; i < gimple_call_num_args (f.call); i++)
>       {
> tree arg = gimple_call_arg (f.call, i);
> - /* Convert V1DI/V1DF arguments to corresponding scalar modes.  */
> - if (scalar_lhs && one_element_vector_type_p (TREE_TYPE (arg)))
> -  arg = f.force_val (build_cast (TREE_TYPE (lhs_type), arg));
> /* .CLZ and .POPCOUNT take an unsigned argument.  */
> - else if ((m_ifn == IFN_CLZ || m_ifn == IFN_POPCOUNT)
> - && !TYPE_UNSIGNED (TREE_TYPE (arg)))
> + if ((m_ifn == IFN_CLZ || m_ifn == IFN_POPCOUNT)
> +    && !TYPE_UNSIGNED (TREE_TYPE (arg)))
>  arg = f.force_val (build_cast (unsigned_type_for (TREE_TYPE (arg)),
> arg));
> args.safe_push (arg);
>       }
> -
> -    auto call = gimple_build_call_internal_vec (this->m_ifn, args);
> -    args.release ();
> -
> -    if (!scalar_lhs)
> -      {
> - gimple_call_set_lhs (call, f.lhs);
> - return call;
> -      }
> -
> -    /* Temporary scalar to hold the result.  */
> -    tree res = create_tmp_var (TREE_TYPE (lhs_type));
> -    gimple_call_set_lhs (call, res);
> -    gimple_seq_add_stmt_without_update (&f.stmts, call);
> -    /* Build the actual vector that the call's result gets assigned to.  */
> -    return gimple_build_assign (f.lhs, build_vec_dup (lhs_type, res));
> +    return gimple_build_assign (f.lhs, build_ifn_call (f, this->m_ifn, 
> lhs_type,
> +       args));
>   }
> };
> 
> @@ -1019,6 +1024,46 @@ struct multiply_accumulate : public 
> gimple_function_base
> template <arith_kind kind> using gimple_mla = multiply_accumulate<kind, 
> false>;
> template <arith_kind kind> using gimple_mls = multiply_accumulate<kind, true>;
> 
> +template <arith_kind kind, bool negate>
> +struct gimple_fused_mla : public gimple_function_base
> +{
> +  gimple *fold (gimple_folder &f) const override
> +  {
> +    tree acc = gimple_call_arg (f.call, 0);
> +    tree lhs = gimple_call_arg (f.call, 1);
> +    tree rhs = gimple_call_arg (f.call, 2);
> +    tree lane_index;
> +    tree ret_type = TREE_TYPE (f.lhs);
> +
> +    switch (kind)
> +      {
> +      case arith_kind::normal:
> + break;
> +
> +      case arith_kind::dup:
> + rhs = f.force_val (build_vec_dup (TREE_TYPE (lhs), rhs));
> + break;
> +
> +      case arith_kind::lane:
> + lane_index = gimple_call_arg (f.call, 3);
> + rhs = f.force_val (build_lane_get (rhs, lane_index));
> + if (VECTOR_TYPE_P (ret_type))
> +  rhs = f.force_val (build_vec_dup (TREE_TYPE (lhs), rhs));
> + break;
> +      }
> +
> +    vec<tree> args{};
> +    args.safe_push (lhs);
> +    args.safe_push (rhs);
> +    args.safe_push (acc);
> +    auto ret = build_ifn_call (f, negate ? IFN_FNMA : IFN_FMA, ret_type, 
> args);
> +    args.release ();
> +    return this->maybe_optimization_barrier (f, ret);
> +  }
> +};
> +template <arith_kind kind> using gimple_fma = gimple_fused_mla<kind, false>;
> +template <arith_kind kind> using gimple_fms = gimple_fused_mla<kind, true>;
> +
> // Reinterpret
> NEON_FUNCTION (vreinterpret, vreinterpretq, gimple_reinterpret,)
> 
> @@ -1060,6 +1105,25 @@ NEON_FUNCTION (vmls_n, vmlsq_n, 
> gimple_mls<arith_kind::dup>,)
> NEON_FUNCTION (vmls_lane, vmls_laneq, vmlsq_lane, vmlsq_laneq,
>       gimple_mls<arith_kind::lane>,)
> 
> +// Multiply-accumulate (fused)
> +NEON_FUNCTION (vfma,   vfmaq,   gimple_fma<arith_kind::normal>,);
> +NEON_FUNCTION (vfma_n, vfmaq_n, gimple_fma<arith_kind::dup>,);
> +NEON_FUNCTION (vfmah_lane, vfmah_laneq,
> +       vfmas_lane, vfmas_laneq,
> +       vfmad_lane, vfmad_laneq,
> +       vfma_lane,  vfma_laneq,
> +       vfmaq_lane, vfmaq_laneq,
> +       gimple_fma<arith_kind::lane>,);
> +
> +NEON_FUNCTION (vfms,   vfmsq,   gimple_fms<arith_kind::normal>,);
> +NEON_FUNCTION (vfms_n, vfmsq_n, gimple_fms<arith_kind::dup>,);
> +NEON_FUNCTION (vfmsh_lane, vfmsh_laneq,
> +       vfmss_lane, vfmss_laneq,
> +       vfmsd_lane, vfmsd_laneq,
> +       vfms_lane,  vfms_laneq,
> +       vfmsq_lane, vfmsq_laneq,
> +       gimple_fms<arith_kind::lane>,);
> +
> // Saturating arithmetic
> NEON_FUNCTION (vqaddb, vqaddh, vqadds, vqaddd, vqadd, vqaddq, gimple_ifn, 
> (IFN_SAT_ADD))
> NEON_FUNCTION (vqsubb, vqsubh, vqsubs, vqsubd, vqsub, vqsubq, gimple_ifn, 
> (IFN_SAT_SUB))
> diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.def 
> b/gcc/config/aarch64/aarch64-neon-builtins-base.def
> index 40aa1a656d7..e519e47beb2 100644
> --- a/gcc/config/aarch64/aarch64-neon-builtins-base.def
> +++ b/gcc/config/aarch64/aarch64-neon-builtins-base.def
> @@ -296,6 +296,60 @@ DEF_NEON_FUNCTION (vmlsq_lane,  neon_mla_lane,  
> ("Q0,Q0,Q0,D0,ss32", lane<3>))
> DEF_NEON_FUNCTION (vmlsq_laneq, neon_mla_lane,  ("Q0,Q0,Q0,Q0,ss32", lane<3>))
> #undef REQUIRED_EXTENSIONS
> 
> +// Fused multiply-accumulate
> +#define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD)
> +DEF_NEON_FUNCTION (vfma, sd_float, ("D0,D0,D0,D0"))
> +DEF_NEON_FUNCTION (vfmaq,       sd_float, ("Q0,Q0,Q0,Q0"))
> +DEF_NEON_FUNCTION (vfma_n,      sd_float, ("D0,D0,D0,s0"))
> +DEF_NEON_FUNCTION (vfmaq_n,     sd_float, ("Q0,Q0,Q0,s0"))
> +DEF_NEON_FUNCTION (vfma_lane,   sd_float, ("D0,D0,D0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfma_laneq,  sd_float, ("D0,D0,D0,Q0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmaq_lane,  sd_float, ("Q0,Q0,Q0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmaq_laneq, sd_float, ("Q0,Q0,Q0,Q0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmas_lane,  s_float,  ("s0,s0,s0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmas_laneq, s_float,  ("s0,s0,s0,Q0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmad_lane,  d_float,  ("s0,s0,s0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmad_laneq, d_float,  ("s0,s0,s0,Q0,ss32", lane<3>))
> +
> +DEF_NEON_FUNCTION (vfms, sd_float, ("D0,D0,D0,D0"))
> +DEF_NEON_FUNCTION (vfmsq,       sd_float, ("Q0,Q0,Q0,Q0"))
> +DEF_NEON_FUNCTION (vfms_n,      sd_float, ("D0,D0,D0,s0"))
> +DEF_NEON_FUNCTION (vfmsq_n,     sd_float, ("Q0,Q0,Q0,s0"))
> +DEF_NEON_FUNCTION (vfms_lane,   sd_float, ("D0,D0,D0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfms_laneq,  sd_float, ("D0,D0,D0,Q0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmsq_lane,  sd_float, ("Q0,Q0,Q0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmsq_laneq, sd_float, ("Q0,Q0,Q0,Q0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmss_lane,  s_float,  ("s0,s0,s0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmss_laneq, s_float,  ("s0,s0,s0,Q0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmsd_lane,  d_float,  ("s0,s0,s0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmsd_laneq, d_float,  ("s0,s0,s0,Q0,ss32", lane<3>))
> +#undef REQUIRED_EXTENSIONS
> +
> +// Fused multiply-accumulate (FP16)
> +#define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD | 
> AARCH64_FL_F16)
> +DEF_NEON_FUNCTION (vfma, h_float, ("D0,D0,D0,D0"))
> +DEF_NEON_FUNCTION (vfmaq,       h_float, ("Q0,Q0,Q0,Q0"))
> +DEF_NEON_FUNCTION (vfma_n,      h_float, ("D0,D0,D0,s0"))
> +DEF_NEON_FUNCTION (vfmaq_n,     h_float, ("Q0,Q0,Q0,s0"))
> +DEF_NEON_FUNCTION (vfma_lane,   h_float, ("D0,D0,D0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfma_laneq,  h_float, ("D0,D0,D0,Q0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmaq_lane,  h_float, ("Q0,Q0,Q0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmaq_laneq, h_float, ("Q0,Q0,Q0,Q0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmah_lane,  h_float, ("s0,s0,s0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmah_laneq, h_float, ("s0,s0,s0,Q0,ss32", lane<3>))
> +
> +DEF_NEON_FUNCTION (vfms, h_float, ("D0,D0,D0,D0"))
> +DEF_NEON_FUNCTION (vfmsq,       h_float, ("Q0,Q0,Q0,Q0"))
> +DEF_NEON_FUNCTION (vfms_n,      h_float, ("D0,D0,D0,s0"))
> +DEF_NEON_FUNCTION (vfmsq_n,     h_float, ("Q0,Q0,Q0,s0"))
> +DEF_NEON_FUNCTION (vfms_lane,   h_float, ("D0,D0,D0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfms_laneq,  h_float, ("D0,D0,D0,Q0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmsq_lane,  h_float, ("Q0,Q0,Q0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmsq_laneq, h_float, ("Q0,Q0,Q0,Q0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmsh_lane,  h_float, ("s0,s0,s0,D0,ss32", lane<3>))
> +DEF_NEON_FUNCTION (vfmsh_laneq, h_float, ("s0,s0,s0,Q0,ss32", lane<3>))
> +#undef REQUIRED_EXTENSIONS
> +
> // Bitwise operations
> #define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD)
> DEF_NEON_FUNCTION (vand,   all_integer, ("D0,D0,D0"))
> diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def 
> b/gcc/config/aarch64/aarch64-simd-builtins.def
> index 1fb7c763990..3792ec3edf4 100644
> --- a/gcc/config/aarch64/aarch64-simd-builtins.def
> +++ b/gcc/config/aarch64/aarch64-simd-builtins.def
> @@ -669,10 +669,8 @@
>   BUILTIN_VALLP_NO_DI (STORE1_P, st1, 0, STORE)
> 
>   /* Implemented by fma<mode>4.  */
> -  BUILTIN_VHSDF (TERNOP, fma, 4, FP)
>   VAR1 (TERNOP, fma, 4, FP, hf)
>   /* Implemented by fnma<mode>4.  */
> -  BUILTIN_VHSDF (TERNOP, fnma, 4, FP)
>   VAR1 (TERNOP, fnma, 4, FP, hf)
> 
>  /* Implemented by aarch64_crypto_pmull<mode>.  */
> diff --git a/gcc/config/aarch64/aarch64-simd.md 
> b/gcc/config/aarch64/aarch64-simd.md
> index a42e1a60c58..7cc0d97b7c3 100644
> --- a/gcc/config/aarch64/aarch64-simd.md
> +++ b/gcc/config/aarch64/aarch64-simd.md
> @@ -2962,9 +2962,9 @@ (define_expand "aarch64_<su>mlsl_hi_laneq<mode>"
> )
> 
> ;; FP vector operations.
> -;; AArch64 AdvSIMD supports single-precision (32-bit) and 
> +;; AArch64 AdvSIMD supports single-precision (32-bit) and
> ;; double-precision (64-bit) floating-point data types and arithmetic as
> -;; defined by the IEEE 754-2008 standard.  This makes them vectorizable 
> +;; defined by the IEEE 754-2008 standard.  This makes them vectorizable
> ;; without the need for -ffast-math or -funsafe-math-optimizations.
> ;;
> ;; Floating-point operations can raise an exception.  Vectorizing such
> @@ -3059,78 +3059,95 @@ (define_insn "abs<mode>2<vczle><vczbe>"
>   [(set_attr "type" "neon_fp_abs_<stype><q>")]
> )
> 
> +;; vfma_f16, vfmaq_f16
> +;; vfma_f32, vfmaq_f32
> +;; vfmaq_f64
> (define_insn "fma<mode>4<vczle><vczbe>"
>   [(set (match_operand:VHSDF 0 "register_operand" "=w")
> -       (fma:VHSDF (match_operand:VHSDF 1 "register_operand" "w")
> -  (match_operand:VHSDF 2 "register_operand" "w")
> -  (match_operand:VHSDF 3 "register_operand" "0")))]
> + (fma:VHSDF (match_operand:VHSDF 1 "register_operand" "w")
> +   (match_operand:VHSDF 2 "register_operand" "w")
> +   (match_operand:VHSDF 3 "register_operand" "0")))]
>   "TARGET_SIMD"
>  "fmla\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
>   [(set_attr "type" "neon_fp_mla_<stype><q>")]
> )
> 
> +;; vfma_lane_f16, vfmaq_laneq_f16
> +;; vfma_lane_f32, vfmaq_laneq_f32
> +;; vfmaq_laneq_f64
> (define_insn "*aarch64_fma4_elt<mode><vczle><vczbe>"
> -  [(set (match_operand:VDQF 0 "register_operand" "=w")
> -    (fma:VDQF
> -      (vec_duplicate:VDQF
> - (vec_select:<VEL>
> -  (match_operand:VDQF 1 "register_operand" "<h_con>")
> -  (parallel [(match_operand:SI 2 "immediate_operand")])))
> -      (match_operand:VDQF 3 "register_operand" "w")
> -      (match_operand:VDQF 4 "register_operand" "0")))]
> +  [(set (match_operand:VHSDF 0 "register_operand" "=w")
> + (fma:VHSDF
> +  (vec_duplicate:VHSDF
> +    (vec_select:<VEL>
> +      (match_operand:VHSDF 1 "register_operand" "<h_con>")
> +      (parallel [(match_operand:SI 2 "immediate_operand")])))
> +  (match_operand:VHSDF 3 "register_operand" "w")
> +  (match_operand:VHSDF 4 "register_operand" "0")))]
>   "TARGET_SIMD"
>   {
>     operands[2] = aarch64_endian_lane_rtx (<MODE>mode, INTVAL (operands[2]));
>     return "fmla\\t%0.<Vtype>, %3.<Vtype>, %1.<Vetype>[%2]";
>   }
> -  [(set_attr "type" "neon_fp_mla_<Vetype>_scalar<q>")]
> +  [(set_attr "type" "neon_fp_mla_<stype>_scalar<q>")]
> )
> 
> +;; vfma_laneq_f16, vfmaq_lane_f16
> +;; vfma_laneq_f32, vfmaq_lane_f32
> (define_insn "*aarch64_fma4_elt_<vswap_width_name><mode><vczle><vczbe>"
> -  [(set (match_operand:VDQSF 0 "register_operand" "=w")
> -    (fma:VDQSF
> -      (vec_duplicate:VDQSF
> - (vec_select:<VEL>
> -  (match_operand:<VSWAP_WIDTH> 1 "register_operand" "<h_con>")
> -  (parallel [(match_operand:SI 2 "immediate_operand")])))
> -      (match_operand:VDQSF 3 "register_operand" "w")
> -      (match_operand:VDQSF 4 "register_operand" "0")))]
> +  [(set (match_operand:VDQHSF 0 "register_operand" "=w")
> + (fma:VDQHSF
> +  (vec_duplicate:VDQHSF
> +    (vec_select:<VEL>
> +      (match_operand:<VSWAP_WIDTH> 1 "register_operand" "<h_con>")
> +      (parallel [(match_operand:SI 2 "immediate_operand")])))
> +  (match_operand:VDQHSF 3 "register_operand" "w")
> +  (match_operand:VDQHSF 4 "register_operand" "0")))]
>   "TARGET_SIMD"
>   {
>     operands[2] = aarch64_endian_lane_rtx (<VSWAP_WIDTH>mode, INTVAL 
> (operands[2]));
>     return "fmla\\t%0.<Vtype>, %3.<Vtype>, %1.<Vetype>[%2]";
>   }
> -  [(set_attr "type" "neon_fp_mla_<Vetype>_scalar<q>")]
> +  [(set_attr "type" "neon_fp_mla_<stype>_scalar<q>")]
> )
> 
> +;; vfma_n_f16, vfmaq_n_f16
> +;; vfma_n_f32, vfmaq_n_f64
> +;; vfmaq_n_f64 vfmaq_lane_f64
> (define_insn "*aarch64_fma4_elt_from_dup<mode><vczle><vczbe>"
>   [(set (match_operand:VMUL 0 "register_operand" "=w")
> -    (fma:VMUL
> -      (vec_duplicate:VMUL
> -  (match_operand:<VEL> 1 "register_operand" "<h_con>"))
> -      (match_operand:VMUL 2 "register_operand" "w")
> -      (match_operand:VMUL 3 "register_operand" "0")))]
> + (fma:VMUL
> +  (vec_duplicate:VMUL
> +    (match_operand:<VEL> 1 "register_operand" "<h_con>"))
> +  (match_operand:VMUL 2 "register_operand" "w")
> +  (match_operand:VMUL 3 "register_operand" "0")))]
>   "TARGET_SIMD"
>   "fmla\t%0.<Vtype>, %2.<Vtype>, %1.<Vetype>[0]"
>   [(set_attr "type" "neon<fp>_mla_<stype>_scalar<q>")]
> )
> 
> -(define_insn "*aarch64_fma4_elt_to_64v2df"
> -  [(set (match_operand:DF 0 "register_operand" "=w")
> -    (fma:DF
> - (vec_select:DF
> -  (match_operand:V2DF 1 "register_operand" "w")
> -  (parallel [(match_operand:SI 2 "immediate_operand")]))
> -      (match_operand:DF 3 "register_operand" "w")
> -      (match_operand:DF 4 "register_operand" "0")))]
> +;; vfmah_lane_f16, vfmah_laneq_f16
> +;; vfmas_lane_f32, vfmas_laneq_f32
> +;; vfma_laneq_f64, vfmad_laneq_f64
> +(define_insn "*aarch64_fma<mode>4_elt_to_scalar"
> +  [(set (match_operand:<VEL> 0 "register_operand" "=w")
> + (fma:<VEL>
> +  (vec_select:<VEL>
> +    (match_operand:VHSDF 1 "register_operand" "<h_con>")
> +    (parallel [(match_operand:SI 2 "immediate_operand")]))
> +  (match_operand:<VEL> 3 "register_operand" "w")
> +  (match_operand:<VEL> 4 "register_operand" "0")))]
>   "TARGET_SIMD"
>   {
> -    operands[2] = aarch64_endian_lane_rtx (V2DFmode, INTVAL (operands[2]));
> -    return "fmla\\t%0.2d, %3.2d, %1.d[%2]";
> +    operands[2] = aarch64_endian_lane_rtx (<MODE>mode, INTVAL (operands[2]));
> +    return "fmla\\t%<Vetype>0, %<Vetype>3, %1.<Vetype>[%2]";
>   }
> -  [(set_attr "type" "neon_fp_mla_d_scalar_q")]
> +  [(set_attr "type" "neon_fp_mla_<stype>_q")]
> )
> 
> +;; vfms_f16, vfmsq_f16
> +;; vfms_f32, vfmsq_f32
> +;; vfmsq_f64
> (define_insn "fnma<mode>4<vczle><vczbe>"
>   [(set (match_operand:VHSDF 0 "register_operand" "=w")
> (fma:VHSDF
> @@ -3142,70 +3159,143 @@ (define_insn "fnma<mode>4<vczle><vczbe>"
>   [(set_attr "type" "neon_fp_mla_<stype><q>")]
> )
> 
> +;; vfms_lane_f16, vfmsq_laneq_f16,
> +;; vfms_lane_f32, vfmsq_laneq_f32
> +;; vfmsq_laneq_f64
> (define_insn "*aarch64_fnma4_elt<mode><vczle><vczbe>"
> -  [(set (match_operand:VDQF 0 "register_operand" "=w")
> -    (fma:VDQF
> -      (neg:VDQF
> -        (match_operand:VDQF 3 "register_operand" "w"))
> -      (vec_duplicate:VDQF
> - (vec_select:<VEL>
> -  (match_operand:VDQF 1 "register_operand" "<h_con>")
> -  (parallel [(match_operand:SI 2 "immediate_operand")])))
> -      (match_operand:VDQF 4 "register_operand" "0")))]
> +  [(set (match_operand:VHSDF 0 "register_operand" "=w")
> + (fma:VHSDF
> +  (neg:VHSDF
> +    (vec_duplicate:VHSDF
> +      (vec_select:<VEL>
> + (match_operand:VHSDF 1 "register_operand" "<h_con>")
> + (parallel [(match_operand:SI 2 "immediate_operand")]))))
> +  (match_operand:VHSDF 3 "register_operand" "w")
> +  (match_operand:VHSDF 4 "register_operand" "0")))]
> +  "TARGET_SIMD"
> +  {
> +    operands[2] = aarch64_endian_lane_rtx (<MODE>mode, INTVAL (operands[2]));
> +    return "fmls\\t%0.<Vtype>, %3.<Vtype>, %1.<Vetype>[%2]";
> +  }
> +  [(set_attr "type" "neon_fp_mla_<stype>_scalar<q>")]
> +)
> +(define_insn "*aarch64_fnma4_elt<mode><vczle><vczbe>_alt"
> +  [(set (match_operand:VHSDF 0 "register_operand" "=w")
> + (fma:VHSDF
> +  (neg:VHSDF
> +    (match_operand:VHSDF 3 "register_operand" "w"))
> +  (vec_duplicate:VHSDF
> +    (vec_select:<VEL>
> +      (match_operand:VHSDF 1 "register_operand" "<h_con>")
> +      (parallel [(match_operand:SI 2 "immediate_operand")])))
> +  (match_operand:VHSDF 4 "register_operand" "0")))]
>   "TARGET_SIMD"
>   {
>     operands[2] = aarch64_endian_lane_rtx (<MODE>mode, INTVAL (operands[2]));
>     return "fmls\\t%0.<Vtype>, %3.<Vtype>, %1.<Vetype>[%2]";
>   }
> -  [(set_attr "type" "neon_fp_mla_<Vetype>_scalar<q>")]
> +  [(set_attr "type" "neon_fp_mla_<stype>_scalar<q>")]
> )
> 
> +;; vfms_laneq_f16, vfmsq_lane_f16
> +;; vfms_laneq_f32, vfmsq_lane_f32
> (define_insn "*aarch64_fnma4_elt_<vswap_width_name><mode><vczle><vczbe>"
> -  [(set (match_operand:VDQSF 0 "register_operand" "=w")
> -    (fma:VDQSF
> -      (neg:VDQSF
> -        (match_operand:VDQSF 3 "register_operand" "w"))
> -      (vec_duplicate:VDQSF
> - (vec_select:<VEL>
> -  (match_operand:<VSWAP_WIDTH> 1 "register_operand" "<h_con>")
> -  (parallel [(match_operand:SI 2 "immediate_operand")])))
> -      (match_operand:VDQSF 4 "register_operand" "0")))]
> +  [(set (match_operand:VDQHSF 0 "register_operand" "=w")
> + (fma:VDQHSF
> +  (neg:VDQHSF
> +    (vec_duplicate:VDQHSF
> +      (vec_select:<VEL>
> + (match_operand:<VSWAP_WIDTH> 1 "register_operand" "<h_con>")
> + (parallel [(match_operand:SI 2 "immediate_operand")]))))
> +  (match_operand:VDQHSF 3 "register_operand" "w")
> +  (match_operand:VDQHSF 4 "register_operand" "0")))]
> +  "TARGET_SIMD"
> +  {
> +    operands[2] = aarch64_endian_lane_rtx (<VSWAP_WIDTH>mode, INTVAL 
> (operands[2]));
> +    return "fmls\\t%0.<Vtype>, %3.<Vtype>, %1.<Vetype>[%2]";
> +  }
> +  [(set_attr "type" "neon_fp_mla_<stype>_scalar<q>")]
> +)
> +(define_insn "*aarch64_fnma4_elt_<vswap_width_name><mode><vczle><vczbe>_alt"
> +  [(set (match_operand:VDQHSF 0 "register_operand" "=w")
> + (fma:VDQHSF
> +  (neg:VDQHSF
> +    (match_operand:VDQHSF 3 "register_operand" "w"))
> +  (vec_duplicate:VDQHSF
> +    (vec_select:<VEL>
> +      (match_operand:<VSWAP_WIDTH> 1 "register_operand" "<h_con>")
> +      (parallel [(match_operand:SI 2 "immediate_operand")])))
> +  (match_operand:VDQHSF 4 "register_operand" "0")))]
>   "TARGET_SIMD"
>   {
>     operands[2] = aarch64_endian_lane_rtx (<VSWAP_WIDTH>mode, INTVAL 
> (operands[2]));
>     return "fmls\\t%0.<Vtype>, %3.<Vtype>, %1.<Vetype>[%2]";
>   }
> -  [(set_attr "type" "neon_fp_mla_<Vetype>_scalar<q>")]
> +  [(set_attr "type" "neon_fp_mla_<stype>_scalar<q>")]
> )
> 
> +;; vfms_n_f16, vfmsq_n_f16
> +;; vfms_n_f32, vfmsq_n_f32
> +;; vfmsq_n_f64, vfmq_lane_f64
> (define_insn "*aarch64_fnma4_elt_from_dup<mode><vczle><vczbe>"
>   [(set (match_operand:VMUL 0 "register_operand" "=w")
> -    (fma:VMUL
> -      (neg:VMUL
> -        (match_operand:VMUL 2 "register_operand" "w"))
> -      (vec_duplicate:VMUL
> - (match_operand:<VEL> 1 "register_operand" "<h_con>"))
> -      (match_operand:VMUL 3 "register_operand" "0")))]
> + (fma:VMUL
> +  (neg:VMUL
> +    (vec_duplicate:VMUL
> +      (match_operand:<VEL> 1 "register_operand" "<h_con>")))
> +  (match_operand:VMUL 2 "register_operand" "w")
> +  (match_operand:VMUL 3 "register_operand" "0")))]
> +  "TARGET_SIMD"
> +  "fmls\t%0.<Vtype>, %2.<Vtype>, %1.<Vetype>[0]"
> +  [(set_attr "type" "neon<fp>_mla_<stype>_scalar<q>")]
> +)
> +(define_insn "*aarch64_fnma4_elt_from_dup<mode><vczle><vczbe>_alt"
> +  [(set (match_operand:VMUL 0 "register_operand" "=w")
> + (fma:VMUL
> +  (neg:VMUL
> +    (match_operand:VMUL 2 "register_operand" "w"))
> +  (vec_duplicate:VMUL
> +    (match_operand:<VEL> 1 "register_operand" "<h_con>"))
> +  (match_operand:VMUL 3 "register_operand" "0")))]
>   "TARGET_SIMD"
>   "fmls\t%0.<Vtype>, %2.<Vtype>, %1.<Vetype>[0]"
>   [(set_attr "type" "neon<fp>_mla_<stype>_scalar<q>")]
> )
> 
> -(define_insn "*aarch64_fnma4_elt_to_64v2df"
> -  [(set (match_operand:DF 0 "register_operand" "=w")
> -    (fma:DF
> -      (vec_select:DF
> - (match_operand:V2DF 1 "register_operand" "w")
> - (parallel [(match_operand:SI 2 "immediate_operand")]))
> -      (neg:DF
> -        (match_operand:DF 3 "register_operand" "w"))
> -      (match_operand:DF 4 "register_operand" "0")))]
> +;; vfmsh_lane_f16, vfmsh_laneq_f16
> +;; vfmss_lane_f32, vfmss_laneq_f32
> +;; vfms_laneq_f64, vfmsd_laneq_f64
> +(define_insn "*aarch64_fnma<mode>4_elt_to_scalar"
> +  [(set (match_operand:<VEL> 0 "register_operand" "=w")
> + (fma:<VEL>
> +  (neg:<VEL>
> +    (vec_select:<VEL>
> +      (match_operand:VHSDF 1 "register_operand" "<h_con>")
> +      (parallel [(match_operand:SI 2 "immediate_operand")])))
> +  (match_operand:<VEL> 3 "register_operand" "w")
> +  (match_operand:<VEL> 4 "register_operand" "0")))]
>   "TARGET_SIMD"
>   {
> -    operands[2] = aarch64_endian_lane_rtx (V2DFmode, INTVAL (operands[2]));
> -    return "fmls\\t%0.2d, %3.2d, %1.d[%2]";
> +    operands[2] = aarch64_endian_lane_rtx (<MODE>mode, INTVAL (operands[2]));
> +    return "fmls\\t%<Vetype>0, %<Vetype>3, %1.<Vetype>[%2]";
> +  }
> +  [(set_attr "type" "neon_fp_mla_<stype>_q")]
> +)
> +(define_insn "*aarch64_fnma<mode>4_elt_to_scalar_alt"
> +  [(set (match_operand:<VEL> 0 "register_operand" "=w")
> + (fma:<VEL>
> +  (neg:<VEL>
> +    (match_operand:<VEL> 3 "register_operand" "w"))
> +  (vec_select:<VEL>
> +    (match_operand:VHSDF 1 "register_operand" "<h_con>")
> +    (parallel [(match_operand:SI 2 "immediate_operand")]))
> +  (match_operand:<VEL> 4 "register_operand" "0")))]
> +  "TARGET_SIMD"
> +  {
> +    operands[2] = aarch64_endian_lane_rtx (<MODE>mode, INTVAL (operands[2]));
> +    return "fmls\\t%<Vetype>0, %<Vetype>3, %1.<Vetype>[%2]";
>   }
> -  [(set_attr "type" "neon_fp_mla_d_scalar_q")]
> +  [(set_attr "type" "neon_fp_mla_<stype>_q")]
> )
> 
> ;; Vector versions of the floating-point frint patterns.
> diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
> index 71b93a6adf5..db9d5c4c185 100644
> --- a/gcc/config/aarch64/arm_neon.h
> +++ b/gcc/config/aarch64/arm_neon.h
> @@ -6858,352 +6858,6 @@ vcvtpq_u64_f64 (float64x2_t __a)
>   return __builtin_aarch64_lceiluv2dfv2di_us (__a);
> }
> 
> -/* vfma  */
> -
> -__extension__ extern __inline float64x1_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfma_f64 (float64x1_t __a, float64x1_t __b, float64x1_t __c)
> -{
> -  return (float64x1_t) {__builtin_fma (__b[0], __c[0], __a[0])};
> -}
> -
> -__extension__ extern __inline float32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfma_f32 (float32x2_t __a, float32x2_t __b, float32x2_t __c)
> -{
> -  return __builtin_aarch64_fmav2sf (__b, __c, __a);
> -}
> -
> -__extension__ extern __inline float32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmaq_f32 (float32x4_t __a, float32x4_t __b, float32x4_t __c)
> -{
> -  return __builtin_aarch64_fmav4sf (__b, __c, __a);
> -}
> -
> -__extension__ extern __inline float64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmaq_f64 (float64x2_t __a, float64x2_t __b, float64x2_t __c)
> -{
> -  return __builtin_aarch64_fmav2df (__b, __c, __a);
> -}
> -
> -__extension__ extern __inline float32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfma_n_f32 (float32x2_t __a, float32x2_t __b, float32_t __c)
> -{
> -  return __builtin_aarch64_fmav2sf (__b, vdup_n_f32 (__c), __a);
> -}
> -
> -__extension__ extern __inline float64x1_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfma_n_f64 (float64x1_t __a, float64x1_t __b, float64_t __c)
> -{
> -  return (float64x1_t) {__b[0] * __c + __a[0]};
> -}
> -
> -__extension__ extern __inline float32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmaq_n_f32 (float32x4_t __a, float32x4_t __b, float32_t __c)
> -{
> -  return __builtin_aarch64_fmav4sf (__b, vdupq_n_f32 (__c), __a);
> -}
> -
> -__extension__ extern __inline float64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmaq_n_f64 (float64x2_t __a, float64x2_t __b, float64_t __c)
> -{
> -  return __builtin_aarch64_fmav2df (__b, vdupq_n_f64 (__c), __a);
> -}
> -
> -/* vfma_lane  */
> -
> -__extension__ extern __inline float32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfma_lane_f32 (float32x2_t __a, float32x2_t __b,
> -       float32x2_t __c, const int __lane)
> -{
> -  return __builtin_aarch64_fmav2sf (__b,
> -    __aarch64_vdup_lane_f32 (__c, __lane),
> -    __a);
> -}
> -
> -__extension__ extern __inline float64x1_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfma_lane_f64 (float64x1_t __a, float64x1_t __b,
> -       float64x1_t __c, const int __lane)
> -{
> -  return (float64x1_t) {__builtin_fma (__b[0], __c[0], __a[0])};
> -}
> -
> -__extension__ extern __inline float64_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmad_lane_f64 (float64_t __a, float64_t __b,
> -        float64x1_t __c, const int __lane)
> -{
> -  return __builtin_fma (__b, __c[0], __a);
> -}
> -
> -__extension__ extern __inline float32_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmas_lane_f32 (float32_t __a, float32_t __b,
> -        float32x2_t __c, const int __lane)
> -{
> -  return __builtin_fmaf (__b, __aarch64_vget_lane_any (__c, __lane), __a);
> -}
> -
> -/* vfma_laneq  */
> -
> -__extension__ extern __inline float32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfma_laneq_f32 (float32x2_t __a, float32x2_t __b,
> -        float32x4_t __c, const int __lane)
> -{
> -  return __builtin_aarch64_fmav2sf (__b,
> -    __aarch64_vdup_laneq_f32 (__c, __lane),
> -    __a);
> -}
> -
> -__extension__ extern __inline float64x1_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfma_laneq_f64 (float64x1_t __a, float64x1_t __b,
> -        float64x2_t __c, const int __lane)
> -{
> -  float64_t __c0 = __aarch64_vget_lane_any (__c, __lane);
> -  return (float64x1_t) {__builtin_fma (__b[0], __c0, __a[0])};
> -}
> -
> -__extension__ extern __inline float64_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmad_laneq_f64 (float64_t __a, float64_t __b,
> -         float64x2_t __c, const int __lane)
> -{
> -  return __builtin_fma (__b, __aarch64_vget_lane_any (__c, __lane), __a);
> -}
> -
> -__extension__ extern __inline float32_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmas_laneq_f32 (float32_t __a, float32_t __b,
> - float32x4_t __c, const int __lane)
> -{
> -  return __builtin_fmaf (__b, __aarch64_vget_lane_any (__c, __lane), __a);
> -}
> -
> -/* vfmaq_lane  */
> -
> -__extension__ extern __inline float32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmaq_lane_f32 (float32x4_t __a, float32x4_t __b,
> -        float32x2_t __c, const int __lane)
> -{
> -  return __builtin_aarch64_fmav4sf (__b,
> -    __aarch64_vdupq_lane_f32 (__c, __lane),
> -    __a);
> -}
> -
> -__extension__ extern __inline float64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmaq_lane_f64 (float64x2_t __a, float64x2_t __b,
> -        float64x1_t __c, const int __lane)
> -{
> -  return __builtin_aarch64_fmav2df (__b, vdupq_n_f64 (__c[0]), __a);
> -}
> -
> -/* vfmaq_laneq  */
> -
> -__extension__ extern __inline float32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmaq_laneq_f32 (float32x4_t __a, float32x4_t __b,
> -         float32x4_t __c, const int __lane)
> -{
> -  return __builtin_aarch64_fmav4sf (__b,
> -    __aarch64_vdupq_laneq_f32 (__c, __lane),
> -    __a);
> -}
> -
> -__extension__ extern __inline float64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmaq_laneq_f64 (float64x2_t __a, float64x2_t __b,
> -         float64x2_t __c, const int __lane)
> -{
> -  return __builtin_aarch64_fmav2df (__b,
> -    __aarch64_vdupq_laneq_f64 (__c, __lane),
> -    __a);
> -}
> -
> -/* vfms  */
> -
> -__extension__ extern __inline float64x1_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfms_f64 (float64x1_t __a, float64x1_t __b, float64x1_t __c)
> -{
> -  return (float64x1_t) {__builtin_fma (-__b[0], __c[0], __a[0])};
> -}
> -
> -__extension__ extern __inline float32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfms_f32 (float32x2_t __a, float32x2_t __b, float32x2_t __c)
> -{
> -  return __builtin_aarch64_fmav2sf (-__b, __c, __a);
> -}
> -
> -__extension__ extern __inline float32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsq_f32 (float32x4_t __a, float32x4_t __b, float32x4_t __c)
> -{
> -  return __builtin_aarch64_fmav4sf (-__b, __c, __a);
> -}
> -
> -__extension__ extern __inline float64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsq_f64 (float64x2_t __a, float64x2_t __b, float64x2_t __c)
> -{
> -  return __builtin_aarch64_fmav2df (-__b, __c, __a);
> -}
> -
> -__extension__ extern __inline float32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfms_n_f32 (float32x2_t __a, float32x2_t __b, float32_t __c)
> -{
> -  return __builtin_aarch64_fmav2sf (-__b, vdup_n_f32 (__c), __a);
> -}
> -
> -__extension__ extern __inline float64x1_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfms_n_f64 (float64x1_t __a, float64x1_t __b, float64_t __c)
> -{
> -  return (float64x1_t) {-__b[0] * __c + __a[0]};
> -}
> -
> -__extension__ extern __inline float32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsq_n_f32 (float32x4_t __a, float32x4_t __b, float32_t __c)
> -{
> -  return __builtin_aarch64_fmav4sf (-__b, vdupq_n_f32 (__c), __a);
> -}
> -
> -__extension__ extern __inline float64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsq_n_f64 (float64x2_t __a, float64x2_t __b, float64_t __c)
> -{
> -  return __builtin_aarch64_fmav2df (-__b, vdupq_n_f64 (__c), __a);
> -}
> -
> -/* vfms_lane  */
> -
> -__extension__ extern __inline float32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfms_lane_f32 (float32x2_t __a, float32x2_t __b,
> -       float32x2_t __c, const int __lane)
> -{
> -  return __builtin_aarch64_fmav2sf (-__b,
> -    __aarch64_vdup_lane_f32 (__c, __lane),
> -    __a);
> -}
> -
> -__extension__ extern __inline float64x1_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfms_lane_f64 (float64x1_t __a, float64x1_t __b,
> -       float64x1_t __c, const int __lane)
> -{
> -  return (float64x1_t) {__builtin_fma (-__b[0], __c[0], __a[0])};
> -}
> -
> -__extension__ extern __inline float64_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsd_lane_f64 (float64_t __a, float64_t __b,
> -        float64x1_t __c, const int __lane)
> -{
> -  return __builtin_fma (-__b, __c[0], __a);
> -}
> -
> -__extension__ extern __inline float32_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmss_lane_f32 (float32_t __a, float32_t __b,
> -        float32x2_t __c, const int __lane)
> -{
> -  return __builtin_fmaf (-__b, __aarch64_vget_lane_any (__c, __lane), __a);
> -}
> -
> -/* vfms_laneq  */
> -
> -__extension__ extern __inline float32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfms_laneq_f32 (float32x2_t __a, float32x2_t __b,
> -        float32x4_t __c, const int __lane)
> -{
> -  return __builtin_aarch64_fmav2sf (-__b,
> -    __aarch64_vdup_laneq_f32 (__c, __lane),
> -    __a);
> -}
> -
> -__extension__ extern __inline float64x1_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfms_laneq_f64 (float64x1_t __a, float64x1_t __b,
> -        float64x2_t __c, const int __lane)
> -{
> -  float64_t __c0 = __aarch64_vget_lane_any (__c, __lane);
> -  return (float64x1_t) {__builtin_fma (-__b[0], __c0, __a[0])};
> -}
> -
> -__extension__ extern __inline float64_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsd_laneq_f64 (float64_t __a, float64_t __b,
> -         float64x2_t __c, const int __lane)
> -{
> -  return __builtin_fma (-__b, __aarch64_vget_lane_any (__c, __lane), __a);
> -}
> -
> -__extension__ extern __inline float32_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmss_laneq_f32 (float32_t __a, float32_t __b,
> - float32x4_t __c, const int __lane)
> -{
> -  return __builtin_fmaf (-__b, __aarch64_vget_lane_any (__c, __lane), __a);
> -}
> -
> -/* vfmsq_lane  */
> -
> -__extension__ extern __inline float32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsq_lane_f32 (float32x4_t __a, float32x4_t __b,
> -        float32x2_t __c, const int __lane)
> -{
> -  return __builtin_aarch64_fmav4sf (-__b,
> -    __aarch64_vdupq_lane_f32 (__c, __lane),
> -    __a);
> -}
> -
> -__extension__ extern __inline float64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsq_lane_f64 (float64x2_t __a, float64x2_t __b,
> -        float64x1_t __c, const int __lane)
> -{
> -  return __builtin_aarch64_fmav2df (-__b, vdupq_n_f64 (__c[0]), __a);
> -}
> -
> -/* vfmsq_laneq  */
> -
> -__extension__ extern __inline float32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsq_laneq_f32 (float32x4_t __a, float32x4_t __b,
> -         float32x4_t __c, const int __lane)
> -{
> -  return __builtin_aarch64_fmav4sf (-__b,
> -    __aarch64_vdupq_laneq_f32 (__c, __lane),
> -    __a);
> -}
> -
> -__extension__ extern __inline float64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsq_laneq_f64 (float64x2_t __a, float64x2_t __b,
> -         float64x2_t __c, const int __lane)
> -{
> -  return __builtin_aarch64_fmav2df (-__b,
> -    __aarch64_vdupq_laneq_f64 (__c, __lane),
> -    __a);
> -}
> -
> /* vld1 */
> 
> __extension__ extern __inline float16x4_t
> @@ -17260,162 +16914,8 @@ vrsqrtsq_f16 (float16x8_t __a, float16x8_t __b)
>   return __builtin_aarch64_rsqrtsv8hf (__a, __b);
> }
> 
> -/* ARMv8.2-A FP16 three operands vector intrinsics.  */
> -
> -__extension__ extern __inline float16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfma_f16 (float16x4_t __a, float16x4_t __b, float16x4_t __c)
> -{
> -  return __builtin_aarch64_fmav4hf (__b, __c, __a);
> -}
> -
> -__extension__ extern __inline float16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmaq_f16 (float16x8_t __a, float16x8_t __b, float16x8_t __c)
> -{
> -  return __builtin_aarch64_fmav8hf (__b, __c, __a);
> -}
> -
> -__extension__ extern __inline float16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfms_f16 (float16x4_t __a, float16x4_t __b, float16x4_t __c)
> -{
> -  return __builtin_aarch64_fnmav4hf (__b, __c, __a);
> -}
> -
> -__extension__ extern __inline float16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsq_f16 (float16x8_t __a, float16x8_t __b, float16x8_t __c)
> -{
> -  return __builtin_aarch64_fnmav8hf (__b, __c, __a);
> -}
> -
> /* ARMv8.2-A FP16 lane vector intrinsics.  */
> 
> -__extension__ extern __inline float16_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmah_lane_f16 (float16_t __a, float16_t __b,
> - float16x4_t __c, const int __lane)
> -{
> -  return vfmah_f16 (__a, __b, __aarch64_vget_lane_any (__c, __lane));
> -}
> -
> -__extension__ extern __inline float16_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmah_laneq_f16 (float16_t __a, float16_t __b,
> - float16x8_t __c, const int __lane)
> -{
> -  return vfmah_f16 (__a, __b, __aarch64_vget_lane_any (__c, __lane));
> -}
> -
> -__extension__ extern __inline float16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfma_lane_f16 (float16x4_t __a, float16x4_t __b,
> -       float16x4_t __c, const int __lane)
> -{
> -  return vfma_f16 (__a, __b, __aarch64_vdup_lane_f16 (__c, __lane));
> -}
> -
> -__extension__ extern __inline float16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmaq_lane_f16 (float16x8_t __a, float16x8_t __b,
> - float16x4_t __c, const int __lane)
> -{
> -  return vfmaq_f16 (__a, __b, __aarch64_vdupq_lane_f16 (__c, __lane));
> -}
> -
> -__extension__ extern __inline float16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfma_laneq_f16 (float16x4_t __a, float16x4_t __b,
> - float16x8_t __c, const int __lane)
> -{
> -  return vfma_f16 (__a, __b, __aarch64_vdup_laneq_f16 (__c, __lane));
> -}
> -
> -__extension__ extern __inline float16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmaq_laneq_f16 (float16x8_t __a, float16x8_t __b,
> - float16x8_t __c, const int __lane)
> -{
> -  return vfmaq_f16 (__a, __b, __aarch64_vdupq_laneq_f16 (__c, __lane));
> -}
> -
> -__extension__ extern __inline float16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfma_n_f16 (float16x4_t __a, float16x4_t __b, float16_t __c)
> -{
> -  return vfma_f16 (__a, __b, vdup_n_f16 (__c));
> -}
> -
> -__extension__ extern __inline float16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmaq_n_f16 (float16x8_t __a, float16x8_t __b, float16_t __c)
> -{
> -  return vfmaq_f16 (__a, __b, vdupq_n_f16 (__c));
> -}
> -
> -__extension__ extern __inline float16_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsh_lane_f16 (float16_t __a, float16_t __b,
> - float16x4_t __c, const int __lane)
> -{
> -  return vfmsh_f16 (__a, __b, __aarch64_vget_lane_any (__c, __lane));
> -}
> -
> -__extension__ extern __inline float16_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsh_laneq_f16 (float16_t __a, float16_t __b,
> - float16x8_t __c, const int __lane)
> -{
> -  return vfmsh_f16 (__a, __b, __aarch64_vget_lane_any (__c, __lane));
> -}
> -
> -__extension__ extern __inline float16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfms_lane_f16 (float16x4_t __a, float16x4_t __b,
> -       float16x4_t __c, const int __lane)
> -{
> -  return vfms_f16 (__a, __b, __aarch64_vdup_lane_f16 (__c, __lane));
> -}
> -
> -__extension__ extern __inline float16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsq_lane_f16 (float16x8_t __a, float16x8_t __b,
> - float16x4_t __c, const int __lane)
> -{
> -  return vfmsq_f16 (__a, __b, __aarch64_vdupq_lane_f16 (__c, __lane));
> -}
> -
> -__extension__ extern __inline float16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfms_laneq_f16 (float16x4_t __a, float16x4_t __b,
> - float16x8_t __c, const int __lane)
> -{
> -  return vfms_f16 (__a, __b, __aarch64_vdup_laneq_f16 (__c, __lane));
> -}
> -
> -__extension__ extern __inline float16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsq_laneq_f16 (float16x8_t __a, float16x8_t __b,
> - float16x8_t __c, const int __lane)
> -{
> -  return vfmsq_f16 (__a, __b, __aarch64_vdupq_laneq_f16 (__c, __lane));
> -}
> -
> -__extension__ extern __inline float16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfms_n_f16 (float16x4_t __a, float16x4_t __b, float16_t __c)
> -{
> -  return vfms_f16 (__a, __b, vdup_n_f16 (__c));
> -}
> -
> -__extension__ extern __inline float16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vfmsq_n_f16 (float16x8_t __a, float16x8_t __b, float16_t __c)
> -{
> -  return vfmsq_f16 (__a, __b, vdupq_n_f16 (__c));
> -}
> -
> __extension__ extern __inline float16_t
> __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> vmulxh_lane_f16 (float16_t __a, float16x4_t __b, const int __lane)
> diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
> index 30bbd5878b6..d787f4f5f53 100644
> --- a/gcc/config/aarch64/iterators.md
> +++ b/gcc/config/aarch64/iterators.md
> @@ -215,6 +215,13 @@ (define_mode_iterator VSFDF [V2SF V4SF V2DF DF SF])
> ;; Advanced SIMD single Float modes.
> (define_mode_iterator VDQSF [V2SF V4SF])
> 
> +;; Advanced SIMD half and single Float modes.
> +(define_mode_iterator VDQHSF [
> + (V4HF "TARGET_SIMD_F16INST")
> + (V8HF "TARGET_SIMD_F16INST")
> + V2SF V4SF
> +])
> +
> ;; Quad vector float modes with half/bfloat elements.
> (define_mode_iterator VQ_BHF [V8HF V8BF])
> 
> diff --git a/gcc/testsuite/gcc.target/aarch64/fmla_intrinsic_1.c 
> b/gcc/testsuite/gcc.target/aarch64/fmla_intrinsic_1.c
> index c1aeb06e747..9571f6df727 100644
> --- a/gcc/testsuite/gcc.target/aarch64/fmla_intrinsic_1.c
> +++ b/gcc/testsuite/gcc.target/aarch64/fmla_intrinsic_1.c
> @@ -19,16 +19,9 @@ test_vfma##q1##_lane##q2##_f##size (float##size##_t * res, 
> \
>   float##size##x##in1_lanes##_t a = vld1##q1##_f##size (res); \
>   float##size##x##in1_lanes##_t b = vld1##q1##_f##size (in1); \
>   float##size##x##in2_lanes##_t c; \
> -  if (in2_lanes > 1) \
> -    { \
> -      c = vld1##q2##_f##size (in2); \
> -      a = vfma##q1##_lane##q2##_f##size (a, b, c, 1); \
> -    } \
> -  else \
> -    { \
> -      c = vld1##q2##_f##size (in2 + 1); \
> -      a = vfma##q1##_lane##q2##_f##size (a, b, c, 0); \
> -    } \
> +  const int lane_no = in2_lanes > 1 ? 1 : 0; \
> +  c = vld1##q2##_f##size (in2 + (in2_lanes == 1)); \
> +  a = vfma##q1##_lane##q2##_f##size (a, b, c, lane_no); \
>   vst1##q1##_f##size (res, a); \
> }
> 
> @@ -99,20 +92,20 @@ main (int argc, char **argv)
> 
> /* vfma_laneq_f32.
>    vfma_lane_f32.  */
> -/* { dg-final { scan-assembler-times "fmla\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s, 
> v\[0-9\]+\.s\\\[\[0-9\]+\\\]" 2 } } */
> +/* { dg-final { scan-assembler-times {fmla v[0-9]+.2s, v[0-9]+.2s, 
> v[0-9]+.s\[[0-9]+\]} 2 } } */
> 
> /* vfmaq_lane_f32.
>    vfmaq_laneq_f32.  */
> -/* { dg-final { scan-assembler-times "fmla\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, 
> v\[0-9\]+\.s\\\[\[0-9\]+\\\]" 2 } } */
> +/* { dg-final { scan-assembler-times {fmla v[0-9]+.4s, v[0-9]+.4s, 
> v[0-9]+.s\[[0-9]+\]} 2 } } */
> 
> /* vfma_lane_f64.
>    vfma_laneq_f64. */
> -/* { dg-final { scan-assembler-times "fmadd\\td\[0-9\]+\, d\[0-9\]+\, 
> d\[0-9\]+\, d\[0-9\]+" 1 { target aarch64_big_endian } } } */
> -/* { dg-final { scan-assembler-times "fmadd\\td\[0-9\]+\, d\[0-9\]+\, 
> d\[0-9\]+\, d\[0-9\]+" 2 { target aarch64_little_endian } } } */
> +/* { dg-final { scan-assembler-times {fmadd d[0-9]+, d[0-9]+, d[0-9]+, 
> d[0-9]+} 1 { target aarch64_big_endian } } } */
> +/* { dg-final { scan-assembler-times {fmadd d[0-9]+, d[0-9]+, d[0-9]+, 
> d[0-9]+} 2 { target aarch64_little_endian } } } */
> 
> /* vfmaq_lane_f64.
>    vfmaq_laneq_f64.  */
> -/* { dg-final { scan-assembler-times "fmla\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, 
> v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 3 { target aarch64_big_endian } } } */
> -/* { dg-final { scan-assembler-times "fmla\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, 
> v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 2 { target aarch64_little_endian } } } */
> +/* { dg-final { scan-assembler-times {fmla v[0-9]+.2d, v[0-9]+.2d, 
> v[0-9]+.d\[[0-9]+\]} 3 { target aarch64_big_endian } } } */
> +/* { dg-final { scan-assembler-times {fmla v[0-9]+.2d, v[0-9]+.2d, 
> v[0-9]+.d\[[0-9]+\]} 2 { target aarch64_little_endian } } } */
> 
> 
> diff --git a/gcc/testsuite/gcc.target/aarch64/fmls_intrinsic_1.c 
> b/gcc/testsuite/gcc.target/aarch64/fmls_intrinsic_1.c
> index 3137ea91e80..0f7e1a76487 100644
> --- a/gcc/testsuite/gcc.target/aarch64/fmls_intrinsic_1.c
> +++ b/gcc/testsuite/gcc.target/aarch64/fmls_intrinsic_1.c
> @@ -19,16 +19,9 @@ test_vfms##q1##_lane##q2##_f##size (float##size##_t * res, 
> \
>   float##size##x##in1_lanes##_t a = vld1##q1##_f##size (res); \
>   float##size##x##in1_lanes##_t b = vld1##q1##_f##size (in1); \
>   float##size##x##in2_lanes##_t c; \
> -  if (in2_lanes > 1) \
> -    { \
> -      c = vld1##q2##_f##size (in2); \
> -      a = vfms##q1##_lane##q2##_f##size (a, b, c, 1); \
> -    } \
> -  else \
> -    { \
> -      c = vld1##q2##_f##size (in2 + 1); \
> -      a = vfms##q1##_lane##q2##_f##size (a, b, c, 0); \
> -    } \
> +  const int lane_no = in2_lanes > 1 ? 1 : 0; \
> +  c = vld1##q2##_f##size (in2 + (in2_lanes == 1)); \
> +  a = vfms##q1##_lane##q2##_f##size (a, b, c, lane_no); \
>   vst1##q1##_f##size (res, a); \
> }
> 
> @@ -100,20 +93,20 @@ main (int argc, char **argv)
> 
> /* vfms_laneq_f32.
>    vfms_lane_f32.  */
> -/* { dg-final { scan-assembler-times "fmls\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s, 
> v\[0-9\]+\.s\\\[\[0-9\]+\\\]" 2 } } */
> +/* { dg-final { scan-assembler-times {fmls v[0-9]+.2s, v[0-9]+.2s, 
> v[0-9]+.s\[[0-9]+\]} 2 } } */
> 
> /* vfmsq_lane_f32.
>    vfmsq_laneq_f32.  */
> -/* { dg-final { scan-assembler-times "fmls\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, 
> v\[0-9\]+\.s\\\[\[0-9\]+\\\]" 2 } } */
> +/* { dg-final { scan-assembler-times {fmls v[0-9]+.4s, v[0-9]+.4s, 
> v[0-9]+.s\[[0-9]+\]} 2 } } */
> 
> /* vfms_lane_f64.
>    vfms_laneq_f64.  */
> -/* { dg-final { scan-assembler-times "fmsub\\td\[0-9\]+\, d\[0-9\]+\, 
> d\[0-9\]+\, d\[0-9\]+" 1 { target aarch64_big_endian } } } */
> -/* { dg-final { scan-assembler-times "fmsub\\td\[0-9\]+\, d\[0-9\]+\, 
> d\[0-9\]+\, d\[0-9\]+" 2 { target aarch64_little_endian } } } */
> +/* { dg-final { scan-assembler-times {fmsub d[0-9]+, d[0-9]+, d[0-9]+, 
> d[0-9]+} 1 { target aarch64_big_endian } } } */
> +/* { dg-final { scan-assembler-times {fmsub d[0-9]+, d[0-9]+, d[0-9]+, 
> d[0-9]+} 2 { target aarch64_little_endian } } } */
> 
> /* vfmsq_lane_f64.
>    vfmsq_laneq_f64.  */
> -/* { dg-final { scan-assembler-times "fmls\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, 
> v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 3 { target aarch64_big_endian } } } */
> -/* { dg-final { scan-assembler-times "fmls\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, 
> v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 2 { target aarch64_little_endian } } } */
> +/* { dg-final { scan-assembler-times {fmls v[0-9]+.2d, v[0-9]+.2d, 
> v[0-9]+.d\[[0-9]+\]} 3 { target aarch64_big_endian } } } */
> +/* { dg-final { scan-assembler-times {fmls v[0-9]+.2d, v[0-9]+.2d, 
> v[0-9]+.d\[[0-9]+\]} 2 { target aarch64_little_endian } } } */
> 
> 
> diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vfma.c 
> b/gcc/testsuite/gcc.target/aarch64/neon/vfma.c
> new file mode 100644
> index 00000000000..7de3e90b867
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/neon/vfma.c
> @@ -0,0 +1,220 @@
> +/* { dg-do compile } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +
> +#include "arm_neon_test.h"
> +
> +#define TEST_LANE(NAME, RET_TYPE, TYPE1, TYPE2, TYPE3)                       
>   \
> +  RET_TYPE test_##NAME (TYPE1 a, TYPE2 b, TYPE3 c)                           
>   \
> +  {                                                                          
>   \
> +    return NAME (a, b, c, VEC_LEN (c) - 1);                                  
>   \
> +  }
> +
> +/*
> +** test_vfma_f16:
> +** fmla v0\.4h, (v1\.4h, v2\.4h|v2\.4h, v1\.4h)
> +** ret
> +*/
> +TEST_UNIFORM_TERNARY (vfma_f16, float16x4_t)
> +
> +/*
> +** test_vfmaq_f16:
> +** fmla v0\.8h, (v1\.8h, v2\.8h|v2\.8h, v1\.8h)
> +** ret
> +*/
> +TEST_UNIFORM_TERNARY (vfmaq_f16, float16x8_t)
> +
> +/*
> +** test_vfma_f32:
> +** fmla v0\.2s, (v1\.2s, v2\.2s|v2\.2s, v1\.2s)
> +** ret
> +*/
> +TEST_UNIFORM_TERNARY (vfma_f32, float32x2_t)
> +
> +/*
> +** test_vfmaq_f32:
> +** fmla v0\.4s, (v1\.4s, v2\.4s|v2\.4s, v1\.4s)
> +** ret
> +*/
> +TEST_UNIFORM_TERNARY (vfmaq_f32, float32x4_t)
> +
> +/*
> +** test_vfma_f64:
> +** fmadd d0, (d1, d2|d2, d1), d0
> +** ret
> +*/
> +TEST_UNIFORM_TERNARY (vfma_f64, float64x1_t)
> +
> +/*
> +** test_vfmaq_f64:
> +** fmla v0\.2d, (v1\.2d, v2\.2d|v2\.2d, v1\.2d)
> +** ret
> +*/
> +TEST_UNIFORM_TERNARY (vfmaq_f64, float64x2_t)
> +
> +/*
> +** test_vfma_n_f16:
> +** fmla v0\.4h, v1\.4h, v2\.h\[0\]
> +** ret
> +*/
> +TEST_TERNARY (vfma_n_f16, float16x4_t, float16x4_t, float16x4_t, float16_t)
> +
> +/*
> +** test_vfmaq_n_f16:
> +** fmla v0\.8h, v1\.8h, v2\.h\[0\]
> +** ret
> +*/
> +TEST_TERNARY (vfmaq_n_f16, float16x8_t, float16x8_t, float16x8_t, float16_t)
> +
> +/*
> +** test_vfma_n_f32:
> +** fmla v0\.2s, v1\.2s, v2\.s\[0\]
> +** ret
> +*/
> +TEST_TERNARY (vfma_n_f32, float32x2_t, float32x2_t, float32x2_t, float32_t)
> +
> +/*
> +** test_vfmaq_n_f32:
> +** fmla v0\.4s, v1\.4s, v2\.s\[0\]
> +** ret
> +*/
> +TEST_TERNARY (vfmaq_n_f32, float32x4_t, float32x4_t, float32x4_t, float32_t)
> +
> +/*
> +** test_vfma_n_f64:
> +** fmadd d0, (d1, d2|d2, d1), d0
> +** ret
> +*/
> +TEST_TERNARY (vfma_n_f64, float64x1_t, float64x1_t, float64x1_t, float64_t)
> +
> +/*
> +** test_vfmaq_n_f64:
> +** fmla v0\.2d, v1\.2d, v2\.d\[0\]
> +** ret
> +*/
> +TEST_TERNARY (vfmaq_n_f64, float64x2_t, float64x2_t, float64x2_t, float64_t)
> +
> +/*
> +** test_vfma_lane_f16:
> +** fmla v0\.4h, v1\.4h, v2\.h\[3\]
> +** ret
> +*/
> +TEST_LANE (vfma_lane_f16, float16x4_t, float16x4_t, float16x4_t, float16x4_t)
> +
> +/*
> +** test_vfma_lane_f32:
> +** fmla v0\.2s, v1\.2s, v2\.s\[1\]
> +** ret
> +*/
> +TEST_LANE (vfma_lane_f32, float32x2_t, float32x2_t, float32x2_t, float32x2_t)
> +
> +/*
> +** test_vfma_lane_f64:
> +** fmadd d0, (d1, d2|d2, d1), d0
> +** ret
> +*/
> +TEST_LANE (vfma_lane_f64, float64x1_t, float64x1_t, float64x1_t, float64x1_t)
> +
> +/*
> +** test_vfma_laneq_f16:
> +** fmla v0\.4h, v1\.4h, v2\.h\[7\]
> +** ret
> +*/
> +TEST_LANE (vfma_laneq_f16, float16x4_t, float16x4_t, float16x4_t, 
> float16x8_t)
> +
> +/*
> +** test_vfma_laneq_f32:
> +** fmla v0\.2s, v1\.2s, v2\.s\[3\]
> +** ret
> +*/
> +TEST_LANE (vfma_laneq_f32, float32x2_t, float32x2_t, float32x2_t, 
> float32x4_t)
> +
> +/*
> +** test_vfma_laneq_f64:
> +** fmla d0, d1, v2\.d\[1\]
> +** ret
> +*/
> +TEST_LANE (vfma_laneq_f64, float64x1_t, float64x1_t, float64x1_t, 
> float64x2_t)
> +
> +/*
> +** test_vfmaq_lane_f16:
> +** fmla v0\.8h, v1\.8h, v2\.h\[3\]
> +** ret
> +*/
> +TEST_LANE (vfmaq_lane_f16, float16x8_t, float16x8_t, float16x8_t, 
> float16x4_t)
> +
> +/*
> +** test_vfmaq_lane_f32:
> +** fmla v0\.4s, v1\.4s, v2\.s\[1\]
> +** ret
> +*/
> +TEST_LANE (vfmaq_lane_f32, float32x4_t, float32x4_t, float32x4_t, 
> float32x2_t)
> +
> +/*
> +** test_vfmaq_lane_f64:
> +** fmla v0\.2d, v1\.2d, v2\.d\[0\]
> +** ret
> +*/
> +TEST_LANE (vfmaq_lane_f64, float64x2_t, float64x2_t, float64x2_t, 
> float64x1_t)
> +
> +/*
> +** test_vfmaq_laneq_f16:
> +** fmla v0\.8h, v1\.8h, v2\.h\[7\]
> +** ret
> +*/
> +TEST_LANE (vfmaq_laneq_f16, float16x8_t, float16x8_t, float16x8_t, 
> float16x8_t)
> +
> +/*
> +** test_vfmaq_laneq_f32:
> +** fmla v0\.4s, v1\.4s, v2\.s\[3\]
> +** ret
> +*/
> +TEST_LANE (vfmaq_laneq_f32, float32x4_t, float32x4_t, float32x4_t, 
> float32x4_t)
> +
> +/*
> +** test_vfmaq_laneq_f64:
> +** fmla v0\.2d, v1\.2d, v2\.d\[1\]
> +** ret
> +*/
> +TEST_LANE (vfmaq_laneq_f64, float64x2_t, float64x2_t, float64x2_t, 
> float64x2_t)
> +
> +/*
> +** test_vfmah_lane_f16:
> +** fmla h0, h1, v2\.h\[3\]
> +** ret
> +*/
> +TEST_LANE (vfmah_lane_f16, float16_t, float16_t, float16_t, float16x4_t)
> +
> +/*
> +** test_vfmah_laneq_f16:
> +** fmla h0, h1, v2\.h\[7\]
> +** ret
> +*/
> +TEST_LANE (vfmah_laneq_f16, float16_t, float16_t, float16_t, float16x8_t)
> +
> +/*
> +** test_vfmas_lane_f32:
> +** fmla s0, s1, v2\.s\[1\]
> +** ret
> +*/
> +TEST_LANE (vfmas_lane_f32, float32_t, float32_t, float32_t, float32x2_t)
> +
> +/*
> +** test_vfmas_laneq_f32:
> +** fmla s0, s1, v2\.s\[3\]
> +** ret
> +*/
> +TEST_LANE (vfmas_laneq_f32, float32_t, float32_t, float32_t, float32x4_t)
> +
> +/*
> +** test_vfmad_lane_f64:
> +** fmadd d0, (d1, d2|d2, d1), d0
> +** ret
> +*/
> +TEST_LANE (vfmad_lane_f64, float64_t, float64_t, float64_t, float64x1_t)
> +
> +/*
> +** test_vfmad_laneq_f64:
> +** fmla d0, d1, v2\.d\[1\]
> +** ret
> +*/
> +TEST_LANE (vfmad_laneq_f64, float64_t, float64_t, float64_t, float64x2_t)
> diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vfms.c 
> b/gcc/testsuite/gcc.target/aarch64/neon/vfms.c
> new file mode 100644
> index 00000000000..c5bd09d3a61
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/neon/vfms.c
> @@ -0,0 +1,220 @@
> +/* { dg-do compile } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +
> +#include "arm_neon_test.h"
> +
> +#define TEST_LANE(NAME, RET_TYPE, TYPE1, TYPE2, TYPE3)                       
>   \
> +  RET_TYPE test_##NAME (TYPE1 a, TYPE2 b, TYPE3 c)                           
>   \
> +  {                                                                          
>   \
> +    return NAME (a, b, c, VEC_LEN (c) - 1);                                  
>   \
> +  }
> +
> +/*
> +** test_vfms_f16:
> +** fmls v0\.4h, (v1\.4h, v2\.4h|v2\.4h, v1\.4h)
> +** ret
> +*/
> +TEST_UNIFORM_TERNARY (vfms_f16, float16x4_t)
> +
> +/*
> +** test_vfmsq_f16:
> +** fmls v0\.8h, (v1\.8h, v2\.8h|v2\.8h, v1\.8h)
> +** ret
> +*/
> +TEST_UNIFORM_TERNARY (vfmsq_f16, float16x8_t)
> +
> +/*
> +** test_vfms_f32:
> +** fmls v0\.2s, (v1\.2s, v2\.2s|v2\.2s, v1\.2s)
> +** ret
> +*/
> +TEST_UNIFORM_TERNARY (vfms_f32, float32x2_t)
> +
> +/*
> +** test_vfmsq_f32:
> +** fmls v0\.4s, (v1\.4s, v2\.4s|v2\.4s, v1\.4s)
> +** ret
> +*/
> +TEST_UNIFORM_TERNARY (vfmsq_f32, float32x4_t)
> +
> +/*
> +** test_vfms_f64:
> +** fmsub d0, (d1, d2|d2, d1), d0
> +** ret
> +*/
> +TEST_UNIFORM_TERNARY (vfms_f64, float64x1_t)
> +
> +/*
> +** test_vfmsq_f64:
> +** fmls v0\.2d, (v1\.2d, v2\.2d|v2\.2d, v1\.2d)
> +** ret
> +*/
> +TEST_UNIFORM_TERNARY (vfmsq_f64, float64x2_t)
> +
> +/*
> +** test_vfms_n_f16:
> +** fmls v0\.4h, v1\.4h, v2\.h\[0\]
> +** ret
> +*/
> +TEST_TERNARY (vfms_n_f16, float16x4_t, float16x4_t, float16x4_t, float16_t)
> +
> +/*
> +** test_vfmsq_n_f16:
> +** fmls v0\.8h, v1\.8h, v2\.h\[0\]
> +** ret
> +*/
> +TEST_TERNARY (vfmsq_n_f16, float16x8_t, float16x8_t, float16x8_t, float16_t)
> +
> +/*
> +** test_vfms_n_f32:
> +** fmls v0\.2s, v1\.2s, v2\.s\[0\]
> +** ret
> +*/
> +TEST_TERNARY (vfms_n_f32, float32x2_t, float32x2_t, float32x2_t, float32_t)
> +
> +/*
> +** test_vfmsq_n_f32:
> +** fmls v0\.4s, v1\.4s, v2\.s\[0\]
> +** ret
> +*/
> +TEST_TERNARY (vfmsq_n_f32, float32x4_t, float32x4_t, float32x4_t, float32_t)
> +
> +/*
> +** test_vfms_n_f64:
> +** fmsub d0, (d1, d2|d2, d1), d0
> +** ret
> +*/
> +TEST_TERNARY (vfms_n_f64, float64x1_t, float64x1_t, float64x1_t, float64_t)
> +
> +/*
> +** test_vfmsq_n_f64:
> +** fmls v0\.2d, v1\.2d, v2\.d\[0\]
> +** ret
> +*/
> +TEST_TERNARY (vfmsq_n_f64, float64x2_t, float64x2_t, float64x2_t, float64_t)
> +
> +/*
> +** test_vfms_lane_f16:
> +** fmls v0\.4h, v1\.4h, v2\.h\[3\]
> +** ret
> +*/
> +TEST_LANE (vfms_lane_f16, float16x4_t, float16x4_t, float16x4_t, float16x4_t)
> +
> +/*
> +** test_vfms_lane_f32:
> +** fmls v0\.2s, v1\.2s, v2\.s\[1\]
> +** ret
> +*/
> +TEST_LANE (vfms_lane_f32, float32x2_t, float32x2_t, float32x2_t, float32x2_t)
> +
> +/*
> +** test_vfms_lane_f64:
> +** fmsub d0, (d1, d2|d2, d1), d0
> +** ret
> +*/
> +TEST_LANE (vfms_lane_f64, float64x1_t, float64x1_t, float64x1_t, float64x1_t)
> +
> +/*
> +** test_vfms_laneq_f16:
> +** fmls v0\.4h, v1\.4h, v2\.h\[7\]
> +** ret
> +*/
> +TEST_LANE (vfms_laneq_f16, float16x4_t, float16x4_t, float16x4_t, 
> float16x8_t)
> +
> +/*
> +** test_vfms_laneq_f32:
> +** fmls v0\.2s, v1\.2s, v2\.s\[3\]
> +** ret
> +*/
> +TEST_LANE (vfms_laneq_f32, float32x2_t, float32x2_t, float32x2_t, 
> float32x4_t)
> +
> +/*
> +** test_vfms_laneq_f64:
> +** fmls d0, d1, v2\.d\[1\]
> +** ret
> +*/
> +TEST_LANE (vfms_laneq_f64, float64x1_t, float64x1_t, float64x1_t, 
> float64x2_t)
> +
> +/*
> +** test_vfmsq_lane_f16:
> +** fmls v0\.8h, v1\.8h, v2\.h\[3\]
> +** ret
> +*/
> +TEST_LANE (vfmsq_lane_f16, float16x8_t, float16x8_t, float16x8_t, 
> float16x4_t)
> +
> +/*
> +** test_vfmsq_lane_f32:
> +** fmls v0\.4s, v1\.4s, v2\.s\[1\]
> +** ret
> +*/
> +TEST_LANE (vfmsq_lane_f32, float32x4_t, float32x4_t, float32x4_t, 
> float32x2_t)
> +
> +/*
> +** test_vfmsq_lane_f64:
> +** fmls v0\.2d, v1\.2d, v2\.d\[0\]
> +** ret
> +*/
> +TEST_LANE (vfmsq_lane_f64, float64x2_t, float64x2_t, float64x2_t, 
> float64x1_t)
> +
> +/*
> +** test_vfmsq_laneq_f16:
> +** fmls v0\.8h, v1\.8h, v2\.h\[7\]
> +** ret
> +*/
> +TEST_LANE (vfmsq_laneq_f16, float16x8_t, float16x8_t, float16x8_t, 
> float16x8_t)
> +
> +/*
> +** test_vfmsq_laneq_f32:
> +** fmls v0\.4s, v1\.4s, v2\.s\[3\]
> +** ret
> +*/
> +TEST_LANE (vfmsq_laneq_f32, float32x4_t, float32x4_t, float32x4_t, 
> float32x4_t)
> +
> +/*
> +** test_vfmsq_laneq_f64:
> +** fmls v0\.2d, v1\.2d, v2\.d\[1\]
> +** ret
> +*/
> +TEST_LANE (vfmsq_laneq_f64, float64x2_t, float64x2_t, float64x2_t, 
> float64x2_t)
> +
> +/*
> +** test_vfmsh_lane_f16:
> +** fmls h0, h1, v2\.h\[3\]
> +** ret
> +*/
> +TEST_LANE (vfmsh_lane_f16, float16_t, float16_t, float16_t, float16x4_t)
> +
> +/*
> +** test_vfmsh_laneq_f16:
> +** fmls h0, h1, v2\.h\[7\]
> +** ret
> +*/
> +TEST_LANE (vfmsh_laneq_f16, float16_t, float16_t, float16_t, float16x8_t)
> +
> +/*
> +** test_vfmss_lane_f32:
> +** fmls s0, s1, v2\.s\[1\]
> +** ret
> +*/
> +TEST_LANE (vfmss_lane_f32, float32_t, float32_t, float32_t, float32x2_t)
> +
> +/*
> +** test_vfmss_laneq_f32:
> +** fmls s0, s1, v2\.s\[3\]
> +** ret
> +*/
> +TEST_LANE (vfmss_laneq_f32, float32_t, float32_t, float32_t, float32x4_t)
> +
> +/*
> +** test_vfmsd_lane_f64:
> +** fmsub d0, (d1, d2|d2, d1), d0
> +** ret
> +*/
> +TEST_LANE (vfmsd_lane_f64, float64_t, float64_t, float64_t, float64x1_t)
> +
> +/*
> +** test_vfmsd_laneq_f64:
> +** fmls d0, d1, v2\.d\[1\]
> +** ret
> +*/
> +TEST_LANE (vfmsd_laneq_f64, float64_t, float64_t, float64_t, float64x2_t)
> diff --git a/gcc/testsuite/gcc.target/aarch64/simd/pr99195_3.c 
> b/gcc/testsuite/gcc.target/aarch64/simd/pr99195_3.c
> index c751924e8d1..cc2b3887947 100644
> --- a/gcc/testsuite/gcc.target/aarch64/simd/pr99195_3.c
> +++ b/gcc/testsuite/gcc.target/aarch64/simd/pr99195_3.c
> @@ -3,7 +3,7 @@
>     the top half of the vector register and no explicit zeroing instructions
>     are emitted.  */
> /* { dg-do compile } */
> -/* { dg-options "-O" } */
> +/* { dg-options "-O -fno-trapping-math" } */
> 
> #include <arm_neon.h>
> 
> @@ -65,4 +65,3 @@ OPTHREE (float32, 2, 4, f32, mla_lane, fma_lane, fms_lane)
> 
> /* { dg-final { scan-assembler-not {\tfmov\t} } }  */
> /* { dg-final { scan-assembler-not {\tmov\t} } }  */
> -
> -- 
> 2.56.0
> 

Reply via email to