> -----Original Message-----
> From: Sarvesh Chandra <[email protected]>
> Sent: Monday, June 22, 2026 6:28 PM
> To: [email protected]
> Cc: Richard Biener <[email protected]>; Uros Bizjak <[email protected]>;
> Liu, Hongtao <[email protected]>; Venkataramanan Kumar
> <[email protected]>; Sarvesh Chandra <[email protected]>;
> Ashwin Godbole <[email protected]>
> Subject: [PATCH] i386: Match vunpcklpd before vmovddup for V4DF/V8DF
> interleave [PR107057]
> 
> An even-lane duplicate of a register operand matched the movddup pattern,
> whose memory-only operand forced the register to be spilled to the stack and
> reloaded.  List the unpcklpd patterns before the movddup patterns so a
> register interleave selects vunpcklpd, while a genuine memory load still folds
> into vmovddup.

Reordering the patterns sounds fragile, could you just extend 
avx512f_movddup512<mask_name> to handle register constraint?

.i.e 

  (define_insn "avx512f_movddup512<mask_name>"
    [(set (match_operand:V8DF 0 "register_operand" "=v,v")
        (vec_select:V8DF
          (vec_concat:V16DF
            (match_operand:V8DF 1 "nonimmediate_operand" "v,m")
            (match_dup 1))
          (parallel [(const_int 0) (const_int 8) ...])))]
    "TARGET_AVX512F"
    "@
     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" "sselog,ssemov")
     (set_attr "prefix" "evex")
     (set_attr "mode" "V8DF")])

Apply the same to movddup512/movddup256

> 
> gcc/ChangeLog:
> 
>       PR target/107057
>       * config/i386/sse.md (avx512f_unpcklpd512): Move before
>       avx512f_movddup512.
>       (avx_unpcklpd256): Move before avx_movddup256.
> 
> 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.
> 
>  gcc/config/i386/sse.md                         |   44 
> ++++++++++++------------
>  gcc/testsuite/gcc.target/i386/avx512-movedup.c |   16 +++++++++
>  2 files changed, 38 insertions(+), 22 deletions(-)
> 
> diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index
> 5d9ab8b14eb..f13232f0e7c 100644
> --- a/gcc/config/i386/sse.md
> +++ b/gcc/config/i386/sse.md
> @@ -13916,64 +13916,64 @@
>     (set_attr "prefix" "orig,maybe_evex,orig,maybe_evex,maybe_vex")
>     (set_attr "mode" "V2DF,V2DF,V1DF,V1DF,V1DF")])
> 
> -(define_insn "avx512f_movddup512<mask_name>"
> +(define_insn "avx512f_unpcklpd512<mask_name>"
>    [(set (match_operand:V8DF 0 "register_operand" "=v")
>       (vec_select:V8DF
>         (vec_concat:V16DF
> -         (match_operand:V8DF 1 "nonimmediate_operand" "m")
> -         (match_dup 1))
> +         (match_operand:V8DF 1 "register_operand" "v")
> +         (match_operand:V8DF 2 "nonimmediate_operand" "vm"))
>         (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{%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %2}"
> +  [(set_attr "type" "sselog")
>     (set_attr "prefix" "evex")
>     (set_attr "mode" "V8DF")])
> 
> -(define_insn "avx512f_unpcklpd512<mask_name>"
> +(define_insn "avx512f_movddup512<mask_name>"
>    [(set (match_operand:V8DF 0 "register_operand" "=v")
>       (vec_select:V8DF
>         (vec_concat:V16DF
> -         (match_operand:V8DF 1 "register_operand" "v")
> -         (match_operand:V8DF 2 "nonimmediate_operand" "vm"))
> +         (match_operand:V8DF 1 "nonimmediate_operand" "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"
> -
> "vunpcklpd\t{%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %2}"
> -  [(set_attr "type" "sselog")
> +  "vmovddup\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
> +  [(set_attr "type" "ssemov")
>     (set_attr "prefix" "evex")
>     (set_attr "mode" "V8DF")])
> 
>  ;; 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")
> +(define_insn "avx_unpcklpd256<mask_name>"
> +  [(set (match_operand:V4DF 0 "register_operand"         "=v")
>       (vec_select:V4DF
>         (vec_concat:V8DF
> -         (match_operand:V4DF 1 "nonimmediate_operand" "m")
> -         (match_dup 1))
> +         (match_operand:V4DF 1 "register_operand" " v")
> +         (match_operand:V4DF 2 "nonimmediate_operand" "vm"))
>         (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{%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %2}"
> +  [(set_attr "type" "sselog")
>     (set_attr "prefix" "<mask_prefix>")
>     (set_attr "mode" "V4DF")])
> 
> -(define_insn "avx_unpcklpd256<mask_name>"
> -  [(set (match_operand:V4DF 0 "register_operand"         "=v")
> +(define_insn "avx_movddup256<mask_name>"
> +  [(set (match_operand:V4DF 0 "register_operand" "=v")
>       (vec_select:V4DF
>         (vec_concat:V8DF
> -         (match_operand:V4DF 1 "register_operand" " v")
> -         (match_operand:V4DF 2 "nonimmediate_operand" "vm"))
> +         (match_operand:V4DF 1 "nonimmediate_operand" "m")
> +         (match_dup 1))
>         (parallel [(const_int 0) (const_int 4)
>                    (const_int 2) (const_int 6)])))]
>    "TARGET_AVX && <mask_avx512vl_condition>"
> -
> "vunpcklpd\t{%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %2}"
> -  [(set_attr "type" "sselog")
> +  "vmovddup\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
> +  [(set_attr "type" "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..20e78dfcb16
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/avx512-movedup.c
> @@ -0,0 +1,16 @@
> +/* { 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