> -----Original Message-----
> From: Sarvesh Chandra <[email protected]>
> Sent: Tuesday, June 23, 2026 3:17 PM
> To: [email protected]
> Cc: Liu, Hongtao <[email protected]>; Ashwin Godbole
> <[email protected]>; Sarvesh Chandra
> <[email protected]>; Richard Biener <[email protected]>; Uros
> Bizjak <[email protected]>; Venkataramanan Kumar
> <[email protected]>
> Subject: [PATCH v2] i386: Emit vunpcklpd for register V4DF/V8DF movddup
> [PR107057]
> 
> These movddup patterns only accepted a memory source, so duplicating the
> even lanes of a register value spilled it to the stack.  Add a register 
> alternative
> that emits vunpcklpd; a memory source still uses vmovddup.

Ok.

> 
> gcc/ChangeLog:
> 
>       PR target/107057
>       * config/i386/sse.md (avx512f_movddup512<mask_name>): Add a
>       register source alternative that emits vunpcklpd.
>       (avx_movddup256<mask_name>): Likewise.
> 
> gcc/testsuite/ChangeLog:
> 
>       PR target/107057
>       * gcc.target/i386/avx512-movedup.c: New test.
> 
> Co-authored-by: Ashwin Godbole <[email protected]>
> Signed-off-by: Sarvesh Chandra <[email protected]>
> ---
> Bootstrapped and regression-tested on x86_64-pc-linux-gnu.
> 
> v2: add a register alternative instead of reordering the patterns.
> 
> Note: the register alternative is typed sselog1 rather than sselog, as GCC 
> uses
> the sselog1 type for single-source-operand SSE logical insns.
> 
>  gcc/config/i386/sse.md                        | 20 +++++++++++--------
>  .../gcc.target/i386/avx512-movedup.c          | 14 +++++++++++++
>  2 files changed, 26 insertions(+), 8 deletions(-)  create mode 100644
> gcc/testsuite/gcc.target/i386/avx512-movedup.c
> 
> diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index
> 5d9ab8b14eb..74078a772a7 100644
> --- a/gcc/config/i386/sse.md
> +++ b/gcc/config/i386/sse.md
> @@ -13917,18 +13917,20 @@
>     (set_attr "mode" "V2DF,V2DF,V1DF,V1DF,V1DF")])
> 
>  (define_insn "avx512f_movddup512<mask_name>"
> -  [(set (match_operand:V8DF 0 "register_operand" "=v")
> +  [(set (match_operand:V8DF 0 "register_operand" "=v,v")
>       (vec_select:V8DF
>         (vec_concat:V16DF
> -         (match_operand:V8DF 1 "nonimmediate_operand" "m")
> +         (match_operand:V8DF 1 "nonimmediate_operand" "v,m")
>           (match_dup 1))
>         (parallel [(const_int 0) (const_int 8)
>                    (const_int 2) (const_int 10)
>                    (const_int 4) (const_int 12)
>                    (const_int 6) (const_int 14)])))]
>    "TARGET_AVX512F"
> -  "vmovddup\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
> -  [(set_attr "type" "ssemov")
> +  "@
> +
> vunpcklpd\t{%1, %1, %0<mask_operand2>|%0<mask_operand2>, %1, %1}
> +   vmovddup\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
> +  [(set_attr "type" "sselog1,ssemov")
>     (set_attr "prefix" "evex")
>     (set_attr "mode" "V8DF")])
> 
> @@ -13950,16 +13952,18 @@
> 
>  ;; Recall that the 256-bit unpck insns only shuffle within their lanes.
>  (define_insn "avx_movddup256<mask_name>"
> -  [(set (match_operand:V4DF 0 "register_operand" "=v")
> +  [(set (match_operand:V4DF 0 "register_operand" "=v,v")
>       (vec_select:V4DF
>         (vec_concat:V8DF
> -         (match_operand:V4DF 1 "nonimmediate_operand" "m")
> +         (match_operand:V4DF 1 "nonimmediate_operand" "v,m")
>           (match_dup 1))
>         (parallel [(const_int 0) (const_int 4)
>                    (const_int 2) (const_int 6)])))]
>    "TARGET_AVX && <mask_avx512vl_condition>"
> -  "vmovddup\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
> -  [(set_attr "type" "ssemov")
> +  "@
> +
> vunpcklpd\t{%1, %1, %0<mask_operand2>|%0<mask_operand2>, %1, %1}
> +   vmovddup\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
> +  [(set_attr "type" "sselog1,ssemov")
>     (set_attr "prefix" "<mask_prefix>")
>     (set_attr "mode" "V4DF")])
> 
> diff --git a/gcc/testsuite/gcc.target/i386/avx512-movedup.c
> b/gcc/testsuite/gcc.target/i386/avx512-movedup.c
> new file mode 100644
> index 00000000000..3b2943bb67d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/avx512-movedup.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -mavx512f" } */
> +/* { dg-final { scan-assembler "vunpcklpd\[ \\t\]+%zmm\[0-9\]+,
> +%zmm\[0-9\]+" } } */
> +/* { dg-final { scan-assembler "vunpcklpd\[ \\t\]+%ymm\[0-9\]+,
> +%ymm\[0-9\]+" } } */
> +/* { dg-final { scan-assembler "vmovddup\[ \\t\]+\\(" } } */
> +/* { dg-final { scan-assembler-not "vmovddup\[^\\n\]*\\(%\[er\]sp\\)" }
> +} */
> +
> +#include <immintrin.h>
> +
> +__m512d dup512 (__m512d x) { return _mm512_movedup_pd (x); }
> __m256d
> +dup256 (__m256d x) { return _mm256_movedup_pd (x); } __m512d
> +interleave512 (__m512d x) { return _mm512_unpacklo_pd (x, x); } __m256d
> +interleave256 (__m256d x) { return _mm256_unpacklo_pd (x, x); } __m512d
> +load512 (double *p) { return _mm512_movedup_pd (_mm512_loadu_pd
> (p)); }
> --
> 2.34.1

Reply via email to