Hi!

As the following testcase shows, the sse2_loadlpd splitter when
the destination (and at the same operand from which the second
DFmode element is taken) is a MEM and the other DFmode operand
is a register stores into wrong part of memory, it does what
the sse2_loadhpd splitter does, while it should overwrite the
first half of the vector and keep the second half preserved.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
ok for trunk/4.7/4.6?

2012-03-27  Jakub Jelinek  <ja...@redhat.com>

        PR target/52736
        * config/i386/sse.md (sse2_loadlpd splitter): Use offset 0
        instead of 8 in adjust_address.

        * gcc.target/i386/pr52736.c: New test.

--- gcc/config/i386/sse.md.jj   2012-03-26 11:53:19.000000000 +0200
+++ gcc/config/i386/sse.md      2012-03-27 16:09:52.764828996 +0200
@@ -4901,7 +4901,7 @@ (define_split
          (vec_select:DF (match_dup 0) (parallel [(const_int 1)]))))]
   "TARGET_SSE2 && reload_completed"
   [(set (match_dup 0) (match_dup 1))]
-  "operands[0] = adjust_address (operands[0], DFmode, 8);")
+  "operands[0] = adjust_address (operands[0], DFmode, 0);")
 
 (define_insn "sse2_movsd"
   [(set (match_operand:V2DF 0 "nonimmediate_operand"   "=x,x,x,x,m,x,x,x,o")
--- gcc/testsuite/gcc.target/i386/pr52736.c.jj  2012-03-27 16:40:37.924944611 
+0200
+++ gcc/testsuite/gcc.target/i386/pr52736.c     2012-03-27 16:40:30.000000000 
+0200
@@ -0,0 +1,29 @@
+/* PR target/52736 */
+/* { dg-do run } */
+/* { dg-options "-O1 -msse2" } */
+/* { dg-require-effective-target sse2_runtime } */
+
+#include <x86intrin.h>
+
+typedef double D __attribute__((may_alias));
+__attribute__((aligned(16))) static const double r[4] = { 1., 5., 1., 3. };
+
+__attribute__((noinline, noclone))
+void
+foo (int x)
+{
+  asm volatile ("" : "+g" (x) : : "memory");
+  if (x != 3)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  __m128d t = _mm_set1_pd (5.);
+  ((D *)(&t))[0] = 1.;
+  foo (_mm_movemask_pd (_mm_cmpeq_pd (t, _mm_load_pd (&r[0]))));
+  ((D *)(&t))[1] = 3.;
+  foo (_mm_movemask_pd (_mm_cmpeq_pd (t, _mm_load_pd (&r[2]))));
+  return 0;
+}

        Jakub

Reply via email to