Hi, This patch contains two more fixes related to the multiply even/odd problem. First, it changes the mulv4si3 pattern so that it always uses the vmulouh (vector multiply odd halfword) instruction regardless of endianness. The reason for this is that we are not really multiplying halfwords, but are multiplying words that have been truncated to halfword length; therefore they always sit in the right half of each word, which is the odd-numbered word in big-endian numbering.
The fix for mulv8hi3 is another case where reversing the meanings of the multiply even/odd instructions requires us to reverse the order of inputs on the merge high/low instructions to compensate. Bootstrapped and tested with the rest of the patch set on powerpc64{,le}-unknown-linux-gnu with no regressions. Ok for trunk? Thanks, Bill 2013-11-03 Bill Schmidt <wschm...@linux.vnet.ibm.com> * config/rs6000/altivec.md (mulv4si3): Ensure we generate vmulouh for both big and little endian. (mulv8hi3): Swap input operands for merge high and merge low instructions. Index: gcc/config/rs6000/altivec.md =================================================================== --- gcc/config/rs6000/altivec.md (revision 204192) +++ gcc/config/rs6000/altivec.md (working copy) @@ -651,7 +651,12 @@ convert_move (small_swap, swap, 0); low_product = gen_reg_rtx (V4SImode); - emit_insn (gen_vec_widen_umult_odd_v8hi (low_product, one, two)); + /* We need this to be vmulouh for both big and little endian, + but for little endian we would swap this, so avoid that. */ + if (BYTES_BIG_ENDIAN) + emit_insn (gen_vec_widen_umult_odd_v8hi (low_product, one, two)); + else + emit_insn (gen_vec_widen_umult_even_v8hi (low_product, one, two)); high_product = gen_reg_rtx (V4SImode); emit_insn (gen_altivec_vmsumuhm (high_product, one, small_swap, zero)); @@ -678,13 +683,18 @@ emit_insn (gen_vec_widen_smult_even_v8hi (even, operands[1], operands[2])); emit_insn (gen_vec_widen_smult_odd_v8hi (odd, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw (high, even, odd)); - emit_insn (gen_altivec_vmrglw (low, even, odd)); - if (BYTES_BIG_ENDIAN) - emit_insn (gen_altivec_vpkuwum (operands[0], high, low)); + { + emit_insn (gen_altivec_vmrghw (high, even, odd)); + emit_insn (gen_altivec_vmrglw (low, even, odd)); + emit_insn (gen_altivec_vpkuwum (operands[0], high, low)); + } else - emit_insn (gen_altivec_vpkuwum (operands[0], low, high)); + { + emit_insn (gen_altivec_vmrghw (high, odd, even)); + emit_insn (gen_altivec_vmrglw (low, odd, even)); + emit_insn (gen_altivec_vpkuwum (operands[0], low, high)); + } DONE; }")