Re: [PATCH, rs6000] Implement -maltivec=be for vec_splat builtins

2014-01-30 Thread David Edelsohn
On Wed, Jan 29, 2014 at 11:50 PM, Bill Schmidt
wschm...@linux.vnet.ibm.com wrote:
 Hi,

 This continues the series of -maltivec=be patches, this one handling
 vec_splat.  Since vec_splat is no longer treated as a true intrinsic,
 its default behavior for little endian is changed to use right-to-left
 element indexing for selecting the element to splat.  With -maltivec=be
 for little endian, this reverts to left-to-right element indexing.

 The main changes are in altivec.md, and are quite similar to what was
 done for vector merge high/low.  Each of the vector splat builtins is
 split into a define_expand and an _internal define_insn.  The expand
 uses the natural element order for the target, unless we have
 -maltivec=be for an LE target, in which case the order is reversed.  The
 _internal insn modifies the element number on the hardware instruction
 for LE to account for the instruction's big-endian bias.

 For those of the vector splat instructions that are generated
 internally, rather than through a builtin, a _direct insn is supplied
 that generates precisely the instruction requested.

 vsx.md contains the same changes for V4SI and V4SF patterns when VSX
 instructions are enabled.  We don't need a separate define_expand for
 this one because the define_expand for altivec_vspltw is used to
 generate the pattern that is recognized by vsx_xxspltw_mode.  Either
 vsx_xxspltw_mode or *altivec_vspltw_internal handles the pattern,
 depending on whether or not VSX instructions are enabled.

 Most of the changes in rs6000.c are to use the new _direct forms.  There
 is one other change to rs6000_expand_vector_init, where the modification
 of the selector field for a generated splat pattern is removed.  That is
 properly handled instead by the code in altivec.md and vsx.md.

 As usual, there are four new test cases to cover the various vector
 types for VMX and VSX.  Two existing test cases require adjustment
 because of the change in the default semantics of vec_splat for little
 endian.

 Bootstrapped and tested on powerpc64{,le}-unknown-linux-gnu with no
 regressions.  Ok for trunk?

 Thanks,
 Bill


 gcc:

 2014-01-29  Bill Schmidt  wschm...@linux.vnet.ibm.com

 * gcc/config/rs6000/rs6000.c (rs6000_expand_vector_init): Use
 gen_vsx_xxspltw_v4sf_direct instead of gen_vsx_xxspltw_v4sf;
 remove element index adjustment for endian (now handled in vsx.md
 and altivec.md).
 (altivec_expand_vec_perm_const): Use
 gen_altivec_vsplt[bhw]_direct instead of gen_altivec_vsplt[bhw].
 * gcc/config/rs6000/vsx.md (UNSPEC_VSX_XXSPLTW): New unspec.
 (vsx_xxspltw_mode): Adjust element index for little endian.
 * gcc/config/rs6000/altivec.md (altivec_vspltb): Divide into a
 define_expand and a new define_insn *altivec_vspltb_internal;
 adjust for -maltivec=be on a little endian target.
 (altivec_vspltb_direct): New.
 (altivec_vsplth): Divide into a define_expand and a new
 define_insn *altivec_vsplth_internal; adjust for -maltivec=be on a
 little endian target.
 (altivec_vsplth_direct): New.
 (altivec_vspltw): Divide into a define_expand and a new
 define_insn *altivec_vspltw_internal; adjust for -maltivec=be on a
 little endian target.
 (altivec_vspltw_direct): New.
 (altivec_vspltsf): Divide into a define_expand and a new
 define_insn *altivec_vspltsf_internal; adjust for -maltivec=be on
 a little endian target.

 gcc/testsuite:

 2014-01-29  Bill Schmidt  wschm...@linux.vnet.ibm.com

 * gcc.dg/vmx/splat.c: New.
 * gcc.dg/vmx/splat-vsx.c: New.
 * gcc.dg/vmx/splat-be-order.c: New.
 * gcc.dg/vmx/splat-vsx-be-order.c: New.
 * gcc.dg/vmx/eg-5.c: Remove special casing for little endian.
 * gcc.dg/vmx/sn7153.c: Add special casing for little endian.

Okay.

Thanks David


[PATCH, rs6000] Implement -maltivec=be for vec_splat builtins

2014-01-29 Thread Bill Schmidt
Hi,

This continues the series of -maltivec=be patches, this one handling
vec_splat.  Since vec_splat is no longer treated as a true intrinsic,
its default behavior for little endian is changed to use right-to-left
element indexing for selecting the element to splat.  With -maltivec=be
for little endian, this reverts to left-to-right element indexing.

The main changes are in altivec.md, and are quite similar to what was
done for vector merge high/low.  Each of the vector splat builtins is
split into a define_expand and an _internal define_insn.  The expand
uses the natural element order for the target, unless we have
-maltivec=be for an LE target, in which case the order is reversed.  The
_internal insn modifies the element number on the hardware instruction
for LE to account for the instruction's big-endian bias.

For those of the vector splat instructions that are generated
internally, rather than through a builtin, a _direct insn is supplied
that generates precisely the instruction requested.

vsx.md contains the same changes for V4SI and V4SF patterns when VSX
instructions are enabled.  We don't need a separate define_expand for
this one because the define_expand for altivec_vspltw is used to
generate the pattern that is recognized by vsx_xxspltw_mode.  Either
vsx_xxspltw_mode or *altivec_vspltw_internal handles the pattern,
depending on whether or not VSX instructions are enabled.

Most of the changes in rs6000.c are to use the new _direct forms.  There
is one other change to rs6000_expand_vector_init, where the modification
of the selector field for a generated splat pattern is removed.  That is
properly handled instead by the code in altivec.md and vsx.md.

As usual, there are four new test cases to cover the various vector
types for VMX and VSX.  Two existing test cases require adjustment
because of the change in the default semantics of vec_splat for little
endian.

Bootstrapped and tested on powerpc64{,le}-unknown-linux-gnu with no
regressions.  Ok for trunk?

Thanks,
Bill


gcc:

2014-01-29  Bill Schmidt  wschm...@linux.vnet.ibm.com

* gcc/config/rs6000/rs6000.c (rs6000_expand_vector_init): Use
gen_vsx_xxspltw_v4sf_direct instead of gen_vsx_xxspltw_v4sf;
remove element index adjustment for endian (now handled in vsx.md
and altivec.md).
(altivec_expand_vec_perm_const): Use
gen_altivec_vsplt[bhw]_direct instead of gen_altivec_vsplt[bhw].
* gcc/config/rs6000/vsx.md (UNSPEC_VSX_XXSPLTW): New unspec.
(vsx_xxspltw_mode): Adjust element index for little endian.
* gcc/config/rs6000/altivec.md (altivec_vspltb): Divide into a
define_expand and a new define_insn *altivec_vspltb_internal;
adjust for -maltivec=be on a little endian target.
(altivec_vspltb_direct): New.
(altivec_vsplth): Divide into a define_expand and a new
define_insn *altivec_vsplth_internal; adjust for -maltivec=be on a
little endian target.
(altivec_vsplth_direct): New.
(altivec_vspltw): Divide into a define_expand and a new
define_insn *altivec_vspltw_internal; adjust for -maltivec=be on a
little endian target.
(altivec_vspltw_direct): New.
(altivec_vspltsf): Divide into a define_expand and a new
define_insn *altivec_vspltsf_internal; adjust for -maltivec=be on
a little endian target.

gcc/testsuite:

2014-01-29  Bill Schmidt  wschm...@linux.vnet.ibm.com

* gcc.dg/vmx/splat.c: New.
* gcc.dg/vmx/splat-vsx.c: New.
* gcc.dg/vmx/splat-be-order.c: New.
* gcc.dg/vmx/splat-vsx-be-order.c: New.
* gcc.dg/vmx/eg-5.c: Remove special casing for little endian.
* gcc.dg/vmx/sn7153.c: Add special casing for little endian.


Index: gcc/testsuite/gcc.dg/vmx/splat.c
===
--- gcc/testsuite/gcc.dg/vmx/splat.c(revision 0)
+++ gcc/testsuite/gcc.dg/vmx/splat.c(revision 0)
@@ -0,0 +1,47 @@
+#include harness.h
+
+static void test()
+{
+  /* Input vectors.  */
+  vector unsigned char vuc = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+  vector signed char vsc = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7};
+  vector unsigned short vus = {0,1,2,3,4,5,6,7};
+  vector signed short vss = {-4,-3,-2,-1,0,1,2,3};
+  vector unsigned int vui = {0,1,2,3};
+  vector signed int vsi = {-2,-1,0,1};
+  vector float vf = {-2.0,-1.0,0.0,1.0};
+
+  /* Result vectors.  */
+  vector unsigned char vucr;
+  vector signed char vscr;
+  vector unsigned short vusr;
+  vector signed short vssr;
+  vector unsigned int vuir;
+  vector signed int vsir;
+  vector float vfr;
+
+  /* Expected result vectors.  */
+  vector unsigned char vucer = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+  vector signed char vscer = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+  vector unsigned short vuser = {7,7,7,7,7,7,7,7};
+  vector signed short vsser = {-4,-4,-4,-4,-4,-4,-4,-4};
+  vector unsigned int vuier = {2,2,2,2};
+  vector