Hi Kyrill,

Sorry missed this.

> -----Original Message-----
> From: [email protected] <[email protected]>
> Sent: 07 October 2026 14:22
> To: [email protected]
> Cc: Kyrylo Tkachov <[email protected]>; Tamar Christina
> <[email protected]>; Wilco Dijkstra <[email protected]>
> Subject: [PATCH v2 3/4] aarch64: insert general registers into zero SVE 
> vectors
> directly
> 
> From: Kyrylo Tkachov <[email protected]>
> 
> The patterns that insert a scalar into element 0 of a zero SVE vector
> accept the scalar only in an FP register.  A scalar in a general
> register needs an extra move:
> 
>       fmov    s0, w0
>       fmov    s0, s0
> 
> and, for 8-bit elements:
> 
>       dup     v31.8b, w0
>       fmov    h0, h31
>       and     z0.h, z0.h, #0xff
> 
> Add alternatives that take the scalar from a general register.  FMOV
> from a general register also clears the rest of the vector.
> 
> Bootstrapped and tested on aarch64-none-linux-gnu.
> Ok for trunk?

OK.

Thanks,
Tamar

> Thanks,
> Kyrill
> 
> Cc: Tamar Christina <[email protected]>
> Cc: Wilco Dijkstra <[email protected]>
> 
> gcc/ChangeLog:
> 
>       * config/aarch64/aarch64-sve.md
>       (*aarch64_vec_shl_insert_into_zero_<mode>): Add an alternative for
>       general registers.  Give the instruction type per alternative.
>       (*aarch64_vec_shl_insert_into_zero_vnx16qi): Likewise.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.target/aarch64/sve/copsi.c (func_init3): Update expected
>       assembly.
>       * gcc.target/aarch64/sve/insr-zero-gpr.c: New test.
>       * gcc.target/aarch64/sve/insr-zero-gpr_run.c: New test.
> 
> Signed-off-by: Kyrylo Tkachov <[email protected]>
> ---
> Changes since v1:
> - Also handle 8-bit elements (*aarch64_vec_shl_insert_into_zero_vnx16qi).
> - Use the attrs column for the instruction type.
> - Test the floating-point element types too.  Rename the run test to
>   insr-zero-gpr_run.c.
> 
>  gcc/config/aarch64/aarch64-sve.md             |  12 +-
>  gcc/testsuite/gcc.target/aarch64/sve/copsi.c  |   1 -
>  .../gcc.target/aarch64/sve/insr-zero-gpr.c    | 165 ++++++++++++++++++
>  .../aarch64/sve/insr-zero-gpr_run.c           |  72 ++++++++
>  4 files changed, 243 insertions(+), 7 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/insr-zero-
> gpr_run.c
> 
> diff --git a/gcc/config/aarch64/aarch64-sve.md
> b/gcc/config/aarch64/aarch64-sve.md
> index dc92cef4d..735983e4d 100644
> --- a/gcc/config/aarch64/aarch64-sve.md
> +++ b/gcc/config/aarch64/aarch64-sve.md
> @@ -3029,10 +3029,10 @@
>          (match_operand:<VEL> 2 "register_operand")]
>         UNSPEC_INSR))]
>    "TARGET_SVE"
> -  {@ [ cons: =0 , 1  , 2 ]
> -     [ w        , Dz , w ] fmov\t%<Vetype>0, %<Vetype>2
> +  {@ [ cons: =0 , 1  , 2 ; attrs: type ]
> +     [ w        , Dz , w ; neon_move    ] fmov\t%<Vetype>0, %<Vetype>2
> +     [ w        , Dz , r ; f_mcr        ] fmov\t%<Vetype>0, %<vccore>2
>    }
> -  [(set_attr "type" "neon_move")]
>  )
> 
>  ;; Shift an SVE vector left and insert a scalar into element 0 of a zero
> @@ -3044,10 +3044,10 @@
>          (match_operand:QI 2 "register_operand")]
>         UNSPEC_INSR))]
>    "TARGET_SVE"
> -  {@ [ cons: =0 , 1  , 2 ; attrs: length ]
> -     [ w        , Dz , w ; 8              ] fmov\t%h0, %h2\;and\t%0.h, %0.h, 
> #0xff
> +  {@ [ cons: =0 , 1  , 2 ; attrs: length , type      ]
> +     [ w        , Dz , w ; 8              , neon_move ] fmov\t%h0, 
> %h2\;and\t%0.h,
> %0.h, #0xff
> +     [ w        , Dz , r ; 8              , f_mcr     ] fmov\t%h0, 
> %w2\;and\t%0.h, %0.h,
> #0xff
>    }
> -  [(set_attr "type" "neon_move")]
>  )
> 
>  ;; Shift an SVE vector left and insert a scalar into element 0 from a memory
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/copsi.c
> b/gcc/testsuite/gcc.target/aarch64/sve/copsi.c
> index d85403640..6bcbffe64 100644
> --- a/gcc/testsuite/gcc.target/aarch64/sve/copsi.c
> +++ b/gcc/testsuite/gcc.target/aarch64/sve/copsi.c
> @@ -20,7 +20,6 @@ func_init4 (int64_t a, int64_t b)
>  /*
>  ** func_init3:
>  **   fmov    s0, w2
> -**   fmov    s0, s0
>  **   insr    z0\.s, w1
>  **   insr    z0\.s, w0
>  **   ret
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr.c
> b/gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr.c
> new file mode 100644
> index 000000000..4aaf9bfd4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr.c
> @@ -0,0 +1,165 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +
> +#include <arm_sve.h>
> +#include <string.h>
> +
> +/* Insert a scalar from a general register into an otherwise zero vector.
> +   The scalar move also clears the rest of the SVE register.  */
> +
> +/*
> +** zero_8:
> +**   fmov    h0, w0
> +**   and     z0\.h, z0\.h, #0xff
> +**   ret
> +*/
> +__attribute__ ((noipa))
> +svuint8_t
> +zero_8 (uint8_t value)
> +{
> +  return svinsr_n_u8 (svdup_n_u8 (0), value);
> +}
> +
> +/*
> +** nonzero_8:
> +**   insr    z0\.b, w0
> +**   ret
> +*/
> +__attribute__ ((noipa))
> +svuint8_t
> +nonzero_8 (svuint8_t vector, uint8_t value)
> +{
> +  return svinsr_n_u8 (vector, value);
> +}
> +
> +/*
> +** zero_16:
> +**   fmov    h0, w0
> +**   ret
> +*/
> +__attribute__ ((noipa))
> +svuint16_t
> +zero_16 (uint16_t value)
> +{
> +  return svinsr_n_u16 (svdup_n_u16 (0), value);
> +}
> +
> +/*
> +** nonzero_16:
> +**   insr    z0\.h, w0
> +**   ret
> +*/
> +__attribute__ ((noipa))
> +svuint16_t
> +nonzero_16 (svuint16_t vector, uint16_t value)
> +{
> +  return svinsr_n_u16 (vector, value);
> +}
> +
> +/*
> +** zero_32:
> +**   fmov    s0, w0
> +**   ret
> +*/
> +__attribute__ ((noipa))
> +svuint32_t
> +zero_32 (uint32_t value)
> +{
> +  return svinsr_n_u32 (svdup_n_u32 (0), value);
> +}
> +
> +/*
> +** nonzero_32:
> +**   insr    z0\.s, w0
> +**   ret
> +*/
> +__attribute__ ((noipa))
> +svuint32_t
> +nonzero_32 (svuint32_t vector, uint32_t value)
> +{
> +  return svinsr_n_u32 (vector, value);
> +}
> +
> +/*
> +** zero_64:
> +**   fmov    d0, x0
> +**   ret
> +*/
> +__attribute__ ((noipa))
> +svuint64_t
> +zero_64 (uint64_t value)
> +{
> +  return svinsr_n_u64 (svdup_n_u64 (0), value);
> +}
> +
> +/*
> +** nonzero_64:
> +**   insr    z0\.d, x0
> +**   ret
> +*/
> +__attribute__ ((noipa))
> +svuint64_t
> +nonzero_64 (svuint64_t vector, uint64_t value)
> +{
> +  return svinsr_n_u64 (vector, value);
> +}
> +
> +/* The same applies to floating-point elements whose bits are in a general
> +   register.  */
> +
> +/*
> +** zero_f16:
> +**   fmov    h0, w0
> +**   ret
> +*/
> +__attribute__ ((noipa))
> +svfloat16_t
> +zero_f16 (uint16_t bits)
> +{
> +  float16_t value;
> +  memcpy (&value, &bits, sizeof (value));
> +  return svinsr_n_f16 (svdup_n_f16 (0), value);
> +}
> +
> +/*
> +** zero_bf16:
> +**   fmov    h0, w0
> +**   ret
> +*/
> +__attribute__ ((noipa))
> +svbfloat16_t
> +zero_bf16 (uint16_t bits)
> +{
> +  bfloat16_t value;
> +  memcpy (&value, &bits, sizeof (value));
> +  return svinsr_n_bf16 (svreinterpret_bf16 (svdup_n_u16 (0)), value);
> +}
> +
> +/*
> +** zero_f32:
> +**   fmov    s0, w0
> +**   ret
> +*/
> +__attribute__ ((noipa))
> +svfloat32_t
> +zero_f32 (uint32_t bits)
> +{
> +  float32_t value;
> +  memcpy (&value, &bits, sizeof (value));
> +  return svinsr_n_f32 (svdup_n_f32 (0), value);
> +}
> +
> +/*
> +** zero_f64:
> +**   fmov    d0, x0
> +**   ret
> +*/
> +__attribute__ ((noipa))
> +svfloat64_t
> +zero_f64 (uint64_t bits)
> +{
> +  float64_t value;
> +  memcpy (&value, &bits, sizeof (value));
> +  return svinsr_n_f64 (svdup_n_f64 (0), value);
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr_run.c
> b/gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr_run.c
> new file mode 100644
> index 000000000..37d56a2a7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr_run.c
> @@ -0,0 +1,72 @@
> +/* { dg-do run { target aarch64_sve_hw } } */
> +/* { dg-options "-O2" } */
> +
> +#include "insr-zero-gpr.c"
> +
> +#define CHECK(BITS, COUNT) \
> +static __attribute__ ((noinline, noclone)) void \
> +check_##BITS (uint##BITS##_t value) \
> +{ \
> +  unsigned long count = COUNT; \
> +  uint##BITS##_t input[count], output[count]; \
> +  for (unsigned long i = 0; i < count; ++i) \
> +    input[i] = (uint##BITS##_t) (i * 13 + 7); \
> +  svst1_u##BITS (svptrue_b##BITS (), output, zero_##BITS (value)); \
> +  if (output[0] != value) \
> +    __builtin_abort (); \
> +  for (unsigned long i = 1; i < count; ++i) \
> +    if (output[i] != 0) \
> +      __builtin_abort (); \
> +  svuint##BITS##_t v = svld1_u##BITS (svptrue_b##BITS (), input); \
> +  svst1_u##BITS (svptrue_b##BITS (), output, nonzero_##BITS (v, value)); \
> +  if (output[0] != value) \
> +    __builtin_abort (); \
> +  for (unsigned long i = 1; i < count; ++i) \
> +    if (output[i] != input[i - 1]) \
> +      __builtin_abort (); \
> +}
> +
> +CHECK (8, svcntb ())
> +CHECK (16, svcnth ())
> +CHECK (32, svcntw ())
> +CHECK (64, svcntd ())
> +
> +#define CHECK_FLOAT(NAME, BITS, COUNT) \
> +static __attribute__ ((noinline, noclone)) void \
> +check_##NAME (uint##BITS##_t value) \
> +{ \
> +  unsigned long count = COUNT; \
> +  uint##BITS##_t output[count]; \
> +  svst1_u##BITS (svptrue_b##BITS (), output, \
> +              svreinterpret_u##BITS (zero_##NAME (value))); \
> +  if (output[0] != value) \
> +    __builtin_abort (); \
> +  for (unsigned long i = 1; i < count; ++i) \
> +    if (output[i] != 0) \
> +      __builtin_abort (); \
> +}
> +
> +CHECK_FLOAT (f16, 16, svcnth ())
> +CHECK_FLOAT (bf16, 16, svcnth ())
> +CHECK_FLOAT (f32, 32, svcntw ())
> +CHECK_FLOAT (f64, 64, svcntd ())
> +
> +int
> +main (void)
> +{
> +  const uint64_t values[] = { 0, 1, 0x80, 0x8000, 0x80000000ULL,
> +                          0x8000000000000000ULL, UINT64_MAX,
> +                          0x123456789abcdef0ULL };
> +  for (unsigned int i = 0; i < sizeof (values) / sizeof (values[0]); ++i)
> +    {
> +      check_8 (values[i]);
> +      check_16 (values[i]);
> +      check_32 (values[i]);
> +      check_64 (values[i]);
> +      check_f16 (values[i]);
> +      check_bf16 (values[i]);
> +      check_f32 (values[i]);
> +      check_f64 (values[i]);
> +    }
> +  return 0;
> +}
> --
> 2.43.0

Reply via email to