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.

Bootstrapped and tested on x86_64-unknown-linux-gnu.  The
sse init testcase adjustments are due to mdreorg no longer
splitting the merged, possibly STLF stall causing MEMs as
the heuristic in ix86_split_stlf_stall_load requires

          || !MEM_EXPR (src)
          || TREE_CODE (get_base_address (MEM_EXPR (src))) != PARM_DECL

but the previously generated

        (mem/c:V2DF (plus:SI (reg/f:SI 7 sp)
                (const_int 4 [0x4])) [1 x+0 S16 A32]))

is of course not correct - the access does not only access 'x'
(but also 'y').  We now generate the correct

        (mem/c:V2DF (plus:SI (reg/f:SI 7 sp)
                (const_int 4 [0x4])) [0  S16 A32]))

the heuristic should have an alternative looking at maybe RTL
points-to, or we should accept this "regression" or find ways
to instead not apply the fusion in the first place (possibly
by doing the above very same check?).  The only possible
improvement to the merged MEM is that we could preserve the
alias-set if it is the same for both original MEMs, not sure
if that's worth it.

OK?  Any opinion on the above?

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.

        * 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/sse.md                        |  6 +-
 gcc/testsuite/gcc.dg/pr127633.c               | 68 +++++++++++++++++++
 .../gcc.target/i386/sse2-init-v2df-2.c        |  6 +-
 .../gcc.target/i386/sse4_1-init-v2df-2.c      |  6 +-
 4 files changed, 79 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr127633.c

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..0b4fbd4c4fe 100644
--- a/gcc/testsuite/gcc.target/i386/sse2-init-v2df-2.c
+++ b/gcc/testsuite/gcc.target/i386/sse2-init-v2df-2.c
@@ -9,15 +9,17 @@ v2df fx0(double x) { return (v2df){ x, 0.0 }; }
 v2df f0x(double x) { return (v2df){ 0.0, x }; }
 v2df fxx(double x) { return (v2df){ x, x }; }
 v2df fxy(double x, double y) { return (v2df){ x, y }; }
+v2df fyx(double x, double y) { return (v2df){ y, x }; }
 
 v2df fm0() { return (v2df){ m, 0.0 }; }
 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 } } */
+/* { dg-final { scan-assembler-times "movupd" 1 } } */
 
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..06dc240a665 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
@@ -9,15 +9,17 @@ v2df fx0(double x) { return (v2df){ x, 0.0 }; }
 v2df f0x(double x) { return (v2df){ 0.0, x }; }
 v2df fxx(double x) { return (v2df){ x, x }; }
 v2df fxy(double x, double y) { return (v2df){ x, y }; }
+v2df fyx(double x, double y) { return (v2df){ y, x }; }
 
 v2df fm0() { return (v2df){ m, 0.0 }; }
 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 } } */
+/* { dg-final { scan-assembler-times "movupd" 1 } } */
 
-- 
2.51.0

Reply via email to