Hi Art,

> -----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 4/4] aarch64/sve: combine AdvSIMD and SVE
> vec_duplicates
> 
> Currently, to duplicate a 64-bit or narrower value into a SVE register, we
> choose to go via an intermediate 128-bit AdvSIMD register, viz.:
> 
> svfloat32_t foo(float x) {
>     return svdupq_n_f32(x, x, x, x);
> }
> 
> which will produce the following code:
> 
>         dup     v0.4s, v0.s[0]
>         dup     z0.q, z0.q[0]
>         ret
> 
> when compiled with -O2 -march=armv9-a+sve.
> 
> This can be simplified into a single dup instruction going to an SVE
> register directly from a scalar (or a smaller vector) value:
> 
>       mov     z0.s, s0
>       ret
> 
> To facilitate this, this patch adds a pattern that combine can use to
> merge two vec_duplicate instructions (scalar -> AdvSIMD and AdvSIMD ->
> SVE) into a single one (scalar -> SVE).
> 
> To demonstrate the effect of this patch, the vec-init-23.c test from
> AdvSIMD was reused as a new SVE test (vec_init_5.c).
> 
> gcc/ChangeLog:
> 
>         * config/aarch64/aarch64-sve.md
>       (*aarch64_vec_duplicate_subvector<vconsv><vconq><mode>):
>       New pattern.
>       * config/aarch64/iterators.md (VCONSV): New mode attribute.
>       (vconsv): Likewise.
> 
> gcc/testsuite/ChangeLog:
> 
>         * gcc.target/aarch64/sve/vec_init_5.c: New test.

OK.

Thanks,
Tamar

> ---
>  gcc/config/aarch64/aarch64-sve.md             |  14 +
>  gcc/config/aarch64/iterators.md               |  24 ++
>  .../gcc.target/aarch64/sve/vec_init_5.c       | 382 ++++++++++++++++++
>  3 files changed, 420 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/vec_init_5.c
> 
> diff --git a/gcc/config/aarch64/aarch64-sve.md
> b/gcc/config/aarch64/aarch64-sve.md
> index 019630eb8d2..ba46e2871e0 100644
> --- a/gcc/config/aarch64/aarch64-sve.md
> +++ b/gcc/config/aarch64/aarch64-sve.md
> @@ -2890,6 +2890,20 @@
>    [(set_attr "sve_type" "sve_int_general")]
>  )
> 
> +;; Initialize an SVE vector by duplicating a 128-bit AdvSIMD register that
> +;; itself contains a duplicated scalar or subvector value.
> +(define_insn "*aarch64_vec_duplicate_subvector<vconsv><vconq><mode>"
> +  [(set (match_operand:<VCONSV> 0 "register_operand")
> +     (vec_duplicate:<VCONSV>
> +       (vec_duplicate:<VCONQ>
> +         (match_operand:VQDUP 1 "register_operand"))))]
> +  "TARGET_SVE"
> +  {@ [ cons: =0 , 1 ]
> +     [ w        , r ] mov\t%0.<single_type>, %<single_wx>1
> +     [ w        , w ] mov\t%0.<single_type>, %<single_type>1
> +  }
> +)
> +
>  ;; This is used for vec_duplicate<mode>s from memory, but can also
>  ;; be used by combine to optimize selects of a vec_duplicate<mode>
>  ;; with zero.
> diff --git a/gcc/config/aarch64/iterators.md
> b/gcc/config/aarch64/iterators.md
> index 462f2d996f0..41410095ba3 100644
> --- a/gcc/config/aarch64/iterators.md
> +++ b/gcc/config/aarch64/iterators.md
> @@ -1995,6 +1995,30 @@
>                        (HI   "v8hi") (QI   "v16qi")
>                        (SF   "v4sf") (DF   "v2df")])
> 
> +;; SVE container modes for duplication into a full SVE register.
> +(define_mode_attr VCONSV [(V8QI "VNx16QI") (V4QI "VNx16QI")
> +                       (V2QI "VNx16QI") (QI "VNx16QI")
> +                       (V4HI "VNx8HI") (V2HI "VNx8HI")
> +                       (HI "VNx8HI") (V2SI "VNx4SI")
> +                       (SI "VNx4SI") (DI "VNx2DI")
> +                       (V4BF "VNx8BF") (V2BF "VNx8BF")
> +                       (BF "VNx8BF") (V4HF "VNx8HF")
> +                       (V2HF "VNx8HF") (HF "VNx8HF")
> +                       (V2SF "VNx4SF") (SF "VNx4SF")
> +                       (DF "VNx2DF")])
> +
> +;; Same as above, but in lowercase.
> +(define_mode_attr vconsv [(V8QI "vnx16qi") (V4QI "vnx16qi")
> +                       (V2QI "vnx16qi") (QI "vnx16qi")
> +                       (V4HI "vnx8hi") (V2HI "vnx8hi")
> +                       (HI "vnx8hi") (V2SI "vnx4si")
> +                       (SI "vnx4si") (DI "vnx2di")
> +                       (V4BF "vnx8bf") (V2BF "vnx8bf")
> +                       (BF "vnx8bf") (V4HF "vnx8hf")
> +                       (V2HF "vnx8hf") (HF "vnx8hf")
> +                       (V2SF "vnx4sf") (SF "vnx4sf")
> +                       (DF "vnx2df")])
> +
>  ;; Half modes of all vector modes.
>  (define_mode_attr VHALF [(V8QI "V4QI")  (V16QI "V8QI")
>                        (V4HI "V2HI")  (V8HI  "V4HI")
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vec_init_5.c
> b/gcc/testsuite/gcc.target/aarch64/sve/vec_init_5.c
> new file mode 100644
> index 00000000000..99e04aac265
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve/vec_init_5.c
> @@ -0,0 +1,382 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +/* { dg-final { check-function-bodies "**" "" "" } } */
> +
> +#include <arm_sve.h>
> +
> +#define TESTCASE(TYPE, ETYPE, T, SZ, NUM, MULT, ...)\
> +  sv##TYPE##SZ##_t test_##TYPE##SZ##_##NUM (ETYPE x0, ETYPE x1, ETYPE
> x2, ETYPE x3,\
> +                                         ETYPE x4, ETYPE x5, ETYPE x6, ETYPE
> x7)\
> +  {\
> +    return svdupq_n_##T##SZ (__VA_ARGS__);\
> +  }
> +
> +#include "../vec-init-23.c"
> +
> +/*
> +** test_int8_1:
> +**   mov     z0\.b, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int8_2:
> +**   bfi     w0, w1, 8, 8
> +**   mov     z0\.h, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int8_3:
> +**   bfi     w0, w1, 8, 8
> +**   bfi     w0, w2, 16, 8
> +**   bfi     w0, w3, 24, 8
> +**   mov     z0\.s, 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     v30\.2s, w1
> +**   zip1    v31\.16b, v31\.16b, v30\.16b
> +**   dup     z0\.q, z31\.q\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_int8_5:
> +**   uxtb    w0, w0
> +**   mov     z0\.h, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int8_6:
> +**   mov     w1, 0
> +**   bfi     w1, w0, 8, 8
> +**   mov     z0\.h, w1
> +**   ret
> +*/
> +
> +/*
> +** test_int8_7:
> +**   mov     w2, 16777472
> +**   bfi     w2, w0, 0, 8
> +**   bfi     w2, w1, 8, 8
> +**   mov     z0\.s, w2
> +**   ret
> +*/
> +
> +/*
> +** test_int8_8:
> +**   mov     w2, 16777472
> +**   bfi     w2, w0, 16, 8
> +**   bfi     w2, w1, 24, 8
> +**   mov     z0\.s, w2
> +**   ret
> +*/
> +
> +/*
> +** test_int8_9:
> +**   mov     w2, 16777216
> +**   bfi     w2, w0, 0, 8
> +**   bfi     w2, w1, 16, 8
> +**   mov     z0.s, 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     d30, \[x0, #:lo12:.LANCHOR[0-9]+\]
> +**   zip1    v31\.16b, v31\.16b, v30\.16b
> +**   dup     z0\.q, z31\.q\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_int8_11:
> +**   bfi     w0, w1, 8, 8
> +**   adrp    x4, .LANCHOR[0-9]+
> +**   bfi     w0, w2, 16, 8
> +**   ldr     d31, \[x4, #:lo12:\.LANCHOR[0-9]+\]
> +**   bfi     w0, w3, 24, 8
> +**   dup     v30\.2s, w0
> +**   zip1    v31\.16b, v31\.16b, v30\.16b
> +**   dup     z0\.q, z31\.q\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_int8_12:
> +**   mov     w4, 255
> +**   movk    w4, 0x201, lsl 16
> +**   bfi     w4, w0, 0, 8
> +**   mov     w0, 256
> +**   movk    w0, 0x302, lsl 16
> +**   bfi     w0, w1, 0, 8
> +**   bfi     w4, w2, 16, 8
> +**   bfi     w0, w3, 16, 8
> +**   dup     v31\.2s, w4
> +**   dup     v30\.2s, w0
> +**   zip1    v31\.16b, v31\.16b, v30\.16b
> +**   dup     z0\.q, z31\.q\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_int8_13:
> +**   mov     w4, 256
> +**   movk    w4, 0x302, lsl 16
> +**   bfi     w4, w0, 8, 8
> +**   mov     w0, 513
> +**   movk    w0, 0x403, lsl 16
> +**   bfi     w0, w1, 8, 8
> +**   bfi     w4, w2, 24, 8
> +**   bfi     w0, w3, 24, 8
> +**   dup     v31\.2s, w4
> +**   dup     v30\.2s, w0
> +**   zip1    v31\.16b, v31\.16b, v30\.16b
> +**   dup     z0\.q, z31\.q\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_float16_1:
> +**   fcvt    h0, s0
> +**   mov     z0\.h, h0
> +**   ret
> +*/
> +
> +/*
> +** test_float16_2:
> +**   fcvt    h1, s1
> +**   fcvt    h0, s0
> +**   uzp1    v0\.4h, v0\.4h, v1\.4h
> +**   mov     z0\.s, s0
> +**   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   v3\.4h, v3\.4s
> +**   mov     z0\.d, d3
> +**   ret
> +*/
> +
> +/*
> +** test_float16_4:
> +**   fcvt    h0, s0
> +**   fmov    h0, h0
> +**   mov     z0\.s, s0
> +**   ret
> +*/
> +
> +/*
> +** test_float16_5:
> +**   movi    v31\.4h, #0
> +**   fcvt    h0, s0
> +**   uzp1    v0\.4h, v31\.4h, v0\.4h
> +**   mov     z0\.s, s0
> +**   ret
> +*/
> +
> +/*
> +** test_float16_6:
> +**   fcvt    h2, s0
> +**   fcvt    h1, s1
> +**   fmov    h31, 1.0e\+0
> +**   fmov    h2, h2
> +**   uzp1    v1\.4h, v1\.4h, v31\.4h
> +**   dup     v0\.2s, v2\.s\[0\]
> +**   dup     v1\.2s, v1\.s\[0\]
> +**   zip1    v0\.8h, v0\.8h, v1\.8h
> +**   dup     z0\.q, z0\.q\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_float16_7:
> +**   fcvt    h3, s0
> +**   fcvt    h2, s1
> +**   movi    v0\.4h, #0
> +**   fmov    h1, 1.0e\+0
> +**   uzp1    v1\.4h, v1\.4h, v2\.4h
> +**   uzp1    v0\.4h, v0\.4h, v3\.4h
> +**   dup     v1\.2s, v1\.s\[0\]
> +**   dup     v0\.2s, v0\.s\[0\]
> +**   zip1    v0\.8h, v0\.8h, v1\.8h
> +**   dup     z0\.q, z0\.q\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_float16_8:
> +**   fcvt    h1, s1
> +**   fcvt    h0, s0
> +**   movi    v31\.2s, 0x3c, lsl 24
> +**   uzp1    v0\.4h, v0\.4h, v1.4h
> +**   dup     v0\.2s, v0\.s\[0\]
> +**   zip1    v0\.8h, v31\.8h, v0\.8h
> +**   dup     z0\.q, z0\.q\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_int16_1:
> +**   mov     z0\.h, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int16_2:
> +**   bfi     w0, w1, 16, 16
> +**   mov     z0\.s, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int16_3:
> +**   bfi     w0, w2, 16, 16
> +**   bfi     w1, w3, 16, 16
> +**   dup     v31\.2s, w0
> +**   dup     v30\.2s, w1
> +**   zip1    v31\.8h, v31\.8h, v30\.8h
> +**   dup     z0\.q, z31\.q\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_int16_4:
> +**   uxth    w0, w0
> +**   mov     z0\.s, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int16_5:
> +**   mov     w1, 0
> +**   bfi     w1, w0, 16, 16
> +**   mov     z0\.s, w1
> +**   ret
> +*/
> +
> +/*
> +** test_int16_6:
> +**   uxth    w0, w0
> +**   dup     v31\.2s, w0
> +**   mov     w0, 1
> +**   bfi     w1, w0, 16, 16
> +**   dup     v30\.2s, w1
> +**   zip1    v31\.8h, v31\.8h, v30\.8h
> +**   dup     z0\.q, z31\.q\[0\]
> +**   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     v30\.2s, w0
> +**   zip1    v31\.8h, v31\.8h, v30\.8h
> +**   dup     z0\.q, z31\.q\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_int16_8:
> +**   bfi     w0, w1, 16, 16
> +**   movi    v31\.2s, 0x1, lsl 16
> +**   dup     v30\.2s, w0
> +**   zip1    v31\.8h, v31\.8h, v30\.8h
> +**   dup     z0\.q, z31\.q\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_float32_1:
> +**   mov     z0\.s, s0
> +**   ret
> +*/
> +
> +/*
> +** test_float32_2:
> +**   uzp1    v0\.2s, v0\.2s, v1\.2s
> +**   mov     z0\.d, d0
> +**   ret
> +*/
> +
> +/*
> +** test_float32_3:
> +**   fmov    s0, s0
> +**   mov     z0\.d, d0
> +**   ret
> +*/
> +
> +/*
> +** test_float32_4:
> +**   movi    v31\.2s, #0
> +**   uzp1    v0\.2s, v31\.2s, v0\.2s
> +**   mov     z0\.d, d0
> +**   ret
> +*/
> +
> +/*
> +** test_int32_1:
> +**   mov     z0\.s, w0
> +**   ret
> +*/
> +
> +/*
> +** test_int32_2:
> +**   fmov    s0, w0
> +**   ins     v0\.s\[1\], w1
> +**   mov     z0\.d, d0
> +**   ret
> +*/
> +
> +/*
> +** test_int32_3:
> +**   fmov    s0, w0
> +**   mov     z0\.d, d0
> +**   ret
> +*/
> +
> +/*
> +** test_int32_4:
> +**   dup     v30\.2s, w0
> +**   movi    v31\.2s, 0
> +**   zip1    v31\.4s, v31\.4s, v30\.4s
> +**   dup     z0\.q, z31\.q\[0\]
> +**   ret
> +*/
> +
> +/*
> +** test_int64_1:
> +**   mov     z0\.d, x0
> +**   ret
> +*/
> +
> +/*
> +** test_float64_1:
> +**   mov     z0\.d, d0
> +**   ret
> +*/
> +
> --
> 2.43.0

Reply via email to