On Thu, Oct 15, 2026 at 9:31 AM liuhongt <[email protected]> wrote:
>
> The zero movzx cost in Skylake and Ice Lake tunings makes CSE duplicate
> DImode to TImode zero extensions into stores, preventing STV conversion.
>
> Use the add cost for standalone extensions when optimizing for speed,
> since clearing the upper word requires an extra instruction.
>
> SImode to DImode zero extensions in 32-bit mode are left unchanged,
> since treating zero_extend as free appears to produce better 32-bit
> code.
>
> Bootstrapped and retested on x86_64-pc-linux-gnu{-m32,}.
> Ok for trunk?
>
> gcc/ChangeLog:
>
>         PR target/127020
>         * config/i386/i386.cc (ix86_rtx_costs): Use the add cost for
>         standalone DImode to TImode zero extensions when optimizing for
>         speed.
>
> gcc/testsuite/ChangeLog:
>
>         PR target/127020
>         * gcc.target/i386/pr127020.c: New test.
>
> Co-authored-by: H.J. Lu <[email protected]>
> ---
>  gcc/config/i386/i386.cc                  |  8 ++++++++
>  gcc/testsuite/gcc.target/i386/pr127020.c | 16 ++++++++++++++++
>  2 files changed, 24 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr127020.c
>
> diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
> index a8edf28f687..2291ec7a88e 100644
> --- a/gcc/config/i386/i386.cc
> +++ b/gcc/config/i386/i386.cc
> @@ -22982,6 +22982,14 @@ ix86_rtx_costs (rtx x, machine_mode mode, int 
> outer_code_i, int opno,
>        if (TARGET_64BIT && mode == DImode
>           && GET_MODE (XEXP (x, 0)) == SImode)
>         *total = 1;
> +      /* A DImode to TImode zero extension needs an extra instruction to
> +        clear the upper word; don't let a zero movzx cost make it look
> +        free, or CSE copies it into every TImode store and STV can no
> +        longer share one vector register.  */
> +      else if (speed && TARGET_64BIT && mode == TImode
> +              && outer_code == SET
> +              && GET_MODE (XEXP (x, 0)) == DImode)
> +       *total = cost->add;

This can also handle 32-bit targets with:

else if (speed && GET_MODE_SIZE (mode) > GET_MODE_SIZE (word_mode))
&& ...
&& GET_MODE (...) == word_mode.

(the last check is also semi-redundant, there are no patterns that
zext from other modes than word mode, but won't hurt anyway)

with a comment updated to something like:

Zero extension to a double-word mode (TImode on x86-64, DImode on
ia32) is not a single movzx: the upper word must be cleared by a
separate instruction. Charge for it; a zero or too-low cost makes the
extension look free, so CSE copies the extended value into every
TImode store and STV can no longer share one vector register.

Uros.

>        else if (TARGET_ZERO_EXTEND_WITH_AND)
>         *total = cost->add;
>        else
> diff --git a/gcc/testsuite/gcc.target/i386/pr127020.c 
> b/gcc/testsuite/gcc.target/i386/pr127020.c
> new file mode 100644
> index 00000000000..4adc17cfc4c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr127020.c
> @@ -0,0 +1,16 @@
> +/* PR target/127020 */
> +/* { dg-do compile { target int128 } } */
> +/* { dg-options "-O2 -msse4.1 -mtune=cascadelake -mstv -mno-stackrealign" } 
> */
> +
> +extern __int128 m0, m1, m2, m3;
> +
> +void
> +foo (unsigned long x)
> +{
> +  m0 = x;
> +  m1 = x;
> +  m2 = x;
> +  m3 = x;
> +}
> +
> +/* { dg-final { scan-assembler-times "(movaps|vmovdqa)" 4 } } */
> --
> 2.34.1
>

Reply via email to