https://gcc.gnu.org/g:39e7936c2ba2dea099bca58d12d9d0721d4eae55
commit r17-4743-g39e7936c2ba2dea099bca58d12d9d0721d4eae55 Author: Richard Biener <[email protected]> Date: Mon Sep 28 10:31:40 2026 +0200 [x86] fix load combining peepholes 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. 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.target/i386/pr127633.c: New testcase. * gcc.target/i386/sse2-init-v2df-2.c: Adjust. * gcc.target/i386/sse4_1-init-v2df-2.c: Likewise. Diff: --- gcc/config/i386/i386.cc | 9 +++ gcc/config/i386/sse.md | 6 +- gcc/testsuite/gcc.target/i386/pr127633.c | 68 ++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/sse2-init-v2df-2.c | 4 +- gcc/testsuite/gcc.target/i386/sse4_1-init-v2df-2.c | 4 +- 5 files changed, 84 insertions(+), 7 deletions(-) diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index b09a5077820a..74a6b39856f0 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 0ce82789dc6c..2b6d7de1f7f7 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.target/i386/pr127633.c b/gcc/testsuite/gcc.target/i386/pr127633.c new file mode 100644 index 000000000000..500e84f66ff3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/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 3f58098af8da..171314229391 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 218cc8bf896a..f1d8e8367aa0 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 } } */
