On Thu Sep 10, 2026 at 12:09 AM PDT, H.J. Lu wrote:
> On Mon, Aug 31, 2026 at 3:43 PM Hongtao Liu <[email protected]> wrote:
>>
>> On Mon, Aug 31, 2026 at 7:34 AM H.J. Lu <[email protected]> wrote:
>> >
>> > Since ZERO_EXTEND TImode store isn't an SSE to integer register move,
>> > treat it as store.
>> For a single ZERO_EXTEND TImode store, movq + movaps is generated, so
>> treating it as store is not correct.
>> The issue in your PR, is not related to the cost of ZERO_EXTEND with
>> memory dest, it's pass_stv is not aware that movq can be CSEed if
>> they're from the same GPR.
>
> I added zero_extend and zero_extend_multiple to track zero-extended
> DImode registers in the v2 patch.
I don't think tracking duplicated zero_extend cost across different chains
is the right direction -- it's better to find out why they end up in
separate chains in the first place.
It looks like fwprop propagates the (zero_extend:TI (reg:DI)) into all
four TI stores because rtx_cost returns 0 for it (on Cascade Lake that
comes from the cost of movzx). The cost of a DImode -> TImode
zero_extend just isn't accurate, so adjusting rtx_cost for it should be
enough to stop the propagation -- then STV sees the zero_extend and the
four stores in a single chain and can do the right thing.
How about?
index a8edf28f687..1e93b0a2084 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -22982,6 +22982,17 @@ 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 standalone double-word zero extension needs an extra
+ instruction to clear the upper half: xor for a register
+ destination, or a store of immediate zero for a memory one.
+ Don't make it as cheap as a register, otherwise CSE propagates
+ it into every TImode store, which is larger and prevents STV
+ from converting the stores with a single integer to SSE move.
+ Keep it cheap as an operand, e.g. of *add<dwi>3_doubleword_zext. */
+ else if (speed && TARGET_64BIT && mode == TImode
+ && outer_code == SET
+ && GET_MODE (XEXP (x, 0)) == DImode)
+ *total = cost->add;
else if (TARGET_ZERO_EXTEND_WITH_AND)
*total = cost->add;
>
>> I don't think it's correct to adjust the cost of ZERO_EXTEND when dest
>> is memory, it's more like limitation of stv don't know further
>> optimization in later rtl passes.
>>
>
> --
> H.J.
> ---
> There are 4 zero-extend TImode stores
>
> (set (mem/c:TI (symbol_ref:DI ("m0") (zero_extend:TI (reg/v:DI 101)))))
>
> in
>
> void
> foo (unsigned long x)
> {
> __int128 m = x;
> m0 = m;
> m1 = m;
> m2 = m;
> m3 = m;
> }
>
> When converting them to V1TI store, we need to zero-extend to V2DImode
> first:
>
> (set (reg:V2DI 102) (vec_concat:V2DI (reg/v:DI 101) (const_int 0 [0])))
> (set (mem/c:V1TI (symbol_ref:DI ("m0")) (subreg:V1TI (reg:V2DI 102) 0)))
>
> Since we only need to zero-extend to V2DImode once for multiple V1TImode
> stores, ignore SSE to integer move cost of multiple zero-extend stores
> of the same register if cost of integer store >= cost of SSE to integer
> move so that all zero-extend stores are converted to V2DImode stores.
>
> gcc/
>
> PR target/127020
> * config/i386/i386-features.cc
> (general_scalar_chain::compute_convert_gain): Add an auto_bitmap
> argument.
> (timode_scalar_chain::compute_convert_gain): Likewise. Ignore
> SSE to integer move cost for multiple zero-extend stores of the
> same register if cost of integer store >= cost of SSE to integer
> move.
> * config/i386/i386-features.h (scalar_chain::compute_convert_gain):
> Add an auto_bitmap argument.
> (general_scalar_chain::compute_convert_gain): Likewise.
> (timode_scalar_chain::compute_convert_gain): Likewise.
>
> gcc/testsuite/
>
> PR target/127020
> * gcc.target/i386/sse4_1-stv-15.c: New file.
> * gcc.target/i386/sse4_1-stv-16.c: Likewise.