On Tue, Sep 29, 2026 at 1:21 PM Richard Biener <[email protected]> wrote:
>
> For the testcase in PR127633 we combine two adjacent DFmode loads from
> the stack into a V2DFmode via a peephole2 that uses adjust_address.
> That unfortunately leaves both the MEM_EXPR and the MEM_ALIAS_SET
> unaltered causing later scheduling to move the widened load before
> the store.  The fix is to instead use widen_memory_access which
> attempts to fixup MEM_EXPR and resets MEM_ALIAS_SET.
>
> To avoid regressing gcc.target/i386/sse{2,4_1}-init-v2df-2.c where
> ix86_split_stlf_stall_load splitted a V2DF load from a parameter
> but this being no longer visible with a cleared MEM_EXPR this
> adjusts ix86_operands_ok_for_move_multiple instead to avoid
> merging two loads from different parameters, not only those
> that ix86_split_stlf_stall_load handles.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu.
>
> OK?

LGTM, but please move the testcase to gcc.target/i386.

Converting a negative double to unsigned is UB. On x86 it happens to
wrap through cvttsd2si, but aarch64's fcvtzu saturates to 0, so the
hard-coded 0xfff97f7f will fail on other targets.

Thanks,
Uros.

> Thanks,
> Richard.
>
>         PR target/127633
>         * config/i386/sse.md (movsd/movhpd to movupd): Use
>         widen_memory_access instead of adjust_address to merge
>         the MEMs.
>         * config/i386/i386.cc (ix86_operands_ok_for_move_multiple):
>         Avoid merging loads from different parameters.
>
>         * gcc.dg/pr127633.c: New testcase.
>         * gcc.target/i386/sse2-init-v2df-2.c: Adjust.
>         * gcc.target/i386/sse4_1-init-v2df-2.c: Likewise.
> ---
>  gcc/config/i386/i386.cc                       |  9 +++
>  gcc/config/i386/sse.md                        |  6 +-
>  gcc/testsuite/gcc.dg/pr127633.c               | 68 +++++++++++++++++++
>  .../gcc.target/i386/sse2-init-v2df-2.c        |  4 +-
>  .../gcc.target/i386/sse4_1-init-v2df-2.c      |  4 +-
>  5 files changed, 84 insertions(+), 7 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/pr127633.c
>
> diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
> index b09a5077820..74a6b39856f 100644
> --- a/gcc/config/i386/i386.cc
> +++ b/gcc/config/i386/i386.cc
> @@ -28079,6 +28079,15 @@ ix86_operands_ok_for_move_multiple (rtx *operands, 
> bool load,
>      {
>        mem_1 = operands[1];
>        mem_2 = operands[3];
> +      /* Avoid fusing two loads from distinct parameters as that might
> +        cause STLF failure.  */
> +      tree base_1;
> +      if (MEM_EXPR (mem_1)
> +         && MEM_EXPR (mem_2)
> +         && (TREE_CODE (base_1 = get_base_address (MEM_EXPR (mem_1)))
> +             == PARM_DECL)
> +         && get_base_address (MEM_EXPR (mem_2)) != base_1)
> +       return false;
>        reg_1 = operands[0];
>        reg_2 = operands[2];
>      }
> diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
> index 0ce82789dc6..2b6d7de1f7f 100644
> --- a/gcc/config/i386/sse.md
> +++ b/gcc/config/i386/sse.md
> @@ -2021,7 +2021,7 @@
>    "TARGET_SSE2 && TARGET_SSE_UNALIGNED_LOAD_OPTIMAL
>     && ix86_operands_ok_for_move_multiple (operands, true, DFmode)"
>    [(set (match_dup 2) (match_dup 5))]
> -  "operands[5] = adjust_address (operands[1], V2DFmode, 0);")
> +  "operands[5] = widen_memory_access (operands[1], V2DFmode, 0);")
>
>  (define_peephole2
>    [(set (match_operand:DF 0 "sse_reg_operand")
> @@ -2033,7 +2033,7 @@
>     && REGNO (operands[4]) == REGNO (operands[2])
>     && ix86_operands_ok_for_move_multiple (operands, true, DFmode)"
>    [(set (match_dup 2) (match_dup 5))]
> -  "operands[5] = adjust_address (operands[1], V2DFmode, 0);")
> +  "operands[5] = widen_memory_access (operands[1], V2DFmode, 0);")
>
>  ;; Merge movlpd/movhpd to movupd for TARGET_SSE_UNALIGNED_STORE_OPTIMAL 
> targets.
>  (define_peephole2
> @@ -2046,7 +2046,7 @@
>    "TARGET_SSE2 && TARGET_SSE_UNALIGNED_STORE_OPTIMAL
>     && ix86_operands_ok_for_move_multiple (operands, false, DFmode)"
>    [(set (match_dup 4) (match_dup 1))]
> -  "operands[4] = adjust_address (operands[0], V2DFmode, 0);")
> +  "operands[4] = widen_memory_access (operands[0], V2DFmode, 0);")
>
>  (define_insn "<sse3>_lddqu<avxsizesuffix>"
>    [(set (match_operand:VI1 0 "register_operand" "=x,x")
> diff --git a/gcc/testsuite/gcc.dg/pr127633.c b/gcc/testsuite/gcc.dg/pr127633.c
> new file mode 100644
> index 00000000000..500e84f66ff
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr127633.c
> @@ -0,0 +1,68 @@
> +/* { dg-do run } */
> +/* { dg-require-effective-target int32plus } */
> +/* { dg-options "-O3 -funroll-all-loops -fno-vect-cost-model" } */
> +
> +int d, ab = -104, ac, ad = -170, ae = -51, af = -151, ag = -1966532803, ah, 
> ai,
> +       aj, ak, al, am, an, *ao, v, ap, aq;
> +short w, y, z, ar, as, at, au, av, aw, ax = -156, ay, az, ba;
> +long bb = -38, bc, bd, be, bf;
> +double bg, bh, *bi;
> +char bj;
> +int a(unsigned bk, unsigned bl) {
> +  return bk^bl;
> +}
> +[[gnu::noinline,gnu::noclone]]
> +int aa(short bn) {
> +  return bn;
> +}
> +[[gnu::noinline,gnu::noclone]]
> +int s(long bk, short bl, short bm, long bn, int bo, short bp, int bq) {
> +  int bt, bu = aa(-1);
> +  double bv, bw, *by, *bz, **ca;
> +  __attribute__((__vector_size__(8 * sizeof(double)))) double cb;
> +  cb[4] = 1.75;
> +  cb[5] = -8.0;
> +  cb[7] = 1.75;
> +  ca = &by;
> +  bt = bu;
> +  bv = -65536;
> +  bz = &bw;
> +  cb[2] = 0 + (bm ? -8.0 : bg);
> +  if (-bl >= 0) {
> +    if (bm)
> +      goto bx;
> +    ca = &bz;
> +  }
> +  cb[3] = 524420 + bt;
> +  az = bl - (1646 ^ bl);
> +  bw = 2.0 * bv;
> +  bv = 2.0 * bw;
> +  *ca = &bv;
> +bx:
> +  cb[1] = -4.0 + 2.5 * bv;
> +  bc = 267503909 - bn;
> +  bi = *ca;
> +  *by = 131072 - 5.0 * bw;
> +  *bz = 3.0 * bg + 0.375 * bv;
> +  ay = ba = bl + 15 * az;
> +  bj = -__builtin_popcount((unsigned char)(109 + az));
> +  an = 0;
> +
> +  an = a(an, cb[1]);
> +  an = a(an, cb[2]);
> +  an = a(an, cb[3]);
> +  an = a(an, cb[4]);
> +  an = a(an, cb[5]);
> +  an = a(an, cb[7]);
> +
> +  an = a(an, bw);
> +  an = an^(int)bg;
> +  return an;
> +}
> +int main() {
> +  am = s(1, 1, 1, 1, 3, 1, 1);
> +  al = am;
> +  if (al != 0xfff97f7f)
> +    __builtin_abort ();
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/sse2-init-v2df-2.c 
> b/gcc/testsuite/gcc.target/i386/sse2-init-v2df-2.c
> index 3f58098af8d..17131422939 100644
> --- a/gcc/testsuite/gcc.target/i386/sse2-init-v2df-2.c
> +++ b/gcc/testsuite/gcc.target/i386/sse2-init-v2df-2.c
> @@ -15,9 +15,9 @@ v2df f0m() { return (v2df){ 0.0, m }; }
>  v2df fmm() { return (v2df){ m, m }; }
>  v2df fmn() { return (v2df){ m, n }; }
>
> -/* { dg-final { scan-assembler-times "movq" 5 } } */
> +/* { dg-final { scan-assembler-times "movq" 4 } } */
>  /* { dg-final { scan-assembler-times "pslldq" 2 } } */
>  /* { dg-final { scan-assembler-times "unpcklpd" 2 } } */
> -/* { dg-final { scan-assembler-times "movsd" 3 } } */
> +/* { dg-final { scan-assembler-times "movsd" 4 } } */
>  /* { dg-final { scan-assembler-times "movhpd" 2 } } */
>
> diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-init-v2df-2.c 
> b/gcc/testsuite/gcc.target/i386/sse4_1-init-v2df-2.c
> index 218cc8bf896..f1d8e8367aa 100644
> --- a/gcc/testsuite/gcc.target/i386/sse4_1-init-v2df-2.c
> +++ b/gcc/testsuite/gcc.target/i386/sse4_1-init-v2df-2.c
> @@ -15,9 +15,9 @@ v2df f0m() { return (v2df){ 0.0, m }; }
>  v2df fmm() { return (v2df){ m, m }; }
>  v2df fmn() { return (v2df){ m, n }; }
>
> -/* { dg-final { scan-assembler-times "movq" 5 } } */
> +/* { dg-final { scan-assembler-times "movq" 4 } } */
>  /* { dg-final { scan-assembler-times "pslldq" 2 } } */
>  /* { dg-final { scan-assembler-times "movddup" 2 } } */
> -/* { dg-final { scan-assembler-times "movsd" 1 } } */
> +/* { dg-final { scan-assembler-times "movsd" 2 } } */
>  /* { dg-final { scan-assembler-times "movhpd" 2 } } */
>
> --
> 2.51.0

Reply via email to