diff mbox

, Patch #4, Improve vector int/long initialization on PowerPC

Message ID 20160811231517.GA2148@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner Aug. 11, 2016, 11:15 p.m. UTC
This patch was originally part of patch #3, but I separated it out as I rework
what used to be part of patch #3 to fix some issues.

This patch adds support for using the ISA 3.0 MTVSRDD instruction when
initializing vector long vectors with variables.  I also changed the CPU type
of the other use of MTVSRDD to be vecperm as Pat suggested.

I added two general tests (vec-init-1.c and vec-init-2.c) that test various
forms of vector initialization to make sure the compiler generates the correct
code.  These tests will test optimizations that the future patches will
enhance.  I also added a third test (vec-init-3.c) to specifically test whether
MTVSRDD is generated.

I did a bootstrap and make check on a little endian power8 system, and there
were no regressions.  Can I install this patch to the trunk?

[gcc]
2016-08-11  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/vsx.md (vsx_concat_<mode>): Add support for the
	ISA 3.0 MTVSRDD instruction.
	(vsx_splat_<mode>): Change cpu type of MTVSRDD instruction to
	vecperm.

[gcc/testsuite]
2016-08-11  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/powerpc/vec-init-1.c: New tests to test various
	vector initialization options.
	* gcc.target/powerpc/vec-init-2.c: Likewise.
	* gcc.target/powerpc/vec-init-3.c: New test to make sure MTVSRDD
	is generated on ISA 3.0.

Comments

Segher Boessenkool Aug. 12, 2016, 12:20 a.m. UTC | #1
On Thu, Aug 11, 2016 at 07:15:17PM -0400, Michael Meissner wrote:
> This patch was originally part of patch #3, but I separated it out as I rework
> what used to be part of patch #3 to fix some issues.
> 
> This patch adds support for using the ISA 3.0 MTVSRDD instruction when
> initializing vector long vectors with variables.  I also changed the CPU type
> of the other use of MTVSRDD to be vecperm as Pat suggested.
> 
> I added two general tests (vec-init-1.c and vec-init-2.c) that test various
> forms of vector initialization to make sure the compiler generates the correct
> code.  These tests will test optimizations that the future patches will
> enhance.  I also added a third test (vec-init-3.c) to specifically test whether
> MTVSRDD is generated.
> 
> I did a bootstrap and make check on a little endian power8 system, and there
> were no regressions.  Can I install this patch to the trunk?

Yes, please do.  Thanks,


Segher


> 2016-08-11  Michael Meissner  <meissner@linux.vnet.ibm.com>
> 
> 	* config/rs6000/vsx.md (vsx_concat_<mode>): Add support for the
> 	ISA 3.0 MTVSRDD instruction.
> 	(vsx_splat_<mode>): Change cpu type of MTVSRDD instruction to
> 	vecperm.
> 
> [gcc/testsuite]
> 2016-08-11  Michael Meissner  <meissner@linux.vnet.ibm.com>
> 
> 	* gcc.target/powerpc/vec-init-1.c: New tests to test various
> 	vector initialization options.
> 	* gcc.target/powerpc/vec-init-2.c: Likewise.
> 	* gcc.target/powerpc/vec-init-3.c: New test to make sure MTVSRDD
> 	is generated on ISA 3.0.
diff mbox

Patch

Index: gcc/config/rs6000/rs6000.c
===================================================================
Index: gcc/config/rs6000/vsx.md
===================================================================
--- gcc/config/rs6000/vsx.md	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 239334)
+++ gcc/config/rs6000/vsx.md	(.../gcc/config/rs6000)	(working copy)
@@ -1911,16 +1911,24 @@  (define_insn "*vsx_float_fix_v2df2"
 
 ;; Build a V2DF/V2DI vector from two scalars
 (define_insn "vsx_concat_<mode>"
-  [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSr>,?<VSa>")
+  [(set (match_operand:VSX_D 0 "gpc_reg_operand" "=<VSa>,we")
 	(vec_concat:VSX_D
-	 (match_operand:<VS_scalar> 1 "vsx_register_operand" "<VS_64reg>,<VSa>")
-	 (match_operand:<VS_scalar> 2 "vsx_register_operand" "<VS_64reg>,<VSa>")))]
+	 (match_operand:<VS_scalar> 1 "gpc_reg_operand" "<VS_64reg>,r")
+	 (match_operand:<VS_scalar> 2 "gpc_reg_operand" "<VS_64reg>,r")))]
   "VECTOR_MEM_VSX_P (<MODE>mode)"
 {
-  if (BYTES_BIG_ENDIAN)
-    return "xxpermdi %x0,%x1,%x2,0";
+  if (which_alternative == 0)
+    return (BYTES_BIG_ENDIAN
+	    ? "xxpermdi %x0,%x1,%x2,0"
+	    : "xxpermdi %x0,%x2,%x1,0");
+
+  else if (which_alternative == 1)
+    return (BYTES_BIG_ENDIAN
+	    ? "mtvsrdd %x0,%1,%2"
+	    : "mtvsrdd %x0,%2,%1");
+
   else
-    return "xxpermdi %x0,%x2,%x1,0";
+    gcc_unreachable ();
 }
   [(set_attr "type" "vecperm")])
 
@@ -2650,7 +2658,7 @@  (define_insn "vsx_splat_<mode>"
    xxpermdi %x0,%x1,%x1,0
    lxvdsx %x0,%y1
    mtvsrdd %x0,%1,%1"
-  [(set_attr "type" "vecperm,vecload,mftgpr")])
+  [(set_attr "type" "vecperm,vecload,vecperm")])
 
 ;; V4SI splat (ISA 3.0)
 ;; When SI's are allowed in VSX registers, add XXSPLTW support
Index: gcc/testsuite/gcc.target/powerpc/vec-init-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vec-init-1.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vec-init-1.c	(.../gcc/testsuite/gcc.target/powerpc)	(revision 239334)
@@ -0,0 +1,169 @@ 
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <altivec.h>
+
+#define ELEMENTS -1, 2, 0, -123456
+#define SPLAT 0x01234567
+
+vector int sv = (vector int) { ELEMENTS };
+vector int splat = (vector int) { SPLAT, SPLAT, SPLAT, SPLAT };
+vector int sv_global, sp_global;
+static vector int sv_static, sp_static;
+static const int expected[] = { ELEMENTS };
+
+extern void check (vector int a)
+  __attribute__((__noinline__));
+
+extern void check_splat (vector int a)
+  __attribute__((__noinline__));
+
+extern vector int pack_reg (int a, int b, int c, int d)
+  __attribute__((__noinline__));
+
+extern vector int pack_const (void)
+  __attribute__((__noinline__));
+
+extern void pack_ptr (vector int *p, int a, int b, int c, int d)
+  __attribute__((__noinline__));
+
+extern void pack_static (int a, int b, int c, int d)
+  __attribute__((__noinline__));
+
+extern void pack_global (int a, int b, int c, int d)
+  __attribute__((__noinline__));
+
+extern vector int splat_reg (int a)
+  __attribute__((__noinline__));
+
+extern vector int splat_const (void)
+  __attribute__((__noinline__));
+
+extern void splat_ptr (vector int *p, int a)
+  __attribute__((__noinline__));
+
+extern void splat_static (int a)
+  __attribute__((__noinline__));
+
+extern void splat_global (int a)
+  __attribute__((__noinline__));
+
+void
+check (vector int a)
+{
+  size_t i;
+
+  for (i = 0; i < 4; i++)
+    if (vec_extract (a, i) != expected[i])
+      abort ();
+}
+
+void
+check_splat (vector int a)
+{
+  size_t i;
+
+  for (i = 0; i < 4; i++)
+    if (vec_extract (a, i) != SPLAT)
+      abort ();
+}
+
+vector int
+pack_reg (int a, int b, int c, int d)
+{
+  return (vector int) { a, b, c, d };
+}
+
+vector int
+pack_const (void)
+{
+  return (vector int) { ELEMENTS };
+}
+
+void
+pack_ptr (vector int *p, int a, int b, int c, int d)
+{
+  *p = (vector int) { a, b, c, d };
+}
+
+void
+pack_static (int a, int b, int c, int d)
+{
+  sv_static = (vector int) { a, b, c, d };
+}
+
+void
+pack_global (int a, int b, int c, int d)
+{
+  sv_global = (vector int) { a, b, c, d };
+}
+
+vector int
+splat_reg (int a)
+{
+  return (vector int) { a, a, a, a };
+}
+
+vector int
+splat_const (void)
+{
+  return (vector int) { SPLAT, SPLAT, SPLAT, SPLAT };
+}
+
+void
+splat_ptr (vector int *p, int a)
+{
+  *p = (vector int) { a, a, a, a };
+}
+
+void
+splat_static (int a)
+{
+  sp_static = (vector int) { a, a, a, a };
+}
+
+void
+splat_global (int a)
+{
+  sp_global = (vector int) { a, a, a, a };
+}
+
+int main (void)
+{
+  vector int sv2, sv3;
+
+  check (sv);
+
+  check (pack_reg (ELEMENTS));
+
+  check (pack_const ());
+
+  pack_ptr (&sv2, ELEMENTS);
+  check (sv2);
+
+  pack_static (ELEMENTS);
+  check (sv_static);
+
+  pack_global (ELEMENTS);
+  check (sv_global);
+
+  check_splat (splat);
+
+  check_splat (splat_reg (SPLAT));
+
+  check_splat (splat_const ());
+
+  splat_ptr (&sv2, SPLAT);
+  check_splat (sv2);
+
+  splat_static (SPLAT);
+  check_splat (sp_static);
+
+  splat_global (SPLAT);
+  check_splat (sp_global);
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vec-init-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vec-init-2.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vec-init-2.c	(.../gcc/testsuite/gcc.target/powerpc)	(revision 239334)
@@ -0,0 +1,169 @@ 
+/* { dg-do run { target { powerpc*-*-linux* && lp64 } } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2 -mvsx" } */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <altivec.h>
+
+#define ELEMENTS -12345678L, 9L
+#define SPLAT 0x0123456789ABCDE
+
+vector long sv = (vector long) { ELEMENTS };
+vector long splat = (vector long) { SPLAT, SPLAT };
+vector long sv_global, sp_global;
+static vector long sv_static, sp_static;
+static const int expected[] = { ELEMENTS };
+
+extern void check (vector long a)
+  __attribute__((__noinline__));
+
+extern void check_splat (vector long a)
+  __attribute__((__noinline__));
+
+extern vector long pack_reg (long a, long b)
+  __attribute__((__noinline__));
+
+extern vector long pack_const (void)
+  __attribute__((__noinline__));
+
+extern void pack_ptr (vector long *p, long a, long b)
+  __attribute__((__noinline__));
+
+extern void pack_static (long a, long b)
+  __attribute__((__noinline__));
+
+extern void pack_global (long a, long b)
+  __attribute__((__noinline__));
+
+extern vector long splat_reg (long a)
+  __attribute__((__noinline__));
+
+extern vector long splat_const (void)
+  __attribute__((__noinline__));
+
+extern void splat_ptr (vector long *p, long a)
+  __attribute__((__noinline__));
+
+extern void splat_static (long a)
+  __attribute__((__noinline__));
+
+extern void splat_global (long a)
+  __attribute__((__noinline__));
+
+void
+check (vector long a)
+{
+  size_t i;
+
+  for (i = 0; i < 2; i++)
+    if (vec_extract (a, i) != expected[i])
+      abort ();
+}
+
+void
+check_splat (vector long a)
+{
+  size_t i;
+
+  for (i = 0; i < 2; i++)
+    if (vec_extract (a, i) != SPLAT)
+      abort ();
+}
+
+vector long
+pack_reg (long a, long b)
+{
+  return (vector long) { a, b };
+}
+
+vector long
+pack_const (void)
+{
+  return (vector long) { ELEMENTS };
+}
+
+void
+pack_ptr (vector long *p, long a, long b)
+{
+  *p = (vector long) { a, b };
+}
+
+void
+pack_static (long a, long b)
+{
+  sv_static = (vector long) { a, b };
+}
+
+void
+pack_global (long a, long b)
+{
+  sv_global = (vector long) { a, b };
+}
+
+vector long
+splat_reg (long a)
+{
+  return (vector long) { a, a };
+}
+
+vector long
+splat_const (void)
+{
+  return (vector long) { SPLAT, SPLAT };
+}
+
+void
+splat_ptr (vector long *p, long a)
+{
+  *p = (vector long) { a, a };
+}
+
+void
+splat_static (long a)
+{
+  sp_static = (vector long) { a, a };
+}
+
+void
+splat_global (long a)
+{
+  sp_global = (vector long) { a, a };
+}
+
+int  main (void)
+{
+  vector long sv2, sv3;
+
+  check (sv);
+
+  check (pack_reg (ELEMENTS));
+
+  check (pack_const ());
+
+  pack_ptr (&sv2, ELEMENTS);
+  check (sv2);
+
+  pack_static (ELEMENTS);
+  check (sv_static);
+
+  pack_global (ELEMENTS);
+  check (sv_global);
+
+  check_splat (splat);
+
+  check_splat (splat_reg (SPLAT));
+
+  check_splat (splat_const ());
+
+  splat_ptr (&sv2, SPLAT);
+  check_splat (sv2);
+
+  splat_static (SPLAT);
+  check_splat (sp_static);
+
+  splat_global (SPLAT);
+  check_splat (sp_global);
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/vec-init-3.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vec-init-3.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vec-init-3.c	(.../gcc/testsuite/gcc.target/powerpc)	(revision 239334)
@@ -0,0 +1,12 @@ 
+/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9 -O2 -mupper-regs-di" } */
+
+vector long
+merge (long a, long b)
+{
+  return (vector long) { a, b };
+}
+
+/* { dg-final { scan-assembler "mtvsrdd" } } */