Re: [PATCH, rs6000] Implement -maltivec=be for vec_mergeh and vec_mergel Altivec builtins
Hi, David suggested privately that I rework some of the pattern names to fit in with existing practice. I've done this, and the result is below. Bootstrapped and tested on powerpc64{,le}-unknown-linux-gnu with no regressions. Is this ok for trunk? Thanks, Bill On Thu, 2014-01-23 at 18:08 -0600, Bill Schmidt wrote: Hi, This patch continues the series of changes to the Altivec builtins to accommodate big-endian element order when targeting a little endian machine. Here the focus is on the vector merge-high and merge-low operations. The primary change is in altivec.md. As an example, look at the pattern altivec_vmrghw. Previously, this was represented with a single define_insn. Now it's been split into a define_expand to create the RTL, and a define_insn (*altivec_vmrghw_endian) to generate the hardware instruction. This is because we need a different selection vector when using -maltivec=be and targeting LE. (Normally LE and BE can use the same selection vector, and GCC takes care of interpreting the indices as left-to-right or right-to-left.) The new define_insn also substitutes vmrglw with swapped operands for vmrghw for little-endian mode, since the hardware instruction has big-endian bias in the interpretation of high and low. Because -maltivec=be applies only to programmer-specified builtins, we need to adjust internal uses of altivec_vmrghw and friends. Thus we have a new define_insn altivec_vmrghw_internal that generates the hardware instruction directly with none of the above transformations. New unspecs are needed for these internal forms. The VSX flavors of merge-high and merge-low are a little simpler (see vsx.md). Here we already had a define_expand where the instructions are generated by separate xxpermdi patterns, and there are no internal uses to worry about. So we only need to change the selection vector in the generated RTL. There are four new test cases that cover all of the supported data types. Tests are divided between those that require only VMX instructions and those that require VSX instructions. There are also variants for -maltivec and -maltivec=be. Bootstrapped and tested on powerpc64{,le}-unknown-linux-gnu with no regressions. Ok for trunk? Thanks, Bill gcc: 2014-01-28 Bill Schmidt wschm...@linux.vnet.ibm.com * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): Use CODE_FOR_altivec_vmrg*_direct rather than CODE_FOR_altivec_vmrg*. * config/rs6000/vsx.md (vsx_mergel_mode): Adjust for -maltivec=be with LE targets. (vsx_mergeh_mode): Likewise. * config/rs6000/altivec.md (UNSPEC_VMRG[HL]_DIRECT): New unspecs. (mulv8hi3): Use gen_altivec_vmrg[hl]w_direct. (altivec_vmrghb): Replace with define_expand and new *altivec_vmrghb_internal insn; adjust for -maltivec=be with LE targets. (altivec_vmrghb_direct): New define_insn. (altivec_vmrghh): Replace with define_expand and new *altivec_vmrghh_internal insn; adjust for -maltivec=be with LE targets. (altivec_vmrghh_direct): New define_insn. (altivec_vmrghw): Replace with define_expand and new *altivec_vmrghw_internal insn; adjust for -maltivec=be with LE targets. (altivec_vmrghw_direct): New define_insn. (*altivec_vmrghsf): Adjust for endianness. (altivec_vmrglb): Replace with define_expand and new *altivec_vmrglb_internal insn; adjust for -maltivec=be with LE targets. (altivec_vmrglb_direct): New define_insn. (altivec_vmrglh): Replace with define_expand and new *altivec_vmrglh_internal insn; adjust for -maltivec=be with LE targets. (altivec_vmrglh_direct): New define_insn. (altivec_vmrglw): Replace with define_expand and new *altivec_vmrglw_internal insn; adjust for -maltivec=be with LE targets. (altivec_vmrglw_direct): New define_insn. (*altivec_vmrglsf): Adjust for endianness. (vec_widen_umult_hi_v16qi): Use gen_altivec_vmrghh_direct. (vec_widen_umult_lo_v16qi): Use gen_altivec_vmrglh_direct. (vec_widen_smult_hi_v16qi): Use gen_altivec_vmrghh_direct. (vec_widen_smult_lo_v16qi): Use gen_altivec_vmrglh_direct. (vec_widen_umult_hi_v8hi): Use gen_altivec_vmrghw_direct. (vec_widen_umult_lo_v8hi): Use gen_altivec_vmrglw_direct. (vec_widen_smult_hi_v8hi): Use gen_altivec_vmrghw_direct. (vec_widen_smult_lo_v8hi): Use gen_altivec_vmrglw_direct. gcc/testsuite: 2014-01-28 Bill Schmidt wschm...@linux.vnet.ibm.com * gcc.dg/vmx/merge-be-order.c: New. * gcc.dg/vmx/merge.c: New. * gcc.dg/vmx/merge-vsx-be-order.c: New. * gcc.dg/vmx/merge-vsx.c: New. Index: gcc/testsuite/gcc.dg/vmx/merge-be-order.c === --- gcc/testsuite/gcc.dg/vmx/merge-be-order.c
Re: [PATCH, rs6000] Implement -maltivec=be for vec_mergeh and vec_mergel Altivec builtins
On Tue, Jan 28, 2014 at 7:17 PM, Bill Schmidt wschm...@linux.vnet.ibm.com wrote: David suggested privately that I rework some of the pattern names to fit in with existing practice. I've done this, and the result is below. Bootstrapped and tested on powerpc64{,le}-unknown-linux-gnu with no regressions. Is this ok for trunk? gcc: 2014-01-28 Bill Schmidt wschm...@linux.vnet.ibm.com * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): Use CODE_FOR_altivec_vmrg*_direct rather than CODE_FOR_altivec_vmrg*. * config/rs6000/vsx.md (vsx_mergel_mode): Adjust for -maltivec=be with LE targets. (vsx_mergeh_mode): Likewise. * config/rs6000/altivec.md (UNSPEC_VMRG[HL]_DIRECT): New unspecs. (mulv8hi3): Use gen_altivec_vmrg[hl]w_direct. (altivec_vmrghb): Replace with define_expand and new *altivec_vmrghb_internal insn; adjust for -maltivec=be with LE targets. (altivec_vmrghb_direct): New define_insn. (altivec_vmrghh): Replace with define_expand and new *altivec_vmrghh_internal insn; adjust for -maltivec=be with LE targets. (altivec_vmrghh_direct): New define_insn. (altivec_vmrghw): Replace with define_expand and new *altivec_vmrghw_internal insn; adjust for -maltivec=be with LE targets. (altivec_vmrghw_direct): New define_insn. (*altivec_vmrghsf): Adjust for endianness. (altivec_vmrglb): Replace with define_expand and new *altivec_vmrglb_internal insn; adjust for -maltivec=be with LE targets. (altivec_vmrglb_direct): New define_insn. (altivec_vmrglh): Replace with define_expand and new *altivec_vmrglh_internal insn; adjust for -maltivec=be with LE targets. (altivec_vmrglh_direct): New define_insn. (altivec_vmrglw): Replace with define_expand and new *altivec_vmrglw_internal insn; adjust for -maltivec=be with LE targets. (altivec_vmrglw_direct): New define_insn. (*altivec_vmrglsf): Adjust for endianness. (vec_widen_umult_hi_v16qi): Use gen_altivec_vmrghh_direct. (vec_widen_umult_lo_v16qi): Use gen_altivec_vmrglh_direct. (vec_widen_smult_hi_v16qi): Use gen_altivec_vmrghh_direct. (vec_widen_smult_lo_v16qi): Use gen_altivec_vmrglh_direct. (vec_widen_umult_hi_v8hi): Use gen_altivec_vmrghw_direct. (vec_widen_umult_lo_v8hi): Use gen_altivec_vmrglw_direct. (vec_widen_smult_hi_v8hi): Use gen_altivec_vmrghw_direct. (vec_widen_smult_lo_v8hi): Use gen_altivec_vmrglw_direct. gcc/testsuite: 2014-01-28 Bill Schmidt wschm...@linux.vnet.ibm.com * gcc.dg/vmx/merge-be-order.c: New. * gcc.dg/vmx/merge.c: New. * gcc.dg/vmx/merge-vsx-be-order.c: New. * gcc.dg/vmx/merge-vsx.c: New. Thanks for adjusting the patch to be more consistent with the pattern names used in the rest of the port. The patch is okay. Thanks, David
[PATCH, rs6000] Implement -maltivec=be for vec_mergeh and vec_mergel Altivec builtins
Hi, This patch continues the series of changes to the Altivec builtins to accommodate big-endian element order when targeting a little endian machine. Here the focus is on the vector merge-high and merge-low operations. The primary change is in altivec.md. As an example, look at the pattern altivec_vmrghw. Previously, this was represented with a single define_insn. Now it's been split into a define_expand to create the RTL, and a define_insn (*altivec_vmrghw_endian) to generate the hardware instruction. This is because we need a different selection vector when using -maltivec=be and targeting LE. (Normally LE and BE can use the same selection vector, and GCC takes care of interpreting the indices as left-to-right or right-to-left.) The new define_insn also substitutes vmrglw with swapped operands for vmrghw for little-endian mode, since the hardware instruction has big-endian bias in the interpretation of high and low. Because -maltivec=be applies only to programmer-specified builtins, we need to adjust internal uses of altivec_vmrghw and friends. Thus we have a new define_insn altivec_vmrghw_internal that generates the hardware instruction directly with none of the above transformations. New unspecs are needed for these internal forms. The VSX flavors of merge-high and merge-low are a little simpler (see vsx.md). Here we already had a define_expand where the instructions are generated by separate xxpermdi patterns, and there are no internal uses to worry about. So we only need to change the selection vector in the generated RTL. There are four new test cases that cover all of the supported data types. Tests are divided between those that require only VMX instructions and those that require VSX instructions. There are also variants for -maltivec and -maltivec=be. Bootstrapped and tested on powerpc64{,le}-unknown-linux-gnu with no regressions. Ok for trunk? Thanks, Bill gcc: 2014-01-23 Bill Schmidt wschm...@linux.vnet.ibm.com * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): Use CODE_FOR_altivec_vmrg*_internal rather than CODE_FOR_altivec_vmrg*. * config/rs6000/vsx.md (vsx_mergel_mode): Adjust for -maltivec=be with LE targets. (vsx_mergeh_mode): Likewise. * config/rs6000/altivec.md (UNSPEC_VMRG[HL][BHW]_INTERNAL): New unspecs. (mulv8hi3): Use gen_altivec_vmrg[hl]w_internal. (altivec_vmrghb): Replace with define_expand and new *altivec_vmrghb_endian insn; adjust for -maltivec=be with LE targets. (altivec_vmrghb_internal): New define_insn. (altivec_vmrghh): Replace with define_expand and new *altivec_vmrghh_endian insn; adjust for -maltivec=be with LE targets. (altivec_vmrghh_internal): New define_insn. (altivec_vmrghw): Replace with define_expand and new *altivec_vmrghw_endian insn; adjust for -maltivec=be with LE targets. (altivec_vmrghw_internal): New define_insn. (*altivec_vmrghsf): Adjust for endianness. (altivec_vmrglb): Replace with define_expand and new *altivec_vmrglb_endian insn; adjust for -maltivec=be with LE targets. (altivec_vmrglb_internal): New define_insn. (altivec_vmrglh): Replace with define_expand and new *altivec_vmrglh_endian insn; adjust for -maltivec=be with LE targets. (altivec_vmrglh_internal): New define_insn. (altivec_vmrglw): Replace with define_expand and new *altivec_vmrglw_endian insn; adjust for -maltivec=be with LE targets. (altivec_vmrglw_internal): New define_insn. (*altivec_vmrglsf): Adjust for endianness. (vec_widen_umult_hi_v16qi): Use gen_altivec_vmrghh_internal. (vec_widen_umult_lo_v16qi): Use gen_altivec_vmrglh_internal. (vec_widen_smult_hi_v16qi): Use gen_altivec_vmrghh_internal. (vec_widen_smult_lo_v16qi): Use gen_altivec_vmrglh_internal. (vec_widen_umult_hi_v8hi): Use gen_altivec_vmrghw_internal. (vec_widen_umult_lo_v8hi): Use gen_altivec_vmrglw_internal. (vec_widen_smult_hi_v8hi): Use gen_altivec_vmrghw_internal. (vec_widen_smult_lo_v8hi): Use gen_altivec_vmrglw_internal. gcc/testsuite: 2014-01-23 Bill Schmidt wschm...@linux.vnet.ibm.com * gcc.dg/vmx/merge-be-order.c: New. * gcc.dg/vmx/merge.c: New. * gcc.dg/vmx/merge-vsx-be-order.c: New. * gcc.dg/vmx/merge-vsx.c: New. Index: gcc/testsuite/gcc.dg/vmx/merge-be-order.c === --- gcc/testsuite/gcc.dg/vmx/merge-be-order.c (revision 0) +++ gcc/testsuite/gcc.dg/vmx/merge-be-order.c (revision 0) @@ -0,0 +1,96 @@ +/* { dg-options -maltivec=be -mabi=altivec -std=gnu99 -mno-vsx } */ + +#include harness.h + +static void test() +{ + /* Input vectors. */ + vector unsigned char vuca = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + vector unsigned char