Hi Kyrill,

> -----Original Message-----
> From: [email protected] <[email protected]>
> Sent: 06 October 2026 15:02
> To: [email protected]
> Cc: Kyrylo Tkachov <[email protected]>; Tamar Christina
> <[email protected]>; Wilco Dijkstra <[email protected]>
> Subject: [PATCH] aarch64: Use standard RTL for FADDP
> 
> From: Kyrylo Tkachov <[email protected]>
> 
> The FADDP patterns use UNSPEC_FADDV, so RTL optimizations cannot see that
> FADDP adds pairs of elements.  ADDP already uses standard RTL.  Describe
> FADDP in the same way and let it share the ADDP patterns, which get
> parameterized names.
> 
> For two-lane vectors, FADDP and the scalar FADDP reduction add the two
> elements of each input.  RTL simplification describes the low element of
> a vector as a lowpart subreg, so use that form for these sums:
> 
>   (plus:SF (vec_select:SF (reg:V2SF x) (parallel [(const_int 1)]))
>          (subreg:SF (reg:V2SF x) 0))
> 
> The insn condition checks that the subreg is the lowpart of the vector
> operand.  The instruction only reads the vector operand.
> 
> Combine can now use FADDP for the sum of the two elements of a vector, and
> pack two such sums into one FADDP.  For example, with -O2:
> 
>   float32x2_t
>   f (float32x2_t a, float32x2_t b)
>   {
>     return (float32x2_t) { vaddv_f32 (a), vaddv_f32 (b) };
>   }
> 
> Before:
>       faddp   s1, v1.2s
>       faddp   s0, v0.2s
>       zip1    v0.2s, v0.2s, v1.2s
> 
> After:
>       faddp   v0.2s, v0.2s, v1.2s
> 
> For x[0] + x[1], where x is a float32x2_t:
> 
> Before:
>       dup     s31, v0.s[1]
>       fadd    s0, s31, s0
> 
> After:
>       faddp   s0, v0.2s
> 
> Tests check lane extraction from FADDP results for both byte orders.  The
> runtime test also passes under big-endian QEMU.
> 
> Bootstrapped and tested on aarch64-none-linux-gnu.
> Ok for trunk?
> Thanks,
> Kyrill
> 
> Cc: Tamar Christina <[email protected]>
> Cc: Wilco Dijkstra <[email protected]>
> 
> gcc/ChangeLog:
> 
>       * config/aarch64/aarch64-protos.h (aarch64_simd_lowpart_of_p):
>       Declare.
>       * config/aarch64/aarch64.cc (aarch64_simd_lowpart_of_p): New
>       function.
>       * config/aarch64/iterators.md (VD_ADDP, VQ_ADDP, VDQ_ADDP):
> New mode
>       iterators.
>       (addp_type): New mode attribute.
>       * config/aarch64/aarch64-simd.md
> (aarch64_faddp<mode><vczle><vczbe>):
>       Remove.
>       (reduc_plus_scal_<mode>): Use standard RTL for V2F.
>       (aarch64_faddp_scal<mode>): New pattern.
>       (aarch64_addp<mode>_insn): Rename to...
>       (@aarch64_addp<mode>_concat): ...this.  Handle FADDP.
>       (aarch64_addp<mode><vczle><vczbe>_insn): Rename to...
>       (@aarch64_addp<mode>_select<vczle><vczbe>): ...this.  Handle
> FADDP.
>       (@aarch64_faddp_scal_pair<mode><vczle><vczbe>): New pattern.
>       (*aarch64_addp_same_reg<mode>): Handle FADDP.
>       (aarch64_addp<mode>): Rename to...
>       (aarch64_<f>addp<mode>): ...this.  Handle FADDP.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.target/aarch64/faddp-concat-1.c: New test.
>       * gcc.target/aarch64/faddp-concat-3.c: Likewise.
>       * gcc.target/aarch64/faddp-concat-be.c: Likewise.
>       * gcc.target/aarch64/simd/faddp_lane_1.c: Likewise.
>       * gcc.target/aarch64/simd/faddp_lane_2.c: Likewise.
>       * gcc.target/aarch64/simd/faddp_reinterpret_1.c: Likewise.
> 
> Signed-off-by: Kyrylo Tkachov <[email protected]>
> ---
>  gcc/config/aarch64/aarch64-protos.h           |   1 +
>  gcc/config/aarch64/aarch64-simd.md            | 183 ++++++++++++------
>  gcc/config/aarch64/aarch64.cc                 |   9 +
>  gcc/config/aarch64/iterators.md               |  20 ++
>  .../gcc.target/aarch64/faddp-concat-1.c       |  64 ++++++
>  .../gcc.target/aarch64/faddp-concat-3.c       |  25 +++
>  .../gcc.target/aarch64/faddp-concat-be.c      |  51 +++++
>  .../gcc.target/aarch64/simd/faddp_lane_1.c    |  76 ++++++++
>  .../gcc.target/aarch64/simd/faddp_lane_2.c    |  53 +++++
>  .../aarch64/simd/faddp_reinterpret_1.c        |  51 +++++
>  10 files changed, 471 insertions(+), 62 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/faddp-concat-1.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/faddp-concat-3.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/faddp-concat-be.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/simd/faddp_lane_1.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/simd/faddp_lane_2.c
>  create mode 100644
> gcc/testsuite/gcc.target/aarch64/simd/faddp_reinterpret_1.c
> 
> diff --git a/gcc/config/aarch64/aarch64-protos.h
> b/gcc/config/aarch64/aarch64-protos.h
> index e8ae3d42794..b825ff5b584 100644
> --- a/gcc/config/aarch64/aarch64-protos.h
> +++ b/gcc/config/aarch64/aarch64-protos.h
> @@ -963,6 +963,7 @@ bool aarch64_regno_ok_for_index_p (int, bool);
>  bool aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT
> *fail);
>  bool aarch64_simd_check_vect_par_cnst_half (rtx op, machine_mode mode,
>                                           bool high);
> +bool aarch64_simd_lowpart_of_p (rtx, rtx);
>  bool aarch64_parallel_select_half_p (machine_mode, rtx);
>  bool aarch64_pars_overlap_p (rtx, rtx);
>  bool aarch64_simd_scalar_immediate_valid_for_move (rtx, scalar_int_mode);
> diff --git a/gcc/config/aarch64/aarch64-simd.md
> b/gcc/config/aarch64/aarch64-simd.md
> index f928c5958cd..e1ce90bfafb 100644
> --- a/gcc/config/aarch64/aarch64-simd.md
> +++ b/gcc/config/aarch64/aarch64-simd.md
> @@ -3760,16 +3760,6 @@
> 
>  ;; 'across lanes' add.
> 
> -(define_insn "aarch64_faddp<mode><vczle><vczbe>"
> - [(set (match_operand:VHSDF 0 "register_operand" "=w")
> -       (unspec:VHSDF [(match_operand:VHSDF 1 "register_operand" "w")
> -                   (match_operand:VHSDF 2 "register_operand" "w")]
> -     UNSPEC_FADDV))]
> - "TARGET_SIMD"
> - "faddp\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
> -  [(set_attr "type" "neon_fp_reduc_add_<stype><q>")]
> -)
> -
>  (define_insn "reduc_plus_scal_<mode>"
>   [(set (match_operand:<VEL> 0 "register_operand" "=w")
>         (unspec:<VEL> [(match_operand:VDQV 1 "register_operand" "w")]
> @@ -3799,12 +3789,31 @@
>    [(set_attr "type" "neon_reduc_add<VDQV_E:q>")]
>  )
> 
> -(define_insn "reduc_plus_scal_<mode>"
> - [(set (match_operand:<VEL> 0 "register_operand" "=w")
> -       (unspec:<VEL> [(match_operand:V2F 1 "register_operand" "w")]
> -                UNSPEC_FADDV))]
> - "TARGET_SIMD"
> - "faddp\\t%<Vetype>0, %1.<Vtype>"
> +(define_expand "reduc_plus_scal_<mode>"
> +  [(match_operand:<VEL> 0 "register_operand")
> +   (match_operand:V2F 1 "register_operand")]
> +  "TARGET_SIMD"
> +  {
> +    rtx hi = aarch64_gen_stepped_int_parallel (1, ENDIAN_LANE_N (2, 1), 1);
> +    rtx x = force_reg (<MODE>mode, operands[1]);
> +    emit_insn (gen_aarch64_faddp_scal<mode> (operands[0], x, hi,
> +                                         gen_lowpart (<VEL>mode, x)));
> +    DONE;
> +  }
> +)
> +
> +;; The sum of the two elements of a vector.  RTL simplification describes
> +;; the low element as a lowpart of the vector, so operand 3 is that lowpart
> +;; of operand 1.
> +(define_insn "aarch64_faddp_scal<mode>"
> +  [(set (match_operand:<VEL> 0 "register_operand" "=w")
> +     (plus:<VEL>
> +       (vec_select:<VEL>
> +         (match_operand:V2F 1 "register_operand" "w")
> +         (match_operand:V2F 2 "vect_par_cnst_hi_half"))
> +       (match_operand:<VEL> 3 "register_operand" "w")))]
> +  "TARGET_SIMD && aarch64_simd_lowpart_of_p (operands[3],
> operands[1])"
> +  "faddp\t%<Vetype>0, %1.<Vtype>"
>    [(set_attr "type" "neon_fp_reduc_add_<Vetype><q>")]
>  )
> 
> @@ -8304,27 +8313,27 @@
>    [(set_attr "type" "neon_fp_compare_<stype><q>")]
>  )
> 
> -;; addp
> +;; addp and faddp
> 
> -;; ADDP with two registers semantically concatenates them and performs
> -;; a pairwise addition on the result.  For 128-bit input modes represent this
> -;; as a concatenation of the pairwise addition results of the two input
> -;; registers.  This allow us to avoid using intermediate 256-bit modes.
> -;; The RTL uses GCC's lane numbering, so on big-endian targets operand 1
> -;; provides the architecturally high half of the result.
> -(define_insn "aarch64_addp<mode>_insn"
> -  [(set (match_operand:VQ_I 0 "register_operand" "=w")
> -     (vec_concat:VQ_I
> +;; ADDP and FADDP with two registers semantically concatenate them and
> +;; perform a pairwise addition on the result.  For 128-bit input modes
> +;; represent this as a concatenation of the pairwise addition results of the
> +;; two input registers.  This allows us to avoid using intermediate 256-bit
> +;; modes.  The RTL uses GCC's lane numbering, so on big-endian targets
> +;; operand 1 provides the architecturally high half of the result.
> +(define_insn "@aarch64_addp<mode>_concat"
> +  [(set (match_operand:VQ_ADDP 0 "register_operand" "=w")
> +     (vec_concat:VQ_ADDP
>         (plus:<VHALF>
>           (vec_select:<VHALF>
> -           (match_operand:VQ_I 1 "register_operand" "w")
> -           (match_operand:VQ_I 3 "vect_par_cnst_even_or_odd_half"))
> +           (match_operand:VQ_ADDP 1 "register_operand" "w")
> +           (match_operand:VQ_ADDP 3 "vect_par_cnst_even_or_odd_half"))
>           (vec_select:<VHALF>
>             (match_dup 1)
> -           (match_operand:VQ_I 4 "vect_par_cnst_even_or_odd_half")))
> +           (match_operand:VQ_ADDP 4
> "vect_par_cnst_even_or_odd_half")))
>         (plus:<VHALF>
>           (vec_select:<VHALF>
> -           (match_operand:VQ_I 2 "register_operand" "w")
> +           (match_operand:VQ_ADDP 2 "register_operand" "w")
>             (match_dup 3))
>           (vec_select:<VHALF>
>             (match_dup 2)
> @@ -8332,26 +8341,27 @@
>    "TARGET_SIMD && !rtx_equal_p (operands[3], operands[4])"
>    {
>      if (BYTES_BIG_ENDIAN)
> -      return "addp\t%<v>0<Vmtype>, %<v>2<Vmtype>, %<v>1<Vmtype>";
> -    return "addp\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>";
> +      return "<f>addp\t%<v>0<Vmtype>, %<v>2<Vmtype>, %<v>1<Vmtype>";
> +    return "<f>addp\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>";
>    }
> -  [(set_attr "type" "neon_reduc_add<q>")]
> +  [(set_attr "type" "<addp_type>")]
>  )
> 
> -;; For 64-bit input modes an ADDP is represented as a concatenation
> +;; For 64-bit input modes an ADDP or FADDP is represented as a
> concatenation
>  ;; of the input registers into an 128-bit register which is then fed
>  ;; into a pairwise add.  That way we avoid having to create intermediate
> -;; 32-bit vector modes.  As above, operand 1 provides the architecturally
> -;; high half of the result on big-endian targets.
> -(define_insn "aarch64_addp<mode><vczle><vczbe>_insn"
> -  [(set (match_operand:VD_BHSI 0 "register_operand" "=w")
> -     (plus:VD_BHSI
> -       (vec_select:VD_BHSI
> +;; 32-bit vector modes.  vpadd_f32 uses @aarch64_faddp_scal_pair<mode>
> +;; instead.  As above, operand 1 provides the architecturally high half of
> +;; the result on big-endian targets.
> +(define_insn "@aarch64_addp<mode>_select<vczle><vczbe>"
> +  [(set (match_operand:VD_ADDP 0 "register_operand" "=w")
> +     (plus:VD_ADDP
> +       (vec_select:VD_ADDP
>           (vec_concat:<VDBL>
> -           (match_operand:VD_BHSI 1 "register_operand" "w")
> -           (match_operand:VD_BHSI 2 "register_operand" "w"))
> +           (match_operand:VD_ADDP 1 "register_operand" "w")
> +           (match_operand:VD_ADDP 2 "register_operand" "w"))
>           (match_operand:<VDBL> 3 "vect_par_cnst_even_or_odd_half"))
> -       (vec_select:VD_BHSI
> +       (vec_select:VD_ADDP
>           (vec_concat:<VDBL>
>             (match_dup 1)
>             (match_dup 2))
> @@ -8359,10 +8369,39 @@
>    "TARGET_SIMD && !rtx_equal_p (operands[3], operands[4])"
>    {
>      if (BYTES_BIG_ENDIAN)
> -      return "addp\t%<v>0<Vmtype>, %<v>2<Vmtype>, %<v>1<Vmtype>";
> -    return "addp\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>";
> +      return "<f>addp\t%<v>0<Vmtype>, %<v>2<Vmtype>, %<v>1<Vmtype>";
> +    return "<f>addp\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>";
> +  }
> +  [(set_attr "type" "<addp_type>")]
> +)
> +
> +;; FADDP of two-lane vectors, represented as the concatenation of the sums
> of
> +;; the two elements of each input.  RTL simplification describes the low
> +;; element of a vector as a lowpart of the vector, so operands 4 and 5 are
> +;; those lowparts of operands 1 and 2.  As above, operand 1 provides the
> +;; architecturally high half of the result on big-endian targets.
> +(define_insn "@aarch64_faddp_scal_pair<mode><vczle><vczbe>"
> +  [(set (match_operand:V2F 0 "register_operand" "=w")
> +     (vec_concat:V2F
> +       (plus:<VEL>
> +         (vec_select:<VEL>
> +           (match_operand:V2F 1 "register_operand" "w")
> +           (match_operand:V2F 3 "vect_par_cnst_hi_half"))
> +         (match_operand:<VEL> 4 "register_operand" "w"))
> +       (plus:<VEL>
> +         (vec_select:<VEL>
> +           (match_operand:V2F 2 "register_operand" "w")
> +           (match_dup 3))
> +         (match_operand:<VEL> 5 "register_operand" "w"))))]
> +  "TARGET_SIMD
> +   && aarch64_simd_lowpart_of_p (operands[4], operands[1])
> +   && aarch64_simd_lowpart_of_p (operands[5], operands[2])"
> +  {
> +    if (BYTES_BIG_ENDIAN)
> +      return "faddp\t%0.<Vtype>, %2.<Vtype>, %1.<Vtype>";
> +    return "faddp\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>";
>    }
> -  [(set_attr "type" "neon_reduc_add<q>")]
> +  [(set_attr "type" "<addp_type>")]
>  )
> 
>  ;; A common usecase of 64-bit ADDP is to have both operands come from the
> same
> @@ -8372,11 +8411,11 @@
>    [(set (match_operand:<VHALF> 0 "register_operand" "=w")
>       (plus:<VHALF>
>         (vec_select:<VHALF>
> -         (match_operand:VQ_I 1 "register_operand" "w")
> -         (match_operand:VQ_I 2 "vect_par_cnst_even_or_odd_half"))
> +         (match_operand:VQ_ADDP 1 "register_operand" "w")
> +         (match_operand:VQ_ADDP 2 "vect_par_cnst_even_or_odd_half"))
>         (vec_select:<VHALF>
>           (match_dup 1)
> -         (match_operand:VQ_I 3 "vect_par_cnst_even_or_odd_half"))))]
> +         (match_operand:VQ_ADDP 3
> "vect_par_cnst_even_or_odd_half"))))]
>    "TARGET_SIMD && !rtx_equal_p (operands[2], operands[3])"
>    "#"
>    "&& 1"
> @@ -8388,29 +8427,49 @@
>      else
>        scratch = lowpart_subreg (<MODE>mode, operands[0], <VHALF>mode);
> 
> -    emit_insn (gen_aarch64_addp<mode>_insn (scratch, operands[1],
> operands[1],
> -                                         operands[2], operands[3]));
> +    emit_insn (gen_aarch64_addp_concat (<MODE>mode, scratch,
> operands[1],
> +                                     operands[1], operands[2],
> +                                     operands[3]));
>      emit_move_insn (operands[0], gen_lowpart (<VHALF>mode, scratch));
>      DONE;
>    }
>  )
> 
> -(define_expand "aarch64_addp<mode>"
> -  [(match_operand:VDQ_I 0 "register_operand")
> -   (match_operand:VDQ_I 1 "register_operand")
> -   (match_operand:VDQ_I 2 "register_operand")]
> +(define_expand "aarch64_<f>addp<mode>"
> +  [(match_operand:VDQ_ADDP 0 "register_operand")
> +   (match_operand:VDQ_ADDP 1 "register_operand")
> +   (match_operand:VDQ_ADDP 2 "register_operand")]
>    "TARGET_SIMD"
>    {
> -    int nunits = GET_MODE_NUNITS (<MODE>mode).to_constant ();
> -    if (known_eq (GET_MODE_BITSIZE (<MODE>mode), 128))
> -      nunits /= 2;
> -    rtx par_even = aarch64_gen_stepped_int_parallel (nunits, 0, 2);
> -    rtx par_odd = aarch64_gen_stepped_int_parallel (nunits, 1, 2);
>      /* The intrinsic uses architectural lane numbering.  */
>      if (BYTES_BIG_ENDIAN)
>        std::swap (operands[1], operands[2]);
> -    emit_insn (gen_aarch64_addp<mode>_insn (operands[0], operands[1],
> -                                         operands[2], par_even, par_odd));
> +    int nunits = GET_MODE_NUNITS (<MODE>mode).to_constant ();
> +    if (nunits == 2 && FLOAT_MODE_P (<MODE>mode))
> +      {
> +     rtx hi = aarch64_gen_stepped_int_parallel (1, ENDIAN_LANE_N (2, 1),
> 1);
> +     rtx x = force_reg (<MODE>mode, operands[1]);
> +     rtx y = force_reg (<MODE>mode, operands[2]);
> +     emit_insn (gen_aarch64_faddp_scal_pair (<MODE>mode,
> operands[0], x, y,
> +                                             hi, gen_lowpart (<VEL>mode,
> x),
> +                                             gen_lowpart (<VEL>mode,
> y)));
> +      }
> +    else if (known_eq (GET_MODE_BITSIZE (<MODE>mode), 128))
> +      {
> +     rtx even = aarch64_gen_stepped_int_parallel (nunits / 2, 0, 2);
> +     rtx odd = aarch64_gen_stepped_int_parallel (nunits / 2, 1, 2);
> +     emit_insn (gen_aarch64_addp_concat (<MODE>mode, operands[0],
> +                                         operands[1], operands[2], even,
> +                                         odd));
> +      }
> +    else
> +      {
> +     rtx even = aarch64_gen_stepped_int_parallel (nunits, 0, 2);
> +     rtx odd = aarch64_gen_stepped_int_parallel (nunits, 1, 2);
> +     emit_insn (gen_aarch64_addp_select (<MODE>mode, operands[0],
> +                                         operands[1], operands[2], even,
> +                                         odd));
> +      }
>      DONE;
>    }

Minor nit, I think I preferred the old approach of nunit /2 for the 128 bits 
case
better.

Patch is OK with that change.

Thanks,
Tamar

>  )
> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
> index 6693cec98bd..d7b5775a66d 100644
> --- a/gcc/config/aarch64/aarch64.cc
> +++ b/gcc/config/aarch64/aarch64.cc
> @@ -25552,6 +25552,15 @@ aarch64_simd_check_vect_par_cnst_half (rtx
> op, machine_mode mode,
>    return true;
>  }
> 
> +/* Return true if X is the low element of vector V, in the lowpart form
> +   that RTL simplification uses for it.  */
> +
> +bool
> +aarch64_simd_lowpart_of_p (rtx x, rtx v)
> +{
> +  return rtx_equal_p (x, lowpart_subreg (GET_MODE (x), v, GET_MODE (v)));
> +}
> +
>  /* Return a PARALLEL containing NELTS elements, with element I equal
>     to BASE + I * STEP.  */
> 
> diff --git a/gcc/config/aarch64/iterators.md
> b/gcc/config/aarch64/iterators.md
> index 568786e3714..66db3f4a5fd 100644
> --- a/gcc/config/aarch64/iterators.md
> +++ b/gcc/config/aarch64/iterators.md
> @@ -238,6 +238,15 @@
>  ;; Advanced SIMD Float modes with 2 elements.
>  (define_mode_iterator V2F [V2SF V2DF])
> 
> +;; 64-bit modes of ADDP and FADDP.
> +(define_mode_iterator VD_ADDP [VD_BHSI (V4HF
> "TARGET_SIMD_F16INST") V2SF])
> +
> +;; 128-bit modes of ADDP and FADDP.
> +(define_mode_iterator VQ_ADDP [VQ_I (V8HF "TARGET_SIMD_F16INST")
> V4SF V2DF])
> +
> +;; Modes of ADDP and FADDP.
> +(define_mode_iterator VDQ_ADDP [VDQ_I VHSDF])
> +
>  ;; All Advanced SIMD modes on which we support any arithmetic operations.
>  (define_mode_iterator VALL [V8QI V16QI V4HI V8HI V2SI V4SI V2DI V2SF
> V4SF V2DF])
> 
> @@ -2715,6 +2724,17 @@
>                    (V2SF "f") (V4SF  "f")
>                    (V2DF "f") (DF    "f")])
> 
> +;; The type of ADDP and FADDP.
> +(define_mode_attr addp_type [(V8QI "neon_reduc_add") (V16QI
> "neon_reduc_add_q")
> +                          (V4HI "neon_reduc_add") (V8HI
> "neon_reduc_add_q")
> +                          (V2SI "neon_reduc_add") (V4SI
> "neon_reduc_add_q")
> +                          (V2DI "neon_reduc_add_q")
> +                          (V4HF "neon_fp_reduc_add_s")
> +                          (V8HF "neon_fp_reduc_add_s_q")
> +                          (V2SF "neon_fp_reduc_add_s")
> +                          (V4SF "neon_fp_reduc_add_s_q")
> +                          (V2DF "neon_fp_reduc_add_d_q")])
> +
>  ;; Defined to '_fp' for types whose element type is a float type.
>  (define_mode_attr fp [(V8QI "")  (V16QI "")
>                     (V4HI "")  (V8HI  "")
> diff --git a/gcc/testsuite/gcc.target/aarch64/faddp-concat-1.c
> b/gcc/testsuite/gcc.target/aarch64/faddp-concat-1.c
> new file mode 100644
> index 00000000000..8b5f69cd6e2
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/faddp-concat-1.c
> @@ -0,0 +1,64 @@
> +/* { dg-do compile } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +/* { dg-options "-O2" } */
> +
> +#include <arm_neon.h>
> +
> +/*
> +** pair_f32: { target aarch64_little_endian }
> +**   faddp\tv0\.2s, v0\.2s, v1\.2s
> +**   ret
> +*/
> +/*
> +** pair_f32: { target aarch64_big_endian }
> +**   faddp\tv0\.2s, v1\.2s, v0\.2s
> +**   ret
> +*/
> +__attribute__ ((noipa)) float32x2_t
> +pair_f32 (float32x2_t a, float32x2_t b)
> +{
> +  return (float32x2_t) { vaddv_f32 (a), vaddv_f32 (b) };
> +}
> +
> +/*
> +** pair_f64: { target aarch64_little_endian }
> +**   faddp\tv0\.2d, v0\.2d, v1\.2d
> +**   ret
> +*/
> +/*
> +** pair_f64: { target aarch64_big_endian }
> +**   faddp\tv0\.2d, v1\.2d, v0\.2d
> +**   ret
> +*/
> +__attribute__ ((noipa)) float64x2_t
> +pair_f64 (float64x2_t a, float64x2_t b)
> +{
> +  return (float64x2_t) { vaddvq_f64 (a), vaddvq_f64 (b) };
> +}
> +
> +/*
> +** pair_mixed:       { target aarch64_little_endian }
> +**   faddp\tv0\.2s, v0\.2s, v1\.2s
> +**   ret
> +*/
> +/*
> +** pair_mixed:       { target aarch64_big_endian }
> +**   faddp\tv0\.2s, v1\.2s, v0\.2s
> +**   ret
> +*/
> +__attribute__ ((noipa)) float32x2_t
> +pair_mixed (float32x2_t a, float32x2_t b)
> +{
> +  return (float32x2_t) { vaddv_f32 (a), b[0] + b[1] };
> +}
> +
> +/*
> +** sum_lanes:
> +**   faddp\ts0, v0\.2s
> +**   ret
> +*/
> +__attribute__ ((noipa)) float32_t
> +sum_lanes (float32x2_t a)
> +{
> +  return a[0] + a[1];
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/faddp-concat-3.c
> b/gcc/testsuite/gcc.target/aarch64/faddp-concat-3.c
> new file mode 100644
> index 00000000000..3fcaa9f0935
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/faddp-concat-3.c
> @@ -0,0 +1,25 @@
> +/* { dg-do compile } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +/* { dg-options "-O2" } */
> +
> +#include <arm_neon.h>
> +
> +/*
> +** shared_reductions:
> +**   faddp\ts[0-9]+, v[0-9]+\.2s
> +**   faddp\ts[0-9]+, v[0-9]+\.2s
> +**   (?:str|zip1|ins)\t[^\n]+
> +**   (?:str|zip1|ins)\t[^\n]+
> +**   (?:str|zip1|ins)\t[^\n]+
> +**   ret
> +*/
> +float32x2_t
> +shared_reductions (float32x2_t a, float32x2_t b,
> +                volatile float *p, volatile float *q)
> +{
> +  float x = vaddv_f32 (a);
> +  float y = vaddv_f32 (b);
> +  *p = x;
> +  *q = y;
> +  return (float32x2_t) { x, y };
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/faddp-concat-be.c
> b/gcc/testsuite/gcc.target/aarch64/faddp-concat-be.c
> new file mode 100644
> index 00000000000..84b7a08fbd1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/faddp-concat-be.c
> @@ -0,0 +1,51 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target aarch64_mbig_endian } */
> +/* Avoid a dependence on big-endian C library headers.  */
> +/* { dg-options "-O2 -mbig-endian -ffreestanding" } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +
> +#include <arm_neon.h>
> +
> +/*
> +** pair_f32:
> +**   faddp\tv0\.2s, v1\.2s, v0\.2s
> +**   ret
> +*/
> +float32x2_t
> +pair_f32 (float32x2_t a, float32x2_t b)
> +{
> +  return (float32x2_t) { vaddv_f32 (a), vaddv_f32 (b) };
> +}
> +
> +/*
> +** pair_f64:
> +**   faddp\tv0\.2d, v1\.2d, v0\.2d
> +**   ret
> +*/
> +float64x2_t
> +pair_f64 (float64x2_t a, float64x2_t b)
> +{
> +  return (float64x2_t) { vaddvq_f64 (a), vaddvq_f64 (b) };
> +}
> +
> +/*
> +** pair_mixed:
> +**   faddp\tv0\.2s, v1\.2s, v0\.2s
> +**   ret
> +*/
> +float32x2_t
> +pair_mixed (float32x2_t a, float32x2_t b)
> +{
> +  return (float32x2_t) { vaddv_f32 (a), b[0] + b[1] };
> +}
> +
> +/*
> +** sum_lanes:
> +**   faddp\ts0, v0\.2s
> +**   ret
> +*/
> +float32_t
> +sum_lanes (float32x2_t a)
> +{
> +  return a[0] + a[1];
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/simd/faddp_lane_1.c
> b/gcc/testsuite/gcc.target/aarch64/simd/faddp_lane_1.c
> new file mode 100644
> index 00000000000..5ae2231697f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/simd/faddp_lane_1.c
> @@ -0,0 +1,76 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2" } */
> +
> +#include <arm_neon.h>
> +
> +__attribute__ ((noipa)) float32_t
> +lane0_q (float32x4_t a, float32x4_t b)
> +{
> +  return vgetq_lane_f32 (vpaddq_f32 (a, b), 0);
> +}
> +
> +__attribute__ ((noipa)) float32_t
> +lane3_q (float32x4_t a, float32x4_t b)
> +{
> +  return vgetq_lane_f32 (vpaddq_f32 (a, b), 3);
> +}
> +
> +__attribute__ ((noipa)) float32x2_t
> +low_q (float32x4_t a, float32x4_t b)
> +{
> +  return vget_low_f32 (vpaddq_f32 (a, b));
> +}
> +
> +__attribute__ ((noipa)) float32_t
> +lane1_d (float32x2_t a, float32x2_t b)
> +{
> +  return vget_lane_f32 (vpadd_f32 (a, b), 1);
> +}
> +
> +__attribute__ ((noipa)) float64_t
> +lane0_q64 (float64x2_t a, float64x2_t b)
> +{
> +  return vgetq_lane_f64 (vpaddq_f64 (a, b), 0);
> +}
> +
> +__attribute__ ((noipa)) float32x4_t
> +const_q (void)
> +{
> +  float32_t a[] = { 1, 2, 4, 8 };
> +  float32_t b[] = { 16, 32, 64, 128 };
> +  return vpaddq_f32 (vld1q_f32 (a), vld1q_f32 (b));
> +}
> +
> +__attribute__ ((noipa)) float32_t
> +sum_d (float32x2_t a)
> +{
> +  return vaddv_f32 (a);
> +}
> +
> +int
> +main (void)
> +{
> +  float32_t a32[] = { 1, 2, 4, 8 };
> +  float32_t b32[] = { 16, 32, 64, 128 };
> +  float64_t a64[] = { 1, 2 };
> +  float64_t b64[] = { 4, 8 };
> +  float32x4_t a = vld1q_f32 (a32);
> +  float32x4_t b = vld1q_f32 (b32);
> +  float32_t res[4];
> +
> +  if (lane0_q (a, b) != 3 || lane3_q (a, b) != 192)
> +    __builtin_abort ();
> +  vst1_f32 (res, low_q (a, b));
> +  if (res[0] != 3 || res[1] != 12)
> +    __builtin_abort ();
> +  if (lane1_d (vld1_f32 (a32), vld1_f32 (b32)) != 48)
> +    __builtin_abort ();
> +  if (lane0_q64 (vld1q_f64 (a64), vld1q_f64 (b64)) != 3)
> +    __builtin_abort ();
> +  vst1q_f32 (res, const_q ());
> +  if (res[0] != 3 || res[1] != 12 || res[2] != 48 || res[3] != 192)
> +    __builtin_abort ();
> +  if (sum_d (vld1_f32 (b32)) != 48)
> +    __builtin_abort ();
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/simd/faddp_lane_2.c
> b/gcc/testsuite/gcc.target/aarch64/simd/faddp_lane_2.c
> new file mode 100644
> index 00000000000..1c29c94c2d0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/simd/faddp_lane_2.c
> @@ -0,0 +1,53 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target aarch64_mbig_endian } */
> +/* Avoid a dependence on big-endian C library headers.  */
> +/* { dg-options "-O2 -mbig-endian -ffreestanding" } */
> +/* { dg-final { check-function-bodies "**" "" "" } } */
> +
> +#include <arm_neon.h>
> +
> +/* The architectural lanes of the low half depend only on A.  */
> +
> +/*
> +** lane0_q:
> +**   faddp   v0\.4s, v0\.4s, v0\.4s
> +**   ret
> +*/
> +float32_t
> +lane0_q (float32x4_t a, float32x4_t b)
> +{
> +  return vgetq_lane_f32 (vpaddq_f32 (a, b), 0);
> +}
> +
> +/*
> +** low_q:
> +**   faddp   v0\.4s, v0\.4s, v0\.4s
> +**   ret
> +*/
> +float32x2_t
> +low_q (float32x4_t a, float32x4_t b)
> +{
> +  return vget_low_f32 (vpaddq_f32 (a, b));
> +}
> +
> +/*
> +** full_d:
> +**   faddp   v0\.2s, v0\.2s, v1\.2s
> +**   ret
> +*/
> +float32x2_t
> +full_d (float32x2_t a, float32x2_t b)
> +{
> +  return vpadd_f32 (a, b);
> +}
> +
> +/*
> +** full_q64:
> +**   faddp   v0\.2d, v0\.2d, v1\.2d
> +**   ret
> +*/
> +float64x2_t
> +full_q64 (float64x2_t a, float64x2_t b)
> +{
> +  return vpaddq_f64 (a, b);
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/simd/faddp_reinterpret_1.c
> b/gcc/testsuite/gcc.target/aarch64/simd/faddp_reinterpret_1.c
> new file mode 100644
> index 00000000000..1422706591d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/simd/faddp_reinterpret_1.c
> @@ -0,0 +1,51 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +/* { dg-final { check-function-bodies "**" "" "" } } */
> +
> +#include <arm_neon.h>
> +
> +/* The FADDP inputs are subregs of vectors with a different element mode.
> */
> +
> +/*
> +** sum_f32:
> +**   faddp   s0, v0\.2s
> +**   ret
> +*/
> +float32_t
> +sum_f32 (int32x2_t x)
> +{
> +  return vaddv_f32 (vreinterpret_f32_s32 (x));
> +}
> +
> +/*
> +** sum_f64:
> +**   faddp   d0, v0\.2d
> +**   ret
> +*/
> +float64_t
> +sum_f64 (int64x2_t x)
> +{
> +  return vaddvq_f64 (vreinterpretq_f64_s64 (x));
> +}
> +
> +/*
> +** pair_f32:
> +**   faddp   v0\.2s, v0\.2s, v1\.2s
> +**   ret
> +*/
> +float32x2_t
> +pair_f32 (int32x2_t x, int32x2_t y)
> +{
> +  return vpadd_f32 (vreinterpret_f32_s32 (x), vreinterpret_f32_s32 (y));
> +}
> +
> +/*
> +** pair_f64:
> +**   faddp   v0\.2d, v0\.2d, v1\.2d
> +**   ret
> +*/
> +float64x2_t
> +pair_f64 (int64x2_t x, int64x2_t y)
> +{
> +  return vpaddq_f64 (vreinterpretq_f64_s64 (x), vreinterpretq_f64_s64 (y));
> +}
> --
> 2.50.1 (Apple Git-155)

Reply via email to