, Add PowerPC ISA 3.0 support for xxinsertw, vinserth, and vinsertb instructions
diff mbox

Message ID 20161113060329.GA2440@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner Nov. 13, 2016, 6:03 a.m. UTC
I modified the vec_insert built-in so that it generates the insert word,
half-word, and byte instructions (XXINSERTW, VINSERTH, and VINSERTB) on ISA 3.0
(power9).

I did the usual bootstrap and make check with no regressions.  In addition, I
ran a program on the simulator that verified that the XXINSERTW code works.
Can I install this patch on the trunk?

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

	* config/rs6000/rs6000.c (rs6000_expand_vector_set): Add support
	for using xxinsertw and vinsert{b,h} on ISA 3.0.

	* config/rs6000/vsx.md (vsx_extract_<mode>): Update comment.
	(vsx_set_<mode>_p9): New insn to generate xxinsertw and
	vinsert{b,h} on ISA 3.0.

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

	* gcc.target/powerpc/vec-set-int.c: New test.
	* gcc.target/powerpc/vec-set-short.c: Likesie.
	* gcc.target/powerpc/vec-set-char.c: Likewise.

Comments

Segher Boessenkool Nov. 13, 2016, 2:23 p.m. UTC | #1
Hi Mike,

On Sun, Nov 13, 2016 at 01:03:29AM -0500, Michael Meissner wrote:
> 	* gcc.target/powerpc/vec-set-short.c: Likesie.

Typo here.

> --- gcc/config/rs6000/rs6000.c	(svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 242318)
> +++ gcc/config/rs6000/rs6000.c	(.../gcc/config/rs6000)	(working copy)
> @@ -7095,12 +7095,32 @@ rs6000_expand_vector_set (rtx target, rt
>    int width = GET_MODE_SIZE (inner_mode);
>    int i;
>  
> -  if (VECTOR_MEM_VSX_P (mode) && (mode == V2DFmode || mode == V2DImode))
> +  if (VECTOR_MEM_VSX_P (mode))
>      {
> -      rtx (*set_func) (rtx, rtx, rtx, rtx)
> -	= ((mode == V2DFmode) ? gen_vsx_set_v2df : gen_vsx_set_v2di);
> -      emit_insn (set_func (target, target, val, GEN_INT (elt)));
> -      return;
> +      rtx (*set_func) (rtx, rtx, rtx, rtx) = (rtx (*) (rtx, rtx, rtx, rtx))0;

Space after a cast.  But, do you need a function pointer at all?  I.e.
instead of

> +      if (mode == V2DFmode)
> +	set_func = gen_vsx_set_v2df;
> +
> +      else if (mode == V2DImode)
> +	set_func = gen_vsx_set_v2di;

do

      rtx_insn *insn = NULL;

      if (mode == V2DFmode)
	insn = gen_vsx_set_v2df (target, target, val, GEN_INT (elt));

      else if (mode == V2DImode)
	insn = gen_vsx_set_v2di (target, target, val, GEN_INT (elt));

[ snip ]

> +      if (set_func)
> +	{
> +	  emit_insn (set_func (target, target, val, GEN_INT (elt)));
> +	  return;

      if (insn)
	{
	  emit_insn (insn);
	  return;
	}

(and maybe do that GEN_INT to a var as well).  Much more readable.


Segher

Patch
diff mbox

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 242318)
+++ gcc/config/rs6000/rs6000.c	(.../gcc/config/rs6000)	(working copy)
@@ -7095,12 +7095,32 @@  rs6000_expand_vector_set (rtx target, rt
   int width = GET_MODE_SIZE (inner_mode);
   int i;
 
-  if (VECTOR_MEM_VSX_P (mode) && (mode == V2DFmode || mode == V2DImode))
+  if (VECTOR_MEM_VSX_P (mode))
     {
-      rtx (*set_func) (rtx, rtx, rtx, rtx)
-	= ((mode == V2DFmode) ? gen_vsx_set_v2df : gen_vsx_set_v2di);
-      emit_insn (set_func (target, target, val, GEN_INT (elt)));
-      return;
+      rtx (*set_func) (rtx, rtx, rtx, rtx) = (rtx (*) (rtx, rtx, rtx, rtx))0;
+
+      if (mode == V2DFmode)
+	set_func = gen_vsx_set_v2df;
+
+      else if (mode == V2DImode)
+	set_func = gen_vsx_set_v2di;
+
+      else if (TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER
+	       && TARGET_UPPER_REGS_DI && TARGET_POWERPC64)
+	{
+	  if (mode == V4SImode)
+	    set_func = gen_vsx_set_v4si_p9;
+	  else if (mode == V8HImode)
+	    set_func = gen_vsx_set_v8hi_p9;
+	  else if (mode == V16QImode)
+	    set_func = gen_vsx_set_v16qi_p9;
+	}
+
+      if (set_func)
+	{
+	  emit_insn (set_func (target, target, val, GEN_INT (elt)));
+	  return;
+	}
     }
 
   /* Simplify setting single element vectors like V1TImode.  */
Index: gcc/config/rs6000/vsx.md
===================================================================
--- gcc/config/rs6000/vsx.md	(svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 242318)
+++ gcc/config/rs6000/vsx.md	(.../gcc/config/rs6000)	(working copy)
@@ -2514,9 +2514,9 @@  (define_expand "vec_perm_const<mode>"
     FAIL;
 })
 
-;; Extraction of a single element in a small integer vector.  None of the small
-;; types are currently allowed in a vector register, so we extract to a DImode
-;; and either do a direct move or store.
+;; Extraction of a single element in a small integer vector.  Until ISA 3.0,
+;; none of the small types were allowed in a vector register, so we had to
+;; extract to a DImode and either do a direct move or store.
 (define_expand  "vsx_extract_<mode>"
   [(parallel [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand")
 		   (vec_select:<VS_scalar>
@@ -2839,6 +2839,31 @@  (define_insn_and_split "*vsx_extract_si_
   DONE;
 })
 
+;; V4SI/V8HI/V16QI set operation on ISA 3.0
+(define_insn "vsx_set_<mode>_p9"
+  [(set (match_operand:VSX_EXTRACT_I 0 "gpc_reg_operand" "=<VSX_EX>")
+	(unspec:VSX_EXTRACT_I
+	 [(match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "0")
+	  (match_operand:<VS_scalar> 2 "gpc_reg_operand" "<VSX_EX>")
+	  (match_operand:QI 3 "<VSX_EXTRACT_PREDICATE>" "n")]
+	 UNSPEC_VSX_SET))]
+  "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_P9_VECTOR && TARGET_VSX_SMALL_INTEGER
+   && TARGET_UPPER_REGS_DI && TARGET_POWERPC64"
+{
+  int ele = INTVAL (operands[3]);
+  int nunits = GET_MODE_NUNITS (<MODE>mode);
+
+  if (!VECTOR_ELT_ORDER_BIG)
+    ele = nunits - 1 - ele;
+
+  operands[3] = GEN_INT (nunits * ele);
+  if (<MODE>mode == V4SImode)
+    return "xxinsertw %x0,%x2,%3";
+  else
+    return "vinsert<wd> %0,%2,%3";
+}
+  [(set_attr "type" "vecperm")])
+
 ;; Expanders for builtins
 (define_expand "vsx_mergel_<mode>"
   [(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
Index: gcc/testsuite/gcc.target/powerpc/vec-set-char.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vec-set-char.c	(svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vec-set-char.c	(.../gcc/testsuite/gcc.target/powerpc)	(revision 242346)
@@ -0,0 +1,40 @@ 
+#include <altivec.h>
+
+/* { 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 -mvsx-small-integer" } */
+
+vector char
+insert_0_0 (vector char v)
+{
+  return vec_insert (0, v, 0);
+}
+
+vector char
+insert_m1_1 (vector char v)
+{
+  return vec_insert (-1, v, 1);
+}
+
+vector char
+insert_5_2 (vector char v)
+{
+  return vec_insert (5, v, 2);
+}
+
+vector char
+insert_mem_15 (vector char v, char *p)
+{
+  return vec_insert (*p, v, 15);
+}
+
+/* { dg-final { scan-assembler     "vinsertb"  } } */
+/* { dg-final { scan-assembler     "xxsplitib" } } */
+/* { dg-final { scan-assembler     "vspltisb"  } } */
+/* { dg-final { scan-assembler-not "mtvsrd"    } } */
+/* { dg-final { scan-assembler-not "mtvsrdd"   } } */
+/* { dg-final { scan-assembler-not "mtvsrwa"   } } */
+/* { dg-final { scan-assembler-not "mtvsrwz"   } } */
+/* { dg-final { scan-assembler-not "mfvsrd"    } } */
+/* { dg-final { scan-assembler-not "mfvsrwz"   } } */
Index: gcc/testsuite/gcc.target/powerpc/vec-set-int.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vec-set-int.c	(svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vec-set-int.c	(.../gcc/testsuite/gcc.target/powerpc)	(revision 242346)
@@ -0,0 +1,40 @@ 
+#include <altivec.h>
+
+/* { 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 -mvsx-small-integer" } */
+
+vector int
+insert_0_0 (vector int v)
+{
+  return vec_insert (0, v, 0);
+}
+
+vector int
+insert_m1_1 (vector int v)
+{
+  return vec_insert (-1, v, 1);
+}
+
+vector int
+insert_5_2 (vector int v)
+{
+  return vec_insert (5, v, 2);
+}
+
+vector int
+insert_mem_3 (vector int v, int *p)
+{
+  return vec_insert (*p, v, 3);
+}
+
+/* { dg-final { scan-assembler     "xxinsertw" } } */
+/* { dg-final { scan-assembler     "xxsplitib" } } */
+/* { dg-final { scan-assembler     "vspltisw"  } } */
+/* { dg-final { scan-assembler-not "mtvsrd"    } } */
+/* { dg-final { scan-assembler-not "mtvsrdd"   } } */
+/* { dg-final { scan-assembler-not "mtvsrwa"   } } */
+/* { dg-final { scan-assembler-not "mtvsrwz"   } } */
+/* { dg-final { scan-assembler-not "mfvsrd"    } } */
+/* { dg-final { scan-assembler-not "mfvsrwz"   } } */
Index: gcc/testsuite/gcc.target/powerpc/vec-set-short.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vec-set-short.c	(svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vec-set-short.c	(.../gcc/testsuite/gcc.target/powerpc)	(revision 242346)
@@ -0,0 +1,40 @@ 
+#include <altivec.h>
+
+/* { 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 -mvsx-small-integer" } */
+
+vector short
+insert_0_0 (vector short v)
+{
+  return vec_insert (0, v, 0);
+}
+
+vector short
+insert_m1_1 (vector short v)
+{
+  return vec_insert (-1, v, 1);
+}
+
+vector short
+insert_5_2 (vector short v)
+{
+  return vec_insert (5, v, 2);
+}
+
+vector short
+insert_mem_7 (vector short v, short *p)
+{
+  return vec_insert (*p, v, 7);
+}
+
+/* { dg-final { scan-assembler     "vinserth"  } } */
+/* { dg-final { scan-assembler     "xxsplitib" } } */
+/* { dg-final { scan-assembler     "vspltish"  } } */
+/* { dg-final { scan-assembler-not "mtvsrd"    } } */
+/* { dg-final { scan-assembler-not "mtvsrdd"   } } */
+/* { dg-final { scan-assembler-not "mtvsrwa"   } } */
+/* { dg-final { scan-assembler-not "mtvsrwz"   } } */
+/* { dg-final { scan-assembler-not "mfvsrd"    } } */
+/* { dg-final { scan-assembler-not "mfvsrwz"   } } */