diff mbox

[rs6000] Add -maltivec=be support for vec_lde and vec_ste

Message ID 1393125955.20991.62.camel@gnopaine
State New
Headers show

Commit Message

Bill Schmidt Feb. 23, 2014, 3:25 a.m. UTC
Hi,

This patch adds -maltivec=be support for vec_lde and vec_ste, similarly
to what was done for vec_ld, vec_st, vec_ldl, and vec_stl.  Much of the
same infrastructure is used.  Because the insn pattern for vec_ste is
formed slightly differently than the ones for vec_st and vec_stl, we
can't reuse altivec_expand_stvx_be in this case (but
altivec_expand_lvx_be works fine for vec_lde).  There are four new test
cases, covering correct behavior for all appropriate vector types for
BE, LE, and LE with -maltivec=be.

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

Thanks,
Bill


gcc:

2014-02-22  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

	* config/rs6000/altivec.md (altivec_lve<VI_char>x): Replace
	define_insn with define_expand and new define_insn
	*altivec_lve<VI_char>x_internal.
	(altivec_stve<VI_char>x): Replace define_insn with define_expand
	and new define_insn *altivec_stve<VI_char>x_internal.
	* config/rs6000/rs6000-protos.h (altivec_expand_stvex_be): New
	prototype.
	* config/rs6000/rs6000.c (altivec_expand_lvx_be): Document use by
	lve*x built-ins.
	(altivec_expand_stvex_be): New function.

gcc/testsuite:

2014-02-22  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

	* testsuite/gcc.dg/vmx/lde.c: New test.
	* testsuite/gcc.dg/vmx/lde-be-order.c: New test.
	* testsuite/gcc.dg/vmx/ste.c: New test.
	* testsuite/gcc.dg/vmx/ste-be-order.c: New test.

Comments

David Edelsohn Feb. 23, 2014, 3:12 p.m. UTC | #1
On Sat, Feb 22, 2014 at 10:25 PM, Bill Schmidt
<wschmidt@linux.vnet.ibm.com> wrote:
> Hi,
>
> This patch adds -maltivec=be support for vec_lde and vec_ste, similarly
> to what was done for vec_ld, vec_st, vec_ldl, and vec_stl.  Much of the
> same infrastructure is used.  Because the insn pattern for vec_ste is
> formed slightly differently than the ones for vec_st and vec_stl, we
> can't reuse altivec_expand_stvx_be in this case (but
> altivec_expand_lvx_be works fine for vec_lde).  There are four new test
> cases, covering correct behavior for all appropriate vector types for
> BE, LE, and LE with -maltivec=be.
>
> Bootstrapped and tested on powerpc64{,le}-unknown-linux-gnu with no
> regressions.  Is this ok for trunk?
>
> Thanks,
> Bill
>
>
> gcc:
>
> 2014-02-22  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
>
>         * config/rs6000/altivec.md (altivec_lve<VI_char>x): Replace
>         define_insn with define_expand and new define_insn
>         *altivec_lve<VI_char>x_internal.
>         (altivec_stve<VI_char>x): Replace define_insn with define_expand
>         and new define_insn *altivec_stve<VI_char>x_internal.
>         * config/rs6000/rs6000-protos.h (altivec_expand_stvex_be): New
>         prototype.
>         * config/rs6000/rs6000.c (altivec_expand_lvx_be): Document use by
>         lve*x built-ins.
>         (altivec_expand_stvex_be): New function.
>
> gcc/testsuite:
>
> 2014-02-22  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
>
>         * testsuite/gcc.dg/vmx/lde.c: New test.
>         * testsuite/gcc.dg/vmx/lde-be-order.c: New test.
>         * testsuite/gcc.dg/vmx/ste.c: New test.
>         * testsuite/gcc.dg/vmx/ste-be-order.c: New test.

Okay.

Thanks, David
diff mbox

Patch

Index: gcc/config/rs6000/altivec.md
===================================================================
--- gcc/config/rs6000/altivec.md	(revision 208022)
+++ gcc/config/rs6000/altivec.md	(working copy)
@@ -2325,12 +2325,26 @@ 
 ;; Parallel some of the LVE* and STV*'s with unspecs because some have
 ;; identical rtl but different instructions-- and gcc gets confused.
 
-(define_insn "altivec_lve<VI_char>x"
+(define_expand "altivec_lve<VI_char>x"
   [(parallel
     [(set (match_operand:VI 0 "register_operand" "=v")
 	  (match_operand:VI 1 "memory_operand" "Z"))
      (unspec [(const_int 0)] UNSPEC_LVE)])]
   "TARGET_ALTIVEC"
+{
+  if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+    {
+      altivec_expand_lvx_be (operands[0], operands[1], <MODE>mode, UNSPEC_LVE);
+      DONE;
+    }
+})
+
+(define_insn "*altivec_lve<VI_char>x_internal"
+  [(parallel
+    [(set (match_operand:VI 0 "register_operand" "=v")
+	  (match_operand:VI 1 "memory_operand" "Z"))
+     (unspec [(const_int 0)] UNSPEC_LVE)])]
+  "TARGET_ALTIVEC"
   "lve<VI_char>x %0,%y1"
   [(set_attr "type" "vecload")])
 
@@ -2435,10 +2449,22 @@ 
   "stvxl %1,%y0"
   [(set_attr "type" "vecstore")])
 
-(define_insn "altivec_stve<VI_char>x"
+(define_expand "altivec_stve<VI_char>x"
   [(set (match_operand:<VI_scalar> 0 "memory_operand" "=Z")
 	(unspec:<VI_scalar> [(match_operand:VI 1 "register_operand" "v")] UNSPEC_STVE))]
   "TARGET_ALTIVEC"
+{
+  if (!BYTES_BIG_ENDIAN && VECTOR_ELT_ORDER_BIG)
+    {
+      altivec_expand_stvex_be (operands[0], operands[1], <MODE>mode, UNSPEC_STVE);
+      DONE;
+    }
+})
+
+(define_insn "*altivec_stve<VI_char>x_internal"
+  [(set (match_operand:<VI_scalar> 0 "memory_operand" "=Z")
+	(unspec:<VI_scalar> [(match_operand:VI 1 "register_operand" "v")] UNSPEC_STVE))]
+  "TARGET_ALTIVEC"
   "stve<VI_char>x %1,%y0"
   [(set_attr "type" "vecstore")])
 
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h	(revision 208022)
+++ gcc/config/rs6000/rs6000-protos.h	(working copy)
@@ -60,6 +60,7 @@  extern void altivec_expand_vec_perm_le (rtx op[4])
 extern bool rs6000_expand_vec_perm_const (rtx op[4]);
 extern void altivec_expand_lvx_be (rtx, rtx, enum machine_mode, unsigned);
 extern void altivec_expand_stvx_be (rtx, rtx, enum machine_mode, unsigned);
+extern void altivec_expand_stvex_be (rtx, rtx, enum machine_mode, unsigned);
 extern void rs6000_expand_extract_even (rtx, rtx, rtx);
 extern void rs6000_expand_interleave (rtx, rtx, rtx, bool);
 extern void build_mask64_2_operands (rtx, rtx *);
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 208022)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -11779,7 +11779,7 @@  swap_selector_for_mode (enum machine_mode mode)
   return force_reg (V16QImode, gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm)));
 }
 
-/* Generate code for an "lvx" or "lvxl" built-in for a little endian target
+/* Generate code for an "lvx", "lvxl", or "lve*x" built-in for a little endian target
    with -maltivec=be specified.  Issue the load followed by an element-reversing
    permute.  */
 void
@@ -11816,6 +11816,23 @@  altivec_expand_stvx_be (rtx op0, rtx op1, enum mac
   emit_insn (par);
 }
 
+/* Generate code for a "stve*x" built-in for a little endian target with -maltivec=be
+   specified.  Issue the store preceded by an element-reversing permute.  */
+void
+altivec_expand_stvex_be (rtx op0, rtx op1, enum machine_mode mode, unsigned unspec)
+{
+  enum machine_mode inner_mode = GET_MODE_INNER (mode);
+  rtx tmp = gen_reg_rtx (mode);
+  rtx stvx = gen_rtx_UNSPEC (inner_mode, gen_rtvec (1, tmp), unspec);
+  rtx sel = swap_selector_for_mode (mode);
+  rtx vperm;
+
+  gcc_assert (REG_P (op1));
+  vperm = gen_rtx_UNSPEC (mode, gen_rtvec (3, op1, op1, sel), UNSPEC_VPERM);
+  emit_insn (gen_rtx_SET (VOIDmode, tmp, vperm));
+  emit_insn (gen_rtx_SET (VOIDmode, op0, stvx));
+}
+
 static rtx
 altivec_expand_lv_builtin (enum insn_code icode, tree exp, rtx target, bool blk)
 {
Index: gcc/testsuite/gcc.dg/vmx/lde-be-order.c
===================================================================
--- gcc/testsuite/gcc.dg/vmx/lde-be-order.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vmx/lde-be-order.c	(working copy)
@@ -0,0 +1,73 @@ 
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+
+#include "harness.h"
+
+static unsigned char svuc[16] __attribute__ ((aligned (16)));
+static signed char svsc[16] __attribute__ ((aligned (16)));
+static unsigned short svus[8] __attribute__ ((aligned (16)));
+static signed short svss[8] __attribute__ ((aligned (16)));
+static unsigned int svui[4] __attribute__ ((aligned (16)));
+static signed int svsi[4] __attribute__ ((aligned (16)));
+static float svf[4] __attribute__ ((aligned (16)));
+
+static void init ()
+{
+  int i;
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+  for (i = 15; i >= 0; --i)
+#else
+  for (i = 0; i < 16; ++i)
+#endif
+    {
+      svuc[i] = i;
+      svsc[i] = i - 8;
+    }
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+  for (i = 7; i >= 0; --i)
+#else
+  for (i = 0; i < 8; ++i)
+#endif
+    {
+      svus[i] = i;
+      svss[i] = i - 4;
+    }
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+  for (i = 3; i >= 0; --i)
+#else
+  for (i = 0; i < 4; ++i)
+#endif
+    {
+      svui[i] = i;
+      svsi[i] = i - 2;
+      svf[i] = i * 1.0f;
+    }
+}
+
+static void test ()
+{
+  vector unsigned char vuc;
+  vector signed char vsc;
+  vector unsigned short vus;
+  vector signed short vss;
+  vector unsigned int vui;
+  vector signed int vsi;
+  vector float vf;
+
+  init ();
+
+  vuc = vec_lde (9*1, (unsigned char *)svuc);
+  vsc = vec_lde (14*1, (signed char *)svsc);
+  vus = vec_lde (7*2, (unsigned short *)svus);
+  vss = vec_lde (1*2, (signed short *)svss);
+  vui = vec_lde (3*4, (unsigned int *)svui);
+  vsi = vec_lde (2*4, (signed int *)svsi);
+  vf  = vec_lde (0*4, (float *)svf);
+
+  check (vec_extract (vuc, 9) == 9, "vuc");
+  check (vec_extract (vsc, 14) == 6, "vsc");
+  check (vec_extract (vus, 7) == 7, "vus");
+  check (vec_extract (vss, 1) == -3, "vss");
+  check (vec_extract (vui, 3) == 3, "vui");
+  check (vec_extract (vsi, 2) == 0, "vsi");
+  check (vec_extract (vf,  0) == 0.0, "vf");
+}
Index: gcc/testsuite/gcc.dg/vmx/lde.c
===================================================================
--- gcc/testsuite/gcc.dg/vmx/lde.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vmx/lde.c	(working copy)
@@ -0,0 +1,59 @@ 
+#include "harness.h"
+
+static unsigned char svuc[16] __attribute__ ((aligned (16)));
+static signed char svsc[16] __attribute__ ((aligned (16)));
+static unsigned short svus[8] __attribute__ ((aligned (16)));
+static signed short svss[8] __attribute__ ((aligned (16)));
+static unsigned int svui[4] __attribute__ ((aligned (16)));
+static signed int svsi[4] __attribute__ ((aligned (16)));
+static float svf[4] __attribute__ ((aligned (16)));
+
+static void init ()
+{
+  unsigned int i;
+  for (i = 0; i < 16; ++i)
+    {
+      svuc[i] = i;
+      svsc[i] = i - 8;
+    }
+  for (i = 0; i < 8; ++i)
+    {
+      svus[i] = i;
+      svss[i] = i - 4;
+    }
+  for (i = 0; i < 4; ++i)
+    {
+      svui[i] = i;
+      svsi[i] = i - 2;
+      svf[i] = i * 1.0f;
+    }
+}
+
+static void test ()
+{
+  vector unsigned char vuc;
+  vector signed char vsc;
+  vector unsigned short vus;
+  vector signed short vss;
+  vector unsigned int vui;
+  vector signed int vsi;
+  vector float vf;
+
+  init ();
+
+  vuc = vec_lde (9*1, (unsigned char *)svuc);
+  vsc = vec_lde (14*1, (signed char *)svsc);
+  vus = vec_lde (7*2, (unsigned short *)svus);
+  vss = vec_lde (1*2, (signed short *)svss);
+  vui = vec_lde (3*4, (unsigned int *)svui);
+  vsi = vec_lde (2*4, (signed int *)svsi);
+  vf  = vec_lde (0*4, (float *)svf);
+
+  check (vec_extract (vuc, 9) == 9, "vuc");
+  check (vec_extract (vsc, 14) == 6, "vsc");
+  check (vec_extract (vus, 7) == 7, "vus");
+  check (vec_extract (vss, 1) == -3, "vss");
+  check (vec_extract (vui, 3) == 3, "vui");
+  check (vec_extract (vsi, 2) == 0, "vsi");
+  check (vec_extract (vf,  0) == 0.0, "vf");
+}
Index: gcc/testsuite/gcc.dg/vmx/ste-be-order.c
===================================================================
--- gcc/testsuite/gcc.dg/vmx/ste-be-order.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vmx/ste-be-order.c	(working copy)
@@ -0,0 +1,53 @@ 
+/* { dg-options "-maltivec=be -mabi=altivec -std=gnu99 -mno-vsx" } */
+
+#include "harness.h"
+
+static unsigned char svuc[16] __attribute__ ((aligned (16)));
+static signed char svsc[16] __attribute__ ((aligned (16)));
+static unsigned short svus[8] __attribute__ ((aligned (16)));
+static signed short svss[8] __attribute__ ((aligned (16)));
+static unsigned int svui[4] __attribute__ ((aligned (16)));
+static signed int svsi[4] __attribute__ ((aligned (16)));
+static float svf[4] __attribute__ ((aligned (16)));
+
+static void check_arrays ()
+{
+  check (svuc[9] == 9, "svuc");
+  check (svsc[14] == 6, "svsc");
+  check (svus[7] == 7, "svus");
+  check (svss[1] == -3, "svss");
+  check (svui[3] == 3, "svui");
+  check (svsi[2] == 0, "svsi");
+  check (svf[0] == 0.0, "svf");
+}
+
+static void test ()
+{
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+  vector unsigned char vuc = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
+  vector signed char vsc = {7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8};
+  vector unsigned short vus = {7,6,5,4,3,2,1,0};
+  vector signed short vss = {3,2,1,0,-1,-2,-3,-4};
+  vector unsigned int vui = {3,2,1,0};
+  vector signed int vsi = {1,0,-1,-2};
+  vector float vf = {3.0,2.0,1.0,0.0};
+#else
+  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 = {0.0,1.0,2.0,3.0};
+#endif
+
+  vec_ste (vuc, 9*1, (unsigned char *)svuc);
+  vec_ste (vsc, 14*1, (signed char *)svsc);
+  vec_ste (vus, 7*2, (unsigned short *)svus);
+  vec_ste (vss, 1*2, (signed short *)svss);
+  vec_ste (vui, 3*4, (unsigned int *)svui);
+  vec_ste (vsi, 2*4, (signed int *)svsi);
+  vec_ste (vf,  0*4, (float *)svf);
+
+  check_arrays ();
+}
Index: gcc/testsuite/gcc.dg/vmx/ste.c
===================================================================
--- gcc/testsuite/gcc.dg/vmx/ste.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vmx/ste.c	(working copy)
@@ -0,0 +1,41 @@ 
+#include "harness.h"
+
+static unsigned char svuc[16] __attribute__ ((aligned (16)));
+static signed char svsc[16] __attribute__ ((aligned (16)));
+static unsigned short svus[8] __attribute__ ((aligned (16)));
+static signed short svss[8] __attribute__ ((aligned (16)));
+static unsigned int svui[4] __attribute__ ((aligned (16)));
+static signed int svsi[4] __attribute__ ((aligned (16)));
+static float svf[4] __attribute__ ((aligned (16)));
+
+static void check_arrays ()
+{
+  check (svuc[9] == 9, "svuc");
+  check (svsc[14] == 6, "svsc");
+  check (svus[7] == 7, "svus");
+  check (svss[1] == -3, "svss");
+  check (svui[3] == 3, "svui");
+  check (svsi[2] == 0, "svsi");
+  check (svf[0] == 0.0, "svf");
+}
+
+static void test ()
+{
+  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 = {0.0,1.0,2.0,3.0};
+
+  vec_ste (vuc, 9*1, (unsigned char *)svuc);
+  vec_ste (vsc, 14*1, (signed char *)svsc);
+  vec_ste (vus, 7*2, (unsigned short *)svus);
+  vec_ste (vss, 1*2, (signed short *)svss);
+  vec_ste (vui, 3*4, (unsigned int *)svui);
+  vec_ste (vsi, 2*4, (signed int *)svsi);
+  vec_ste (vf,  0*4, (float *)svf);
+
+  check_arrays ();
+}