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
>