This fixes element ordering for V2SFmode, V2SImode and V2DImode concats in ix86_expand_vector_set.
Boostrap / regtest pending on x86_64-unknown-linux-gnu. Ok everywhere? (the testcase only fails on trunk) Thanks, Richard. 2012-02-28 Richard Guenther <rguent...@suse.de> PR target/52407 * config/i386/i386.c (ix86_expand_vector_set): Fix element ordering for the VEC_CONCAT for two element vectors for V2SFmode, V2SImode and V2DImode. * gcc.dg/torture/pr52407.c: New testcase. Index: gcc/config/i386/i386.c =================================================================== *** gcc/config/i386/i386.c (revision 184622) --- gcc/config/i386/i386.c (working copy) *************** ix86_expand_vector_set (bool mmx_ok, rtx *** 33562,33570 **** tmp = gen_reg_rtx (GET_MODE_INNER (mode)); ix86_expand_vector_extract (true, tmp, target, 1 - elt); if (elt == 0) - tmp = gen_rtx_VEC_CONCAT (mode, tmp, val); - else tmp = gen_rtx_VEC_CONCAT (mode, val, tmp); emit_insn (gen_rtx_SET (VOIDmode, target, tmp)); return; } --- 33562,33570 ---- tmp = gen_reg_rtx (GET_MODE_INNER (mode)); ix86_expand_vector_extract (true, tmp, target, 1 - elt); if (elt == 0) tmp = gen_rtx_VEC_CONCAT (mode, val, tmp); + else + tmp = gen_rtx_VEC_CONCAT (mode, tmp, val); emit_insn (gen_rtx_SET (VOIDmode, target, tmp)); return; } *************** ix86_expand_vector_set (bool mmx_ok, rtx *** 33578,33586 **** tmp = gen_reg_rtx (GET_MODE_INNER (mode)); ix86_expand_vector_extract (false, tmp, target, 1 - elt); if (elt == 0) - tmp = gen_rtx_VEC_CONCAT (mode, tmp, val); - else tmp = gen_rtx_VEC_CONCAT (mode, val, tmp); emit_insn (gen_rtx_SET (VOIDmode, target, tmp)); return; --- 33578,33586 ---- tmp = gen_reg_rtx (GET_MODE_INNER (mode)); ix86_expand_vector_extract (false, tmp, target, 1 - elt); if (elt == 0) tmp = gen_rtx_VEC_CONCAT (mode, val, tmp); + else + tmp = gen_rtx_VEC_CONCAT (mode, tmp, val); emit_insn (gen_rtx_SET (VOIDmode, target, tmp)); return; Index: gcc/testsuite/gcc.dg/torture/pr52407.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr52407.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr52407.c (revision 0) *************** *** 0 **** --- 1,35 ---- + /* { dg-do run } */ + + extern void abort (void); + + typedef __INT64_TYPE__ int64_t; + typedef int64_t vl_t __attribute__((vector_size(16))); + + vl_t ul[4] = {}; + vl_t vl[4] = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; + int64_t res[8] = { 2, 4, 6, 8, 10, 12, 14, 16 }; + + static void + mul_vl_l(vl_t *u, vl_t *v, int64_t x, int m) + { + vl_t w; + int64_t *p = (int64_t *)&w; + p[0] = p[1] = x; + while (m--) + *u++ = *v++ * w; + } + + int + main(int argc, char *argv[]) + { + int i; + int64_t *pl; + + pl = (int64_t *)&ul; + mul_vl_l(ul, vl, 2, 4); + for (i = 0; i < 8; i++) + if (pl[i] != res[i]) + abort (); + + return; + }