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