> -----Original Message-----
> From: Artemiy Volkov <[email protected]>
> Sent: 21 May 2026 17:52
> To: [email protected]
> Cc: Tamar Christina <[email protected]>; Wilco Dijkstra
> <[email protected]>; [email protected]; Richard
> Earnshaw <[email protected]>; [email protected]; Alice
> Carlotti <[email protected]>; Alex Coplan <[email protected]>;
> Artemiy Volkov <[email protected]>
> Subject: [PATCH v2 2/4] aarch64: initialize vectors from starting subsequence
> 
> Now that we have 2- and 4-element vector modes for all the sub-word scalar
> modes, we can emit more efficient code when the elements of a vector
> constructor can be generated from a common starting subsequence of length
> power of two.  To do this, first detect the shortest possible starting
> subsequence by repeatedly folding the initial constructor element array
> in half, as long as the left and the right halves are equal.  Afterwards,
> after emitting the subsequence, duplicate it by generating a
> vec_duplicate with the correct source mode.
> 
> On the MD side, this requires implementing the vec_duplicate optab to
> duplicate an arbitrary sub-128-bit value into a full 64- or a 128-bit
> AdvSIMD register, as well as the vec_set insn for the VSUB64 modes (needed
> as fallback for the divide-and-conquer approach).  The latter uses a
> properly scaled and shifted "bfi" for integer values, and a properly
> indexed "ins" for FP elements.
> 
> This change allows us to get rid of long chains of inserts and compile
> things like:
> 
> int16x8_t f (int16_t x, int16_t y, int16_t z, int16_t w)
> {
>       return (int16x8_t) {x, y, z, w, x, y, z, w};
> }
> 
> into:
>       bfi     w0, w2, 16, 16
>       bfi     w1, w3, 16, 16
>       dup     v31.2s, w0
>       dup     v0.2s, w1
>       zip1    v0.8h, v31.8h, v0.8h
>       ret
> 
> rather than:
> 
>       dup     v31.4h, w0
>       dup     v0.4h, w1
>       ins     v31.h[1], w2
>       ins     v0.h[1], w3
>       ins     v31.h[3], w2
>       ins     v0.h[3], w3
>       zip1    v0.8h, v31.8h, v0.8h
>       ret
> 
> This patch also includes an extensive new test, which includes the above
> case, as well as adjustments to existing codegen tests as necessary.

OK.

Thanks,
Tamar

> 
> gcc/ChangeLog:
> 
>       * config/aarch64/aarch64-simd.md
> (*aarch64_simd_dup_subvector<vconq><mode>):
>       New insn pattern.
>       (*aarch64_simd_dup_subvector<vcond><mode>): Likewise.
>       (@aarch64_simd_vec_set<mode>): Likewise.
>       (vec_set<mode>): Handle 16- and 32-bit vector modes in the
> expander.
>       * config/aarch64/aarch64.cc (aarch64_expand_vector_init_fallback):
> Add
>       logic to initialize vector from starting subsequence.  Make static.
>       (scalar_move_insn_p): Consider sub-64-bit vector moves scalar.
>       * config/aarch64/iterators.md (VDDUP): New iterator.
>       (VQDUP): Likewise.
>       (elem_bits): Define attribute for sub-64-bit vector modes.
>       (Vetype): Likewise.
>       (VEL): Likewise.
>       (single_wx): Define attribute for sub-64-bit vector and scalar modes.
>       (single_type): Likewise.
>       (VCOND): Likewise.
>       (VCONQ): Likewise.
>       (Vqduptype): New mode attribute.
>       (Vdduptype): Likewise.
>       (vcond): Likewise.
>       (vconq): Likewise.
>       (vstype): Define attribute for 64-bit vector and sub-128-bit scalar
>       modes.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.target/aarch64/ldp_stp_16.c: Adjust testcase.
>       * gcc.target/aarch64/sve/slp_1.c: Likewise.
>       * gcc.target/aarch64/vec-init-18.c: Likewise.
>       * gcc.target/aarch64/vec-init-23.c: New test.
> ---
>  gcc/config/aarch64/aarch64-simd.md            |  50 +-
>  gcc/config/aarch64/aarch64.cc                 |  42 +-
>  gcc/config/aarch64/iterators.md               | 107 ++++-
>  gcc/testsuite/gcc.target/aarch64/ldp_stp_16.c |   5 +-
>  gcc/testsuite/gcc.target/aarch64/sve/slp_1.c  |   7 +-
>  .../gcc.target/aarch64/vec-init-18.c          |   8 +-
>  .../gcc.target/aarch64/vec-init-23.c          | 435 ++++++++++++++++++
>  7 files changed, 632 insertions(+), 22 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/vec-init-23.c
> 
> diff --git a/gcc/config/aarch64/aarch64-simd.md
> b/gcc/config/aarch64/aarch64-simd.md
> index c2fdc4d6adc..15c6acb6788 100644
> --- a/gcc/config/aarch64/aarch64-simd.md
> +++ b/gcc/config/aarch64/aarch64-simd.md
> @@ -137,6 +137,28 @@
>    }
>  )
> 
> +(define_insn "*aarch64_simd_dup_subvector<vconq><mode>"
> +  [(set (match_operand:<VCONQ> 0 "register_operand")
> +     (vec_duplicate:<VCONQ>
> +       (match_operand:VQDUP 1 "register_operand")))]
> +  "TARGET_SIMD"
> +  {@ [ cons: =0 , 1 ; attrs: type    ]
> +     [ w        , w ; neon_dup_q     ] dup\t%0.<Vqduptype>, %1.<vstype>[0]
> +     [ w        , r ; neon_from_gp_q ] dup\t%0.<Vqduptype>, %<single_wx>1
> +  }
> +)
> +
> +(define_insn "*aarch64_simd_dup_subvector<vcond><mode>"
> +  [(set (match_operand:<VCOND> 0 "register_operand")
> +     (vec_duplicate:<VCOND>
> +       (match_operand:VDDUP 1 "register_operand")))]
> +  "TARGET_SIMD"
> +  {@ [ cons: =0 , 1 ; attrs: type  ]
> +     [ w        , w ; neon_dup     ] dup\t%0.<Vdduptype>, %1.<vstype>[0]
> +     [ w        , r ; neon_from_gp ] dup\t%0.<Vdduptype>, %<single_wx>1
> +  }
> +)
> +
>  (define_insn "@aarch64_dup_lane<mode>"
>    [(set (match_operand:VALL_F16 0 "register_operand" "=w")
>       (vec_duplicate:VALL_F16
> @@ -1285,6 +1307,32 @@
>    [(set_attr "type" "neon_ins<q>, neon_from_gp<q>,
> neon_load1_one_lane<q>")]
>  )
> 
> +(define_insn "@aarch64_simd_vec_set<mode>"
> +  [(set (match_operand:VSUB64 0 "register_operand" "=r,w,w")
> +     (vec_merge:VSUB64
> +         (vec_duplicate:VSUB64
> +             (match_operand:<VEL> 1
> "aarch64_simd_nonimmediate_operand" "r,w,Utv"))
> +         (match_operand:VSUB64 3 "register_operand" "0,0,0")
> +         (match_operand:SI 2 "immediate_operand" "i,i,i")))]
> +  "TARGET_SIMD && exact_log2 (INTVAL (operands[2])) >= 0"
> +  {
> +    int elt = exact_log2 (INTVAL (operands[2]));
> +    switch (which_alternative)
> +      {
> +      case 0:
> +     operands[2] = GEN_INT (elt * <elem_bits>);
> +     return "bfi\t%w0, %w1, %2, <elem_bits>";
> +      case 1:
> +     return "ins\t%0.<Vetype>[%p2], %1.<Vetype>[0]";
> +      case 2:
> +     return "ld1\t{%0.<Vetype>}[%p2], %1";
> +      default:
> +     gcc_unreachable ();
> +      }
> +  }
> +  [(set_attr "type" "bfm, neon_ins, neon_load1_one_lane")]
> +)
> +
>  ;; Inserting from the zero register into a vector lane is treated as an
>  ;; expensive GP->FP move on all CPUs.  Avoid it when optimizing for speed.
>  (define_insn "aarch64_simd_vec_set_zero<mode>"
> @@ -1714,7 +1762,7 @@
>  )
> 
>  (define_expand "vec_set<mode>"
> -  [(match_operand:VALL_F16 0 "register_operand")
> +  [(match_operand:VALL_F16_SUB64 0 "register_operand")
>     (match_operand:<VEL> 1 "aarch64_simd_nonimmediate_operand")
>     (match_operand:SI 2 "immediate_operand")]
>    "TARGET_SIMD"
> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
> index 0f78f36cba3..9dedad773f0 100644
> --- a/gcc/config/aarch64/aarch64.cc
> +++ b/gcc/config/aarch64/aarch64.cc
> @@ -25667,7 +25667,7 @@ aarch64_choose_vector_init_constant
> (machine_mode mode, rtx vals)
>     The caller has already tried a divide-and-conquer approach, so do
>     not consider that case here.  */
> 
> -void
> +static void
>  aarch64_expand_vector_init_fallback (rtx target, rtx vals)
>  {
>    machine_mode mode = GET_MODE (target);
> @@ -25725,6 +25725,43 @@ aarch64_expand_vector_init_fallback (rtx
> target, rtx vals)
>        return;
>      }
> 
> +  /* Check if the vector can be represented as a duplicate of a
> +     subvector starting at index 0.  */
> +  if (pow2p_hwi (n_elts))
> +    {
> +     bool halves_equal = true;
> +     int n_seq = n_elts;
> +     while (n_seq > 2)
> +       {
> +         for (int i = 0; i < n_seq / 2; i++)
> +           if (!rtx_equal_p (XVECEXP (vals, 0, i),
> +                             XVECEXP (vals, 0, i + n_seq / 2)))
> +             {
> +               halves_equal = false;
> +               break;
> +             }
> +
> +         if (!halves_equal)
> +           break;
> +
> +         n_seq /= 2;
> +       }
> +
> +     if (n_seq != n_elts)
> +       {
> +         machine_mode subv_mode = mode_for_vector (inner_mode,
> +                                                   n_seq).require ();
> +         rtx new_target = gen_reg_rtx (subv_mode);
> +         rtvec new_vals = rtvec_alloc (n_seq);
> +         for (int i = 0; i < n_seq; i++)
> +           RTVEC_ELT (new_vals, i) = XVECEXP (vals, 0, i);
> +         aarch64_expand_vector_init (new_target,
> +                                     gen_rtx_PARALLEL (subv_mode,
> new_vals));
> +         aarch64_emit_move (target, gen_vec_duplicate (mode,
> new_target));
> +         return;
> +       }
> +    }
> +
>    enum insn_code icode = optab_handler (vec_set_optab, mode);
>    gcc_assert (icode != CODE_FOR_nothing);
> 
> @@ -25884,7 +25921,8 @@ scalar_move_insn_p (rtx set)
>    rtx src = SET_SRC (set);
>    rtx dest = SET_DEST (set);
>    return (is_a<scalar_mode> (GET_MODE (dest))
> -       && aarch64_mov_operand (src, GET_MODE (dest)));
> +       && aarch64_mov_operand (src, GET_MODE (dest)))
> +      || aarch64_advsimd_sub_dword_mode_p (GET_MODE (dest));
>  }
> 
>  /* Similar to seq_cost, but ignore cost for scalar moves.  */
> diff --git a/gcc/config/aarch64/iterators.md
> b/gcc/config/aarch64/iterators.md
> index dfca3327f1f..f3e7b9d58f3 100644
> --- a/gcc/config/aarch64/iterators.md
> +++ b/gcc/config/aarch64/iterators.md
> @@ -139,6 +139,14 @@
>  ;; VQMOV without 2-element modes.
>  (define_mode_iterator VQMOV_NO2E [V16QI V8HI V4SI V8HF V8BF V4SF])
> 
> +;; Modes that can be duplicated into a 64-bit register.
> +(define_mode_iterator VDDUP [V4QI V2QI QI V2HI HI SI
> +                             V2BF BF V2HF HF SF])
> +
> +;; Modes that can be duplicated into a 128-bit register.
> +(define_mode_iterator VQDUP [V8QI V4QI V2QI QI V4HI V2HI HI V2SI SI DI
> +                             V4BF V2BF BF V4HF V2HF HF V2SF SF DF])
> +
>  ;; Double integer vector modes.
>  (define_mode_iterator VD_I [V8QI V4HI V2SI DI])
> 
> @@ -1488,7 +1496,9 @@
> 
>  ;; The number of bits in a vector element, or controlled by a predicate
>  ;; element.
> -(define_mode_attr elem_bits [(VNx16BI "8") (VNx8BI "16")
> +(define_mode_attr elem_bits [(V2QI "8") (V4QI "8") (V2HF "16") (V2HI
> "16")
> +                          (V2BF "16")
> +                          (VNx16BI "8") (VNx8BI "16")
>                            (VNx4BI "32") (VNx2BI "64")
>                            (VNx16QI "8") (VNx32QI "8") (VNx64QI "8")
>                            (VNx8HI "16") (VNx16HI "16") (VNx32HI "16")
> @@ -1593,11 +1603,12 @@
> 
>  ;; Mode-to-individual element type mapping.
>  (define_mode_attr Vetype [(V8QI "b") (V16QI "b")
> -                       (V4HI "h") (V8HI  "h")
> +                       (V2QI "b") (V4QI "b")
> +                       (V4HI "h") (V8HI  "h") (V2HI "h")
>                         (V2SI "s") (V4SI  "s")
>                         (V2DI "d") (V1DI  "d")
> -                       (V4HF "h") (V8HF  "h")
> -                       (V2SF "s") (V4SF  "s")
> +                       (V4HF "h") (V8HF  "h") (V2HF "h")
> +                       (V2SF "s") (V4SF  "s") (V2BF "h")
>                         (V2DF "d") (V1DF  "d")
>                         (V2x8QI "b") (V2x4HI "h")
>                         (V2x2SI "s") (V2x1DI "d")
> @@ -1772,8 +1783,10 @@
>                              (V4x2DF "v2df") (V4x8BF "v8bf")])
> 
>  ;; Define element mode for each vector mode.
> -(define_mode_attr VEL [(V8QI  "QI") (V16QI "QI")
> +(define_mode_attr VEL [(V8QI "QI") (V16QI "QI")
> +                    (V2QI "QI") (V4QI  "QI")
>                      (V4HI "HI") (V8HI  "HI")
> +                    (V2HI "HI") (V2HF  "HF")
>                      (V2SI "SI") (V4SI  "SI")
>                      (DI   "DI") (V1DI  "DI")
>                      (V2DI "DI")
> @@ -1784,6 +1797,7 @@
>                      (SI   "SI") (HI    "HI")
>                      (QI   "QI")
>                      (V4BF "BF") (V8BF "BF")
> +                    (V2BF "BF")
>                      (V2x8QI "QI") (V2x4HI "HI")
>                      (V2x2SI "SI") (V2x1DI "DI")
>                      (V2x4HF "HF") (V2x2SF "SF")
> @@ -1900,25 +1914,66 @@
> 
>  ;; 64-bit container modes the inner or scalar source mode.
>  (define_mode_attr VCOND [(HI "V4HI") (SI "V2SI")
> +                      (V2HI "V4HI")
>                        (V4HI "V4HI") (V8HI "V4HI")
>                        (V2SI "V2SI") (V4SI "V2SI")
> +                      (QI "V8QI") (V2QI "V8QI")
> +                      (V4QI "V8QI")
>                        (DI   "DI") (V2DI "DI")
> +                      (HF "V4HF") (V2HF "V4HF")
>                        (V4HF "V4HF") (V8HF "V4HF")
> +                      (BF "V4BF") (V2BF "V4BF")
> +                      (SF "V2SF")
>                        (V2SF "V2SF") (V4SF "V2SF")
>                        (V2DF "DF")])
> 
> +;; Same as above, but in lowercase.
> +(define_mode_attr vcond [(HI "v4hi") (SI "v2si")
> +                      (V2HI "v4hi")
> +                      (V4HI "v4hi") (V8HI "v4hi")
> +                      (V2SI "v2si") (V4SI "v2si")
> +                      (QI "v8qi") (V2QI "v8qi")
> +                      (V4QI "v8qi")
> +                      (DI   "di") (V2DI "di")
> +                      (HF "v4hf") (V2HF "v4hf")
> +                      (V4HF "v4hf") (V8HF "v4hf")
> +                      (BF "v4bf") (V2BF "v4bf")
> +                      (SF "v2sf")
> +                      (V2SF "v2sf") (V4SF "v2sf")
> +                      (V2DF "df")])
> +
>  ;; 128-bit container modes the inner or scalar source mode.
>  (define_mode_attr VCONQ [(V8QI "V16QI") (V16QI "V16QI")
> +                      (V4QI "V16QI") (V2QI "V16QI")
>                        (V4HI "V8HI") (V8HI "V8HI")
> +                      (V2HI "V8HI")
>                        (V2SI "V4SI") (V4SI "V4SI")
>                        (DI   "V2DI") (V2DI "V2DI")
>                        (V4HF "V8HF") (V8HF "V8HF")
> +                      (V2HF "V8HF") (HF "V8HF")
>                        (V4BF "V8BF") (V8BF "V8BF")
> +                      (V2BF "V8BF") (BF "V8BF")
>                        (V2SF "V4SF") (V4SF "V4SF")
>                        (V2DF "V2DF") (SI   "V4SI")
>                        (HI   "V8HI") (QI   "V16QI")
>                        (SF   "V4SF") (DF   "V2DF")])
> 
> +;; Same as above, but in lowercase.
> +(define_mode_attr vconq [(V8QI "v16qi") (V16QI "v16qi")
> +                      (V4QI "v16qi") (V2QI "v16qi")
> +                      (V4HI "v8hi") (V8HI "v8hi")
> +                      (V2HI "v8hi")
> +                      (V2SI "v4si") (V4SI "v4si")
> +                      (DI   "v2di") (V2DI "v2di")
> +                      (V4HF "v8hf") (V8HF "v8hf")
> +                      (V2HF "v8hf") (HF "v8hf")
> +                      (V4BF "v8bf") (V8BF "v8bf")
> +                      (V2BF "v8bf") (BF "v8bf")
> +                      (V2SF "v4sf") (V4SF "v4sf")
> +                      (V2DF "v2df") (SI   "v4si")
> +                      (HI   "v8hi") (QI   "v16qi")
> +                      (SF   "v4sf") (DF   "v2df")])
> +
>  ;; Half modes of all vector modes.
>  (define_mode_attr VHALF [(V8QI "V4QI")  (V16QI "V8QI")
>                        (V4HI "V2HI")  (V8HI  "V4HI")
> @@ -2037,6 +2092,26 @@
>  (define_mode_attr V2ntype [(V8HI "16b") (V4SI "8h")
>                          (V2DI "4s")])
> 
> +;; Register suffix used when duplicating a value of a certain mode
> +;; into a full 128-bit AdvSIMD register.
> +(define_mode_attr Vqduptype [(QI "16b") (V2QI "8h") (V4QI "4s") (V8QI
> "2d")
> +                          (HI "8h") (V2HI "4s") (V4HI "2d")
> +                          (HF "8h") (V2HF "4s") (V4HF "2d")
> +                          (BF "8h") (V2BF "4s") (V4BF "2d")
> +                          (SI "4s") (V2SI "2d")
> +                          (SF "4s") (V2SF "2d")
> +                          (DI "2d") (DF "2d")])
> +
> +;; Register suffix used when duplicating a value of a certain mode
> +;; into a partial 64-bit AdvSIMD register.
> +(define_mode_attr Vdduptype [(QI "8b") (V2QI "4h") (V4QI "2s") (V8QI "")
> +                          (HI "4h") (V2HI "2s") (V4HI "")
> +                          (HF "4h") (V2HF "2s") (V4HF "")
> +                          (BF "4h") (V2BF "2s") (V4BF "")
> +                          (SI "2s") (V2SI "")
> +                          (SF "2s") (V2SF "")
> +                          (DI "") (DF "")])
> +
>  ;; The result of FCVTN on two vectors of the given mode.  The result has
>  ;; twice as many QI elements as the input.
>  (define_mode_attr VPACKB [(V4HF "V8QI") (V8HF "V16QI") (V4SF "V8QI")])
> @@ -2161,8 +2236,13 @@
>  ;; Whether a mode fits in W or X registers (i.e. "w" for 32-bit modes
>  ;; and "x" for 64-bit modes).
>  (define_mode_attr single_wx [(SI   "w") (SF   "w")
> +                          (V2QI "w") (V4QI "w")
>                            (V8QI "x") (V4HI "x")
>                            (V4HF "x") (V4BF "x")
> +                          (V2HI "w") (V2HF "w")
> +                          (HF   "w") (QI   "w")
> +                          (V2BF "w") (BF   "w")
> +                          (HI   "w")
>                            (V2SI "x") (V2SF "x")
>                            (DI   "x") (DF   "x")])
> 
> @@ -2172,7 +2252,12 @@
>                              (V8QI "d") (V4HI "d")
>                              (V4HF "d") (V4BF "d")
>                              (V2SI "d") (V2SF "d")
> -                            (DI   "d") (DF   "d")])
> +                            (DI   "d") (DF   "d")
> +                            (QI   "b") (BF   "h")
> +                            (V2HF "s") (HI   "h")
> +                            (V4QI "s") (V2QI "h")
> +                            (V2HI "s") (V2BF "s")
> +                            (HF   "h")])
> 
>  ;; Whether a double-width mode fits in D or Q registers (i.e. "d" for
>  ;; 32-bit modes and "q" for 64-bit modes).
> @@ -2182,9 +2267,13 @@
>                               (V2SI "q") (V2SF "q")
>                               (DI   "q") (DF   "q")])
> 
> -;; Scalar size of a sub-64-bit vector mode.
> -(define_mode_attr vstype [(V4QI "s") (V2QI "h")
> -                       (V2HI "s") (V2BF "s") (V2HF "s")])
> +;; Scalar size of a sub-128-bit vector or scalar mode.
> +(define_mode_attr vstype [(V8QI "d") (V4QI "s") (V2QI "h") (QI "b")
> +                       (V4HI "d") (V2HI "s") (HI "h")
> +                       (V2SI "d") (SI "s") (DI "d")
> +                       (V4BF "d") (V2BF "s") (BF "h")
> +                       (V4HF "d") (V2HF "s") (HF "h")
> +                       (V2SF "d") (SF "s") (DF "d")])
> 
>  ;; Define corresponding core/FP element mode for each vector mode.
>  (define_mode_attr vw [(V8QI "w") (V16QI "w")
> diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_16.c
> b/gcc/testsuite/gcc.target/aarch64/ldp_stp_16.c
> index 95835aa2eb4..a6b4d50f34f 100644
> --- a/gcc/testsuite/gcc.target/aarch64/ldp_stp_16.c
> +++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_16.c
> @@ -96,9 +96,8 @@ CONS2_FN (4, float);
> 
>  /*
>  ** cons2_8_float:
> -**   dup     v[0-9]+\.2s, v[0-9]+\.s\[0\]
> -**   dup     v[0-9]+\.2s, v[0-9]+\.s\[0\]
> -**   zip1    v([0-9]+)\.4s, v[0-9]+\.4s, v[0-9]+\.4s
> +**   uzp1    v1\.2s, v0\.2s, v1\.2s
> +**   dup     v([0-9]+)\.2d, v1\.d\[0\]
>  **   stp     q\1, q\1, \[x0\]
>  **   stp     q\1, q\1, \[x0, #?32\]
>  **   ret
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_1.c
> b/gcc/testsuite/gcc.target/aarch64/sve/slp_1.c
> index 739e63a96a1..ddf4c23869f 100644
> --- a/gcc/testsuite/gcc.target/aarch64/sve/slp_1.c
> +++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_1.c
> @@ -30,14 +30,13 @@ vec_slp_##TYPE (TYPE *restrict a, TYPE b, TYPE c, int
> n)    \
>  TEST_ALL (VEC_PERM)
> 
>  /* We should use one DUP for each of the 8-, 16- and 32-bit types,
> -   (for now, insert both elements with umov + ins for _Float16).  We should
> use two
> +   (for now, insert both elements with ins for _Float16).  We should use two
>     DUPs for each of the three 64-bit types.  */
>  /* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.h, [hw]} 2 } } */
>  /* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.s, [sw]} 3 } } */
>  /* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.d, [dx]} 9 } } */
> -/* { dg-final { scan-assembler-times {\tumov\tw[0-9]+, v[0-9]+\.h} 2 } } */
> -/* { dg-final { scan-assembler-times {\tins\tv[0-9]+\.h\[0\], w[0-9]+} 3 } } 
> */
> -/* { dg-final { scan-assembler-times {\tins\tv[0-9]+\.h\[1\], w[0-9]+} 3 } } 
> */
> +/* { dg-final { scan-assembler-times {\tins\tv[0-9]+\.h\[0\], 
> v[0-9]+\.h\[0\]}
> 3 } } */
> +/* { dg-final { scan-assembler-times {\tins\tv[0-9]+\.h\[1\], 
> v[0-9]+\.h\[0\]}
> 3 } } */
>  /* { dg-final { scan-assembler-times {\tzip1\tz[0-9]+\.d, z[0-9]+\.d, z[0-
> 9]+\.d\n} 3 } } */
>  /* { dg-final { scan-assembler-not {\tzip2\t} } } */
> 
> diff --git a/gcc/testsuite/gcc.target/aarch64/vec-init-18.c
> b/gcc/testsuite/gcc.target/aarch64/vec-init-18.c
> index ecb59fe510b..99e84096708 100644
> --- a/gcc/testsuite/gcc.target/aarch64/vec-init-18.c
> +++ b/gcc/testsuite/gcc.target/aarch64/vec-init-18.c
> @@ -15,6 +15,8 @@ int16x8_t foo2(int16_t x)
>    return v;
>  }
> 
> -/* { dg-final { scan-assembler-times {\tdup\tv[0-9]+\.4h, w[0-9]+} 3 } } */
> -/* { dg-final { scan-assembler {\tmovi\tv[0-9]+\.4h, 0x1} } } */
> -/* { dg-final { scan-assembler-times {\tzip1\tv[0-9]+\.8h, v[0-9]+\.8h, v[0-
> 9]+\.8h} 2 } } */
> +/* { dg-final { scan-assembler-times {\tdup\tv[0-9]+\.4s, v[0-9]+\.s\[0\]} 1 
> }
> } */
> +/* { dg-final { scan-assembler-times {\tdup\tv[0-9]+\.4s, w[0-9]+} 1 } } */
> +/* { dg-final { scan-assembler-times {\tmov\tw[0-9]+, 65537} 1 } } */
> +/* { dg-final { scan-assembler-times {\tbfi\tw[0-9]+, w[0-9]+, 0, 16} 1 } } 
> */
> +/* { dg-final { scan-assembler-times {\tbfi\tw[0-9]+, w[0-9]+, 16, 16} 1 } } 
> */
> diff --git a/gcc/testsuite/gcc.target/aarch64/vec-init-23.c
> b/gcc/testsuite/gcc.target/aarch64/vec-init-23.c
> new file mode 100644
> index 00000000000..940fe34c325
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/vec-init-23.c
> @@ -0,0 +1,435 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -march=armv8.2-a+fp16" } */
> +/* { dg-final { check-function-bodies "**" "" "" } } */
> +
> +#include <arm_neon.h>
> +
> +/* Check vector initialization with a repeating sequence of elements.  */
> +
> +#ifndef TESTCASE
> +#define TESTCASE(TYPE, ETYPE, T, SZ, NUM, MULT, ...)\
> +  TYPE##SZ##MULT##_t test_##TYPE##SZ##_##NUM (ETYPE x0, ETYPE x1,
> ETYPE x2, ETYPE x3,\
> +                                        ETYPE x4, ETYPE x5, ETYPE x6, ETYPE
> x7)\
> +  {\
> +    return (TYPE##SZ##MULT##_t) {__VA_ARGS__};\
> +  }
> +#endif
> +
> +#define TEST_8(TYPE, ETYPE, T)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 1, x16, x0, x0, x0, x0, x0, x0, x0, x0,\
> +                            x0, x0, x0, x0, x0, x0, x0, x0)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 2, x16, x0, x1, x0, x1, x0, x1, x0, x1,\
> +                            x0, x1, x0, x1, x0, x1, x0, x1)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 3, x16, x0, x1, x2, x3, x0, x1, x2, x3,\
> +                            x0, x1, x2, x3, x0, x1, x2, x3)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 4, x16, x0, x1, x2, x3, x4, x5, x6, x7,\
> +                            x0, x1, x2, x3, x4, x5, x6, x7)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 5, x16, x0, 0, x0, 0, x0, 0, x0, 0,\
> +                            x0, 0, x0, 0, x0, 0, x0, 0)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 6, x16, 0, x0, 0, x0, 0, x0, 0, x0,\
> +                            0, x0, 0, x0, 0, x0, 0, x0)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 7, x16, x0, x1, 0, 1, x0, x1, 0, 1,\
> +                            x0, x1, 0, 1, x0, x1, 0, 1)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 8, x16, 0, 1, x0, x1, 0, 1, x0, x1,\
> +                        0, 1, x0, x1, 0, 1, x0, x1)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 9, x16, x0, 0, x1, 1, x0, 0, x1, 1,\
> +                            x0, 0, x1, 1, x0, 0, x1, 1)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 10, x16, x0, 0, x1, 1, x2, 2, x3, 3,\
> +                            x0, 0, x1, 1, x2, 2, x3, 3)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 11, x16, 0, x0, 1, x1, 2, x2, 3, x3,\
> +                            0, x0, 1, x1, 2, x2, 3, x3)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 12, x16, x0, x1, 0, 1, x2, x3, 2, 3,\
> +                            x0, x1, 0, 1, x2, x3, 2, 3)\
> +    TESTCASE (TYPE, ETYPE, T, 8, 13, x16, 0, 1, x0, x1, 2, 3, x2, x3,\
> +                            0, 1, x0, x1, 2, 3, x2, x3)
> +
> +#define TEST_16(TYPE, ETYPE, T)\
> +    TESTCASE (TYPE, ETYPE, T, 16, 1, x8, x0, x0, x0, x0, x0, x0, x0, x0)\
> +    TESTCASE (TYPE, ETYPE, T, 16, 2, x8, x0, x1, x0, x1, x0, x1, x0, x1)\
> +    TESTCASE (TYPE, ETYPE, T, 16, 3, x8, x0, x1, x2, x3, x0, x1, x2, x3)\
> +    TESTCASE (TYPE, ETYPE, T, 16, 4, x8, x0, 0, x0, 0, x0, 0, x0, 0)\
> +    TESTCASE (TYPE, ETYPE, T, 16, 5, x8, 0, x0, 0, x0, 0, x0, 0, x0)\
> +    TESTCASE (TYPE, ETYPE, T, 16, 6, x8, x0, x1, 0, 1, x0, x1, 0, 1)\
> +    TESTCASE (TYPE, ETYPE, T, 16, 7, x8, 0, 1, x0, x1, 0, 1, x0, x1)\
> +    TESTCASE (TYPE, ETYPE, T, 16, 8, x8, 0, x0, 1, x1, 0, x0, 1, x1)\
> +
> +#define TEST_32(TYPE, ETYPE, T)\
> +    TESTCASE (TYPE, ETYPE, T, 32, 1, x4, x0, x0, x0, x0)\
> +    TESTCASE (TYPE, ETYPE, T, 32, 2, x4, x0, x1, x0, x1)\
> +    TESTCASE (TYPE, ETYPE, T, 32, 3, x4, x0, 0, x0, 0)\
> +    TESTCASE (TYPE, ETYPE, T, 32, 4, x4, 0, x0, 0, x0)
> +
> +#define TEST_64(TYPE, ETYPE, T)\
> +    TESTCASE (TYPE, ETYPE, T, 64, 1, x2, x0, x0)
> +
> +TEST_8(int, int8_t, s)
> +
> +TEST_16(float, float, f)
> +TEST_16(int, int16_t, s)
> +
> +TEST_32(float, float, f)
> +TEST_32(int, int32_t, s)
> +
> +TEST_64(float, double, f)
> +TEST_64(int, int64_t, s)
> +
> +/*
> +** test_int8_1:
> +**   dup     v0\.16b, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int8_2:
> +**   bfi     w0, w1, 8, 8
> +**   dup     v0\.8h, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int8_3:
> +**   bfi     w0, w1, 8, 8
> +**   bfi     w0, w2, 16, 8
> +**   bfi     w0, w3, 24, 8
> +**   dup     v0\.4s, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int8_4:
> +**   bfi     w0, w2, 8, 8
> +**   bfi     w1, w3, 8, 8
> +**   bfi     w0, w4, 16, 8
> +**   bfi     w1, w5, 16, 8
> +**   bfi     w0, w6, 24, 8
> +**   bfi     w1, w7, 24, 8
> +**   dup     v31\.2s, w0
> +**   dup     v0\.2s, w1
> +**   zip1    v0\.16b, v31\.16b, v0\.16b
> +**   ret
> +*/
> +
> +/*
> +** test_int8_5:
> +**   mov     w1, 0
> +**   bfi     w1, w0, 0, 8
> +**   dup     v0\.8h, w1
> +**   ret
> +*/
> +
> +/*
> +** test_int8_6:
> +**   mov     w1, 0
> +**   bfi     w1, w0, 8, 8
> +**   dup     v0\.8h, w1
> +**   ret
> +*/
> +
> +/*
> +** test_int8_7:
> +**   mov     w2, 16777472
> +**   bfi     w2, w0, 0, 8
> +**   bfi     w2, w1, 8, 8
> +**   dup     v0\.4s, w2
> +**   ret
> +*/
> +
> +/*
> +** test_int8_8:
> +**   mov     w2, 16777472
> +**   bfi     w2, w0, 16, 8
> +**   bfi     w2, w1, 24, 8
> +**   dup     v0\.4s, w2
> +**   ret
> +*/
> +
> +/*
> +** test_int8_9:
> +**   mov     w2, 16777216
> +**   bfi     w2, w0, 0, 8
> +**   bfi     w2, w1, 16, 8
> +**   dup     v0\.4s, w2
> +**   ret
> +*/
> +
> +/*
> +** test_int8_10:
> +**   bfi     w0, w1, 8, 8
> +**   bfi     w0, w2, 16, 8
> +**   bfi     w0, w3, 24, 8
> +**   dup     v31\.2s, w0
> +**   adrp    x0, .LANCHOR[0-9]+
> +**   ldr     d0, \[x0, #:lo12:.LANCHOR[0-9]+\]
> +**   zip1    v0\.16b, v31\.16b, v0\.16b
> +**   ret
> +*/
> +
> +/*
> +** test_int8_11:
> +**   bfi     w0, w1, 8, 8
> +**   adrp    x4, .LANCHOR[0-9]+
> +**   bfi     w0, w2, 16, 8
> +**   ldr     d0, \[x4, #:lo12:\.LANCHOR[0-9]+\]
> +**   bfi     w0, w3, 24, 8
> +**   dup     v31\.2s, w0
> +**   zip1    v0\.16b, v0\.16b, v31\.16b
> +**   ret
> +*/
> +
> +/*
> +** test_int8_12:
> +**   mov     w4, 33685504
> +**   bfi     w4, w0, 0, 8
> +**   mov     w0, 257
> +**   movk    w0, 0x303, lsl 16
> +**   bfi     w0, w1, 0, 8
> +**   bfi     w4, w2, 16, 8
> +**   bfi     w0, w3, 16, 8
> +**   dup     v31\.2s, w4
> +**   dup     v0\.2s, w0
> +**   zip1    v0\.16b, v31\.16b, v0\.16b
> +**   ret
> +*/
> +
> +/*
> +** test_int8_13:
> +**   mov     w4, 33685504
> +**   bfi     w4, w0, 8, 8
> +**   mov     w0, 257
> +**   movk    w0, 0x303, lsl 16
> +**   bfi     w0, w1, 8, 8
> +**   bfi     w4, w2, 24, 8
> +**   bfi     w0, w3, 24, 8
> +**   dup     v31\.2s, w4
> +**   dup     v0\.2s, w0
> +**   zip1    v0\.16b, v31\.16b, v0\.16b
> +**   ret
> +*/
> +
> +/*
> +** test_float16_1:
> +**   fcvt    h0, s0
> +**   dup     v0\.8h, v0\.h\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_float16_2:
> +**   fcvt    h1, s1
> +**   fcvt    h0, s0
> +**   ins     v0\.h\[1\], v1\.h\[0\]
> +**   dup     v0\.4s, v0\.s\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_float16_3:
> +**   uzp1    v2\.2s, v0\.2s, v2\.2s
> +**   uzp1    v3\.2s, v1\.2s, v3\.2s
> +**   zip1    v3\.4s, v2\.4s, v3\.4s
> +**   fcvtn   v0\.4h, v3\.4s
> +**   uzp1    v0\.2d, v0\.2d, v0\.2d
> +**   ret
> +*/
> +
> +/*
> +** test_float16_4:
> +**   fcvt    h0, s0
> +**   movi    v31\.2d, #0
> +**   ins     v31\.h\[0\], v0\.h\[0\]
> +**   dup     v0\.4s, v31\.s\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_float16_5:
> +**   fcvt    h0, s0
> +**   movi    v31\.2d, #0
> +**   ins     v31\.h\[1\], v0\.h\[0\]
> +**   dup     v0\.4s, v31\.s\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_float16_6:
> +**   fcvt    h1, s1
> +**   fcvt    h0, s0
> +**   movi    v31\.2d, #0
> +**   mov     w0, 1006648320
> +**   umov    w1, v1\.h\[0\]
> +**   ins     v31\.h\[0\], v0\.h\[0\]
> +**   bfi     w0, w1, 0, 16
> +**   dup     v31\.2s, v31\.s\[0\]
> +**   dup     v0\.2s, w0
> +**   zip1    v0\.8h, v31\.8h, v0\.8h
> +**   ret
> +*/
> +
> +/*
> +** test_float16_7:
> +**   fcvt    h1, s1
> +**   fcvt    h0, s0
> +**   movi    v31\.2d, #0
> +**   mov     w0, 1006648320
> +**   umov    w1, v1\.h\[0\]
> +**   ins     v31\.h\[1\], v0\.h\[0\]
> +**   bfi     w0, w1, 16, 16
> +**   dup     v31\.2s, v31\.s\[0\]
> +**   dup     v0\.2s, w0
> +**   zip1    v0\.8h, v31\.8h, v0\.8h
> +**   ret
> +*/
> +
> +/*
> +** test_float16_8:
> +**   fcvt    h1, s1
> +**   fcvt    h0, s0
> +**   movi    v31\.2s, 0x3c, lsl 24
> +**   ins     v0\.h\[1\], v1\.h\[0\]
> +**   dup     v0\.2s, v0\.s\[0\]
> +**   zip1    v0\.8h, v31\.8h, v0\.8h
> +**   ret
> +*/
> +
> +/*
> +** test_int16_1:
> +**   dup     v0\.8h, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int16_2:
> +**   bfi     w0, w1, 16, 16
> +**   dup     v0\.4s, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int16_3:
> +**   bfi     w0, w2, 16, 16
> +**   bfi     w1, w3, 16, 16
> +**   dup     v31\.2s, w0
> +**   dup     v0\.2s, w1
> +**   zip1    v0\.8h, v31\.8h, v0\.8h
> +**   ret
> +*/
> +
> +/*
> +** test_int16_4:
> +**   mov     w1, 0
> +**   bfi     w1, w0, 0, 16
> +**   dup     v0\.4s, w1
> +**   ret
> +*/
> +
> +/*
> +** test_int16_5:
> +**   mov     w1, 0
> +**   bfi     w1, w0, 16, 16
> +**   dup     v0\.4s, w1
> +**   ret
> +*/
> +
> +/*
> +** test_int16_6:
> +**   mov     w2, 0
> +**   bfi     w2, w0, 0, 16
> +**   mov     w0, 65537
> +**   bfi     w0, w1, 0, 16
> +**   dup     v31\.2s, w2
> +**   dup     v0\.2s, w0
> +**   zip1    v0\.8h, v31\.8h, v0\.8h
> +**   ret
> +*/
> +
> +/*
> +** test_int16_7:
> +**   mov     w2, 0
> +**   bfi     w2, w0, 16, 16
> +**   mov     w0, 65537
> +**   bfi     w0, w1, 16, 16
> +**   dup     v31\.2s, w2
> +**   dup     v0\.2s, w0
> +**   zip1    v0\.8h, v31\.8h, v0\.8h
> +**   ret
> +*/
> +
> +/*
> +** test_int16_8:
> +**   bfi     w0, w1, 16, 16
> +**   movi    v0\.2s, 0x1, lsl 16
> +**   dup     v31\.2s, w0
> +**   zip1    v0\.8h, v0\.8h, v31\.8h
> +**   ret
> +*/
> +
> +/*
> +** test_float32_1:
> +**   dup     v0\.4s, v0\.s\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_float32_2:
> +**   uzp1    v0\.2s, v0\.2s, v1\.2s
> +**   dup     v0\.2d, v0\.d\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_float32_3:
> +**   movi    v31\.2s, 0
> +**   dup     v0\.2s, v0\.s\[0\]
> +**   zip1    v0\.4s, v0\.4s, v31\.4s
> +**   ret
> +*/
> +
> +/*
> +** test_float32_4:
> +**   movi    v31\.2s, 0
> +**   dup     v0\.2s, v0\.s\[0\]
> +**   zip1    v0\.4s, v31\.4s, v0\.4s
> +**   ret
> +*/
> +
> +/*
> +** test_int32_1:
> +**   dup     v0\.4s, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int32_2:
> +**   fmov    s0, w0
> +**   ins     v0\.s\[1\], w1
> +**   dup     v0\.2d, v0\.d\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_int32_3:
> +**   dup     v31\.2s, w0
> +**   movi    v0\.2s, 0
> +**   zip1    v0\.4s, v31\.4s, v0\.4s
> +**   ret
> +*/
> +
> +/*
> +** test_int32_4:
> +**   dup     v31\.2s, w0
> +**   movi    v0\.2s, 0
> +**   zip1    v0\.4s, v0\.4s, v31\.4s
> +**   ret
> +*/
> +
> +/*
> +** test_float64_1:
> +**   dup     v0\.2d, v0\.d\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_int64_1:
> +**   dup     v0\.2d, x0
> +**   ret
> +*/
> --
> 2.43.0


Reply via email to