gcc/ChangeLog:
* config/aarch64/aarch64-neon-builtins-base.cc
(singleton_vector_p): New function.
(class gimple_fused_mla): New class.
* config/aarch64/aarch64-neon-builtins-base.def
(vfma, vfmaq, vfma_n, vfmaq_n, vfma_lane, vfma_laneq,
vfmaq_lane, vfmaq_laneq, vfms, vfmsq, vfms_n, vfmsq_n,
vfms_lane, vfms_laneq, vfmsq_lane, vfmsq_laneq): New function
declarations.
* config/aarch64/aarch64-simd.md (fmav1df4<vczle><vczbe>,
fnmav1df4<vczle><vczbe>): New insns.
(*aarch64_fma4_elt<mode><vczle><vczbe>): Match against HF
modes as well.
(*aarch64_fma4_elt_<vswap_width_name><mode><vczle><vczbe>):
Likewise.
(*aarch64_fnma4_elt<mode><vczle><vczbe>): Match against HF
modes, and permute first two argument operands to match the RTL
generated by `.FNMA`.
(*aarch64_fnma4_elt_<vswap_width_name><mode><vczle><vczbe>):
Likewise.
(*aarch64_fnma4_elt_from_dup<mode><vczle><vczbe>): Likewise.
(*aarch64_fnma4_elt_to_64v2df): Likewise.
* 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.
* config/arm/types.md (neon_fp_mla_h, neon_fp_mla_h_q,
neon_fp_mla_h_scalar, neon_fp_mla_h_scalar_q): New attrs.
gcc/testsuite/ChangeLog:
* gcc.target/aarch64/fmla_intrinsic_1.c: Rewrite `TEST_VMLA`
macro so that the choice of lane 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/neon/vfma.c: New test.
* gcc.target/aarch64/neon/vfms.c: New test.
---
.../aarch64/aarch64-neon-builtins-base.cc | 98 +++-
.../aarch64/aarch64-neon-builtins-base.def | 54 ++
gcc/config/aarch64/aarch64-simd.md | 122 +++--
gcc/config/aarch64/arm_neon.h | 500 ------------------
gcc/config/aarch64/iterators.md | 7 +
gcc/config/arm/types.md | 20 +-
.../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 ++++++++
10 files changed, 717 insertions(+), 574 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 37071c4aab8..ee29905e63b 100644
--- a/gcc/config/aarch64/aarch64-neon-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
@@ -45,6 +45,15 @@
#include "gimple-fold.h"
namespace aarch64_acle {
+/* Return true if VEC (a vector expression or vector type) is known to have a
+ single element. */
+bool
+singleton_vector_p (tree vec)
+{
+ tree type = TYPE_P (vec) ? vec : TREE_TYPE (vec);
+ return VECTOR_TYPE_P (type) && known_eq (TYPE_VECTOR_SUBPARTS (type), 1U);
+}
+
/* Build a cast expression, `(TYPE)EXPR`, if necessary to make an expression
with type TYPE. */
tree
@@ -101,7 +110,7 @@ build_lane_set (tree vec, tree index, tree elem)
tree
build_vec_dup (tree type, tree elem)
{
- return known_eq (TYPE_VECTOR_SUBPARTS (type), 1U)
+ return singleton_vector_p (type)
? fold_build1 (VIEW_CONVERT_EXPR, type, elem)
: fold_build1 (VEC_DUPLICATE_EXPR, type, elem);
}
@@ -224,7 +233,7 @@ struct gimple_combine : public gimple_function_base
auto elem_type = TREE_TYPE (arg_type);
auto ret_type = TREE_TYPE (f.lhs);
- if (known_eq (TYPE_VECTOR_SUBPARTS (arg_type), 1U))
+ if (singleton_vector_p (arg_type))
{
arg1 = f.force_val (fold_build1 (VIEW_CONVERT_EXPR, elem_type, arg1));
arg2 = f.force_val (fold_build1 (VIEW_CONVERT_EXPR, elem_type, arg2));
@@ -759,6 +768,72 @@ public:
}
};
+enum class fma_kind
+{
+ normal,
+ dup,
+ lane,
+};
+
+template <fma_kind kind, bool negate>
+class gimple_fused_mla : public gimple_function_base
+{
+public:
+ gimple *fold (gimple_folder &f) const override
+ {
+ tree add = gimple_call_arg (f.call, 0);
+ tree mul1 = gimple_call_arg (f.call, 1);
+ tree mul2 = gimple_call_arg (f.call, 2);
+ tree lane_index;
+ tree ret_type = TREE_TYPE (f.lhs);
+ tree ret = f.lhs;
+
+ auto mk_call = [] (auto mul1, auto mul2, auto add) {
+ return gimple_build_call_internal (negate ? IFN_FNMA : IFN_FMA, 3, mul1,
+ mul2, add);
+ };
+
+ switch (kind)
+ {
+ case fma_kind::normal:
+ break;
+
+ case fma_kind::dup:
+ mul2 = f.force_val (build_vec_dup (TREE_TYPE (mul1), mul2));
+ break;
+
+ case fma_kind::lane:
+ lane_index = gimple_call_arg (f.call, 3);
+ mul2 = f.force_val (build_lane_get (mul2, lane_index));
+
+ /* FIXME (Karl Meakin): Hack to get better codegen for `vmla_laneq_f64`.
+ Instead of building an unecessary VECTOR_DUP, call FMA with the
+ element type and then cast the result to a singleton vector. */
+ if (singleton_vector_p (ret_type) || SCALAR_FLOAT_TYPE_P (ret_type))
+ {
+ tree elem_type = TREE_TYPE (mul2);
+ add = f.force_val (build_cast (elem_type, add));
+ mul1 = f.force_val (build_cast (elem_type, mul1));
+ ret = create_tmp_var (elem_type);
+ auto call = mk_call (mul1, mul2, add);
+ gsi_insert_before (f.gsi, call, GSI_SAME_STMT);
+ gimple_call_set_lhs (call, ret);
+ return gimple_build_assign (f.lhs, f.force_val (
+ build_cast (ret_type, ret)));
+ }
+ else
+ mul2 = f.force_val (build_vec_dup (TREE_TYPE (mul1), mul2));
+ break;
+ }
+
+ auto call = mk_call (mul1, mul2, add);
+ gimple_call_set_lhs (call, ret);
+ return call;
+ }
+};
+template <fma_kind kind> using gimple_fma = gimple_fused_mla<kind, false>;
+template <fma_kind kind> using gimple_fms = gimple_fused_mla<kind, true>;
+
// Reinterpret
NEON_FUNCTION (vreinterpret, vreinterpretq, gimple_reinterpret,)
@@ -783,6 +858,25 @@ NEON_FUNCTION (vmla, vmlaq, vmla_n, vmlaq_n, vmla_lane,
vmla_laneq, vmlaq_lane,
NEON_FUNCTION (vmls, vmlsq, vmls_n, vmlsq_n, vmls_lane, vmls_laneq, vmlsq_lane,
vmlsq_laneq, gimple_mla, (MINUS_EXPR))
+// Multiply-accumulate (fused)
+NEON_FUNCTION (vfma, vfmaq, gimple_fma<fma_kind::normal>,);
+NEON_FUNCTION (vfma_n, vfmaq_n, gimple_fma<fma_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<fma_kind::lane>,);
+
+NEON_FUNCTION (vfms, vfmsq, gimple_fms<fma_kind::normal>,);
+NEON_FUNCTION (vfms_n, vfmsq_n, gimple_fms<fma_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<fma_kind::lane>,);
+
// Bitwise operations
NEON_FUNCTION (vand, vandq, gimple_expr, (BIT_AND_EXPR))
NEON_FUNCTION (vbic, vbicq, gimple_not_rhs, (BIT_AND_EXPR))
diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.def
b/gcc/config/aarch64/aarch64-neon-builtins-base.def
index d2ab46a3d95..49380ca24ec 100644
--- a/gcc/config/aarch64/aarch64-neon-builtins-base.def
+++ b/gcc/config/aarch64/aarch64-neon-builtins-base.def
@@ -96,6 +96,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.md
b/gcc/config/aarch64/aarch64-simd.md
index 0b824e73dbf..ba1b87e0a9a 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -3050,15 +3050,48 @@ (define_insn "fma<mode>4<vczle><vczbe>"
[(set_attr "type" "neon_fp_mla_<stype><q>")]
)
+(define_insn "fmav1df4<vczle><vczbe>"
+ [(set (match_operand:V1DF 0 "register_operand" "=w")
+ (fma:V1DF (match_operand:V1DF 3 "register_operand" "w")
+ (match_operand:V1DF 1 "register_operand" "%w")
+ (match_operand:V1DF 2 "register_operand" "w")))]
+ "TARGET_SIMD"
+ "fmadd\\t%d0, %d1, %d2, %d3"
+ [(set_attr "type" "neon_fp_mla_d_q")]
+)
+
+(define_insn "fnmav1df4<vczle><vczbe>"
+ [(set (match_operand:V1DF 0 "register_operand" "=w")
+ (fma:V1DF (neg:V1DF (match_operand:V1DF 3 "register_operand" "w"))
+ (match_operand:V1DF 1 "register_operand" "%w")
+ (match_operand:V1DF 2 "register_operand" "w")))]
+ "TARGET_SIMD"
+ "fmsub\\t%d0, %d1, %d2, %d3"
+ [(set_attr "type" "neon_fp_mla_d_q")]
+)
+
+(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"
+ "fmla\\t%<Vetype>0, %<Vetype>3, %1.<Vetype>[%2]"
+ [(set_attr "type" "neon_fp_mla_d_q")]
+)
+
(define_insn "*aarch64_fma4_elt<mode><vczle><vczbe>"
- [(set (match_operand:VDQF 0 "register_operand" "=w")
- (fma:VDQF
- (vec_duplicate:VDQF
+ [(set (match_operand:VHSDF 0 "register_operand" "=w")
+ (fma:VHSDF
+ (vec_duplicate:VHSDF
(vec_select:<VEL>
- (match_operand:VDQF 1 "register_operand" "<h_con>")
+ (match_operand:VHSDF 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")))]
+ (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]));
@@ -3068,14 +3101,14 @@ (define_insn "*aarch64_fma4_elt<mode><vczle><vczbe>"
)
(define_insn "*aarch64_fma4_elt_<vswap_width_name><mode><vczle><vczbe>"
- [(set (match_operand:VDQSF 0 "register_operand" "=w")
- (fma:VDQSF
- (vec_duplicate:VDQSF
+ [(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:VDQSF 3 "register_operand" "w")
- (match_operand:VDQSF 4 "register_operand" "0")))]
+ (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]));
@@ -3102,8 +3135,8 @@ (define_insn "*aarch64_fma4_elt_to_64v2df"
(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")))]
+ (match_operand:DF 3 "register_operand" "w")
+ (match_operand:DF 4 "register_operand" "0")))]
"TARGET_SIMD"
{
operands[2] = aarch64_endian_lane_rtx (V2DFmode, INTVAL (operands[2]));
@@ -3124,15 +3157,14 @@ (define_insn "fnma<mode>4<vczle><vczbe>"
)
(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
+ [(set (match_operand:VHSDF 0 "register_operand" "=w")
+ (fma:VHSDF
+ (neg:VHSDF (vec_duplicate:VHSDF
(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")))]
+ (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]));
@@ -3141,16 +3173,28 @@ (define_insn "*aarch64_fnma4_elt<mode><vczle><vczbe>"
[(set_attr "type" "neon_fp_mla_<Vetype>_scalar<q>")]
)
+(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"
+ "fmls\\t%<Vetype>0, %<Vetype>3, %1.<Vetype>[%2]"
+ [(set_attr "type" "neon_fp_mla_d_q")]
+)
+
(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
+ [(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:VDQSF 4 "register_operand" "0")))]
+ (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]));
@@ -3162,8 +3206,19 @@ (define_insn
"*aarch64_fnma4_elt_<vswap_width_name><mode><vczle><vczbe>"
(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"))
+ (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>_permuted"
+ [(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")))]
@@ -3175,11 +3230,10 @@ (define_insn
"*aarch64_fnma4_elt_from_dup<mode><vczle><vczbe>"
(define_insn "*aarch64_fnma4_elt_to_64v2df"
[(set (match_operand:DF 0 "register_operand" "=w")
(fma:DF
- (vec_select:DF
+ (neg: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"))
+ (parallel [(match_operand:SI 2 "immediate_operand")])))
+ (match_operand:DF 3 "register_operand" "w")
(match_operand:DF 4 "register_operand" "0")))]
"TARGET_SIMD"
{
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index 968609fcd4b..b499ed9361d 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -7990,352 +7990,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
@@ -19852,162 +19506,8 @@ vsubq_f16 (float16x8_t __a, float16x8_t __b)
return __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__))
vmulh_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 568786e3714..001a4734394 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/config/arm/types.md b/gcc/config/arm/types.md
index 7f8d83be410..45ec40f81c0 100644
--- a/gcc/config/arm/types.md
+++ b/gcc/config/arm/types.md
@@ -471,6 +471,10 @@ (define_attr "autodetect_type"
; neon_fp_mul_d
; neon_fp_mul_d_q
; neon_fp_mul_d_scalar_q
+; neon_fp_mla_h
+; neon_fp_mla_h_q
+; neon_fp_mla_h_scalar
+; neon_fp_mla_h_scalar_q
; neon_fp_mla_s
; neon_fp_mla_s_q
; neon_fp_mla_s_scalar
@@ -969,6 +973,10 @@ (define_attr "type"
neon_fp_mul_d_q,\
neon_fp_mul_d_scalar_q,\
\
+ neon_fp_mla_h,\
+ neon_fp_mla_h_q,\
+ neon_fp_mla_h_scalar,\
+ neon_fp_mla_h_scalar_q,\
neon_fp_mla_s,\
neon_fp_mla_s_q,\
neon_fp_mla_s_scalar,\
@@ -1154,12 +1162,12 @@ (define_attr "is_neon_type" "yes,no"
neon_fp_recpx_d_q, neon_fp_rsqrte_s, neon_fp_rsqrte_s_q,\
neon_fp_rsqrte_d, neon_fp_rsqrte_d_q, neon_fp_rsqrts_s,\
neon_fp_rsqrts_s_q, neon_fp_rsqrts_d, neon_fp_rsqrts_d_q,\
- neon_fp_mul_s, neon_fp_mul_s_q, neon_fp_mul_s_scalar,\
- neon_fp_mul_s_scalar_q, neon_fp_mul_d, neon_fp_mul_d_q,\
- neon_fp_mul_d_scalar_q, neon_fp_mla_s, neon_fp_mla_s_q,\
- neon_fp_mla_s_scalar, neon_fp_mla_s_scalar_q, neon_fp_mla_d,\
- neon_fp_mla_d_q, neon_fp_mla_d_scalar_q, neon_fp_sqrt_s,\
- neon_fp_sqrt_s_q, neon_fp_sqrt_d, neon_fp_sqrt_d_q,\
+ neon_fp_mul_s, neon_fp_mul_s_q, neon_fp_mul_s_scalar,
neon_fp_mul_s_scalar_q,\
+ neon_fp_mul_d, neon_fp_mul_d_q,
neon_fp_mul_d_scalar_q,\
+ neon_fp_mla_h, neon_fp_mla_h_q, neon_fp_mla_h_scalar,
neon_fp_mla_h_scalar_q,\
+ neon_fp_mla_s, neon_fp_mla_s_q, neon_fp_mla_s_scalar,
neon_fp_mla_s_scalar_q,\
+ neon_fp_mla_d, neon_fp_mla_d_q,
neon_fp_mla_d_scalar_q,\
+ neon_fp_sqrt_s, neon_fp_sqrt_s_q, neon_fp_sqrt_d, neon_fp_sqrt_d_q,\
neon_fp_div_s, neon_fp_div_s_q, neon_fp_div_d, neon_fp_div_d_q,
crypto_aese,\
neon_fcadd, neon_fcmla, \
crypto_aesmc, crypto_sha1_xor, crypto_sha1_fast, crypto_sha1_slow,\
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)
--
2.51.0