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