Hi, While working on a backport, I discovered a bug that only exists in the 4.8 branch (the buggy code was rewritten with the direct move additions in 4.9). A load-and-extract of the first doubleword in memory can always be done with the lxsd[u]x instruction. In 4.8 I wrongly added code to use this to load the second doubleword instead for little-endian. This is wrong because the order of array elements in memory remains the same for both endiannesses (versus in registers where they differ). Unfortunately the existing test case didn't exercise this properly, so the bug was missed. This patch corrects the bug and expands the test case to cover this case.
Tested on powerpc64le-unknown-linux-gnu with no regressions. Ok for 4.8? Thanks, Bill [gcc] 2015-03-26 Bill Schmidt <wschm...@linux.vnet.ibm.com> * config/rs6000/vsx.md (*vsx_extract_<mode>_zero): Remove endianness requirement. (*vsx_extract_<mode>_one_le): Remove define_insn. [gcc/testsuite] 2015-03-26 Bill Schmidt <wschm...@linux.vnet.ibm.com> * gcc.dg/vmx/extract-vsx.c: Add more cases. Index: gcc/config/rs6000/vsx.md =================================================================== --- gcc/config/rs6000/vsx.md (revision 221668) +++ gcc/config/rs6000/vsx.md (working copy) @@ -1781,7 +1781,7 @@ (vec_select:<VS_scalar> (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z") (parallel [(const_int 0)])))] - "VECTOR_MEM_VSX_P (<MODE>mode) && WORDS_BIG_ENDIAN" + "VECTOR_MEM_VSX_P (<MODE>mode)" "lxsd%U1x %x0,%y1" [(set (attr "type") (if_then_else @@ -1790,21 +1790,6 @@ (const_string "fpload"))) (set_attr "length" "4")]) -;; Optimize extracting element 1 from memory for little endian -(define_insn "*vsx_extract_<mode>_one_le" - [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,d,?wa") - (vec_select:<VS_scalar> - (match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z,Z,Z") - (parallel [(const_int 1)])))] - "VECTOR_MEM_VSX_P (<MODE>mode) && !WORDS_BIG_ENDIAN" - "lxsd%U1x %x0,%y1" - [(set (attr "type") - (if_then_else - (match_test "update_indexed_address_mem (operands[1], VOIDmode)") - (const_string "fpload_ux") - (const_string "fpload"))) - (set_attr "length" "4")]) - ;; Extract a SF element from V4SF (define_insn_and_split "vsx_extract_v4sf" [(set (match_operand:SF 0 "vsx_register_operand" "=f,f") Index: gcc/testsuite/gcc.dg/vmx/extract-vsx.c =================================================================== --- gcc/testsuite/gcc.dg/vmx/extract-vsx.c (revision 221668) +++ gcc/testsuite/gcc.dg/vmx/extract-vsx.c (working copy) @@ -10,7 +10,11 @@ static void test() vector double vd = {0.0, 1.0}; check (vec_extract (vl, 0) == 0, "vec_extract, vl, 0"); + check (vec_extract (vl, 1) == 1, "vec_extract, vl, 1"); + check (vec_extract (vd, 0) == 0.0, "vec_extract, vd, 0"); check (vec_extract (vd, 1) == 1.0, "vec_extract, vd, 1"); check (vl[0] == 0, "[], vl, 0"); - check (vd[1] == 1.0, "[], vd, 0"); + check (vl[1] == 1, "[], vl, 1"); + check (vd[0] == 0.0, "[], vd, 0"); + check (vd[1] == 1.0, "[], vd, 1"); }