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  <meiss...@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  <meiss...@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.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  
(svn+ssh://meiss...@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://meiss...@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://meiss...@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://meiss...@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://meiss...@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"   } } */

Reply via email to