===================================================================
@@ -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. */
===================================================================
@@ -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" ""))
===================================================================
@@ -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" } } */
===================================================================
@@ -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" } } */
===================================================================
@@ -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" } } */