aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meissner <meissner@linux.vnet.ibm.com>2016-05-31 22:30:49 +0000
committerMichael Meissner <meissner@linux.vnet.ibm.com>2016-05-31 22:30:49 +0000
commita392408d09f870ac83ee7b4101146d2f8a8f9869 (patch)
tree43fe413dde4f61b9b4bab1a0e130fa556d407a88
parentb7e05fb83fb7a6319389f625d2b4c98d2ccaf5a7 (diff)
Backport vparity/vctz changes to gcc 6
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/ibm/power9-gcc6@236960 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/config/rs6000/altivec.h17
-rw-r--r--gcc/config/rs6000/altivec.md27
-rw-r--r--gcc/config/rs6000/rs6000-builtin.def125
-rw-r--r--gcc/config/rs6000/rs6000-c.c73
-rw-r--r--gcc/config/rs6000/rs6000.md4
-rw-r--r--gcc/config/rs6000/vector.md19
-rw-r--r--gcc/doc/extend.texi54
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ctz-3.c62
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ctz-4.c110
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p9-vparity.c107
10 files changed, 596 insertions, 2 deletions
diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index 5fc1cce0165..f9fac682b7b 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -384,6 +384,23 @@
#define vec_vupklsw __builtin_vec_vupklsw
#endif
+#ifdef _ARCH_PWR9
+/* Vector additions added in ISA 3.0. */
+#define vec_vctz __builtin_vec_vctz
+#define vec_cntlz __builtin_vec_vctz
+#define vec_vctzb __builtin_vec_vctzb
+#define vec_vctzd __builtin_vec_vctzd
+#define vec_vctzh __builtin_vec_vctzh
+#define vec_vctzw __builtin_vec_vctzw
+#define vec_vprtyb __builtin_vec_vprtyb
+#define vec_vprtybd __builtin_vec_vprtybd
+#define vec_vprtybw __builtin_vec_vprtybw
+
+#ifdef _ARCH_PPC64
+#define vec_vprtybq __builtin_vec_vprtybq
+#endif
+#endif
+
/* Predicates.
For C++, we use templates in order to allow non-parenthesized arguments.
For C, instead, we use macros since non-parenthesized arguments were
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 452d9e2cee5..8e22924d2b2 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -190,6 +190,13 @@
(KF "FLOAT128_VECTOR_P (KFmode)")
(TF "FLOAT128_VECTOR_P (TFmode)")])
+;; Specific iterator for parity which does not have a byte/half-word form, but
+;; does have a quad word form
+(define_mode_iterator VParity [V4SI
+ V2DI
+ V1TI
+ (TI "TARGET_VSX_TIMODE")])
+
(define_mode_attr VI_char [(V2DI "d") (V4SI "w") (V8HI "h") (V16QI "b")])
(define_mode_attr VI_scalar [(V2DI "DI") (V4SI "SI") (V8HI "HI") (V16QI "QI")])
(define_mode_attr VI_unit [(V16QI "VECTOR_UNIT_ALTIVEC_P (V16QImode)")
@@ -3362,7 +3369,7 @@
}")
-;; Power8 vector instructions encoded as Altivec instructions
+;; Power8/power9 vector instructions encoded as Altivec instructions
;; Vector count leading zeros
(define_insn "*p8v_clz<mode>2"
@@ -3373,6 +3380,15 @@
[(set_attr "length" "4")
(set_attr "type" "vecsimple")])
+;; Vector count trailing zeros
+(define_insn "*p9v_ctz<mode>2"
+ [(set (match_operand:VI2 0 "register_operand" "=v")
+ (ctz:VI2 (match_operand:VI2 1 "register_operand" "v")))]
+ "TARGET_P9_VECTOR"
+ "vctz<wd> %0,%1"
+ [(set_attr "length" "4")
+ (set_attr "type" "vecsimple")])
+
;; Vector population count
(define_insn "*p8v_popcount<mode>2"
[(set (match_operand:VI2 0 "register_operand" "=v")
@@ -3382,6 +3398,15 @@
[(set_attr "length" "4")
(set_attr "type" "vecsimple")])
+;; Vector parity
+(define_insn "*p9v_parity<mode>2"
+ [(set (match_operand:VParity 0 "register_operand" "=v")
+ (parity:VParity (match_operand:VParity 1 "register_operand" "v")))]
+ "TARGET_P9_VECTOR"
+ "vprtyb<wd> %0,%1"
+ [(set_attr "length" "4")
+ (set_attr "type" "vecsimple")])
+
;; Vector Gather Bits by Bytes by Doubleword
(define_insn "p8v_vgbbd"
[(set (match_operand:V16QI 0 "register_operand" "=v")
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 6f332788684..40573dc1a13 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -647,8 +647,113 @@
| RS6000_BTC_BINARY), \
CODE_FOR_ ## ICODE) /* ICODE */
+
+/* Miscellaneous builtins for instructions added in ISA 3.0. These
+ instructions don't require either the DFP or VSX options, just the basic
+ ISA 3.0 enablement since they operate on general purpose registers. */
+#define BU_P9_MISC_1(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_1 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_MODULO, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_UNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+/* Miscellaneous builtins for instructions added in ISA 3.0. These
+ instructions don't require either the DFP or VSX options, just the basic
+ ISA 3.0 enablement since they operate on general purpose registers,
+ and they require 64-bit addressing. */
+#define BU_P9_64BIT_MISC_0(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_0 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_MODULO \
+ | RS6000_BTM_64BIT, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_SPECIAL), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+/* Miscellaneous builtins for instructions added in ISA 3.0. These
+ instructions don't require either the DFP or VSX options, just the basic
+ ISA 3.0 enablement since they operate on general purpose registers. */
+#define BU_P9_MISC_0(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_0 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_MODULO, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_SPECIAL), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+/* ISA 3.0 (power9) vector convenience macros. */
+/* For the instructions that are encoded as altivec instructions use
+ __builtin_altivec_ as the builtin name. */
+#define BU_P9V_AV_1(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_1 (P9V_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_altivec_" NAME, /* NAME */ \
+ RS6000_BTM_P9_VECTOR, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_UNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_P9V_AV_2(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_2 (P9V_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_altivec_" NAME, /* NAME */ \
+ RS6000_BTM_P9_VECTOR, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_BINARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_P9V_AV_3(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_3 (P9V_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_altivec_" NAME, /* NAME */ \
+ RS6000_BTM_P9_VECTOR, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_TERNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_P9V_AV_P(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_P (P9V_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_altivec_" NAME, /* NAME */ \
+ RS6000_BTM_P9_VECTOR, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_PREDICATE), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+/* For the instructions encoded as VSX instructions use __builtin_vsx as the
+ builtin name. */
+#define BU_P9V_VSX_1(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_1 (P9V_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_vsx_" NAME, /* NAME */ \
+ RS6000_BTM_P9_VECTOR, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_UNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_P9V_OVERLOAD_1(ENUM, NAME) \
+ RS6000_BUILTIN_1 (P9V_BUILTIN_VEC_ ## ENUM, /* ENUM */ \
+ "__builtin_vec_" NAME, /* NAME */ \
+ RS6000_BTM_P9_VECTOR, /* MASK */ \
+ (RS6000_BTC_OVERLOADED /* ATTR */ \
+ | RS6000_BTC_UNARY), \
+ CODE_FOR_nothing) /* ICODE */
+
+#define BU_P9V_OVERLOAD_2(ENUM, NAME) \
+ RS6000_BUILTIN_2 (P9V_BUILTIN_VEC_ ## ENUM, /* ENUM */ \
+ "__builtin_vec_" NAME, /* NAME */ \
+ RS6000_BTM_P9_VECTOR, /* MASK */ \
+ (RS6000_BTC_OVERLOADED /* ATTR */ \
+ | RS6000_BTC_BINARY), \
+ CODE_FOR_nothing) /* ICODE */
+
+#define BU_P9V_OVERLOAD_3(ENUM, NAME) \
+ RS6000_BUILTIN_3 (P9V_BUILTIN_VEC_ ## ENUM, /* ENUM */ \
+ "__builtin_vec_" NAME, /* NAME */ \
+ RS6000_BTM_P9_VECTOR, /* MASK */ \
+ (RS6000_BTC_OVERLOADED /* ATTR */ \
+ | RS6000_BTC_TERNARY), \
+ CODE_FOR_nothing) /* ICODE */
#endif
+
/* Insure 0 is not a legitimate index. */
BU_SPECIAL_X (RS6000_BUILTIN_NONE, NULL, 0, RS6000_BTC_MISC)
@@ -1659,6 +1764,26 @@ BU_LDBL128_2 (UNPACK_TF, "unpack_longdouble", CONST, unpacktf)
BU_P7_MISC_2 (PACK_V1TI, "pack_vector_int128", CONST, packv1ti)
BU_P7_MISC_2 (UNPACK_V1TI, "unpack_vector_int128", CONST, unpackv1ti)
+/* 1 argument vector functions added in ISA 3.0 (power9). */
+BU_P9V_AV_1 (VCTZB, "vctzb", CONST, ctzv16qi2)
+BU_P9V_AV_1 (VCTZH, "vctzh", CONST, ctzv8hi2)
+BU_P9V_AV_1 (VCTZW, "vctzw", CONST, ctzv4si2)
+BU_P9V_AV_1 (VCTZD, "vctzd", CONST, ctzv2di2)
+BU_P9V_AV_1 (VPRTYBD, "vprtybd", CONST, parityv2di2)
+BU_P9V_AV_1 (VPRTYBQ, "vprtybq", CONST, parityv1ti2)
+BU_P9V_AV_1 (VPRTYBW, "vprtybw", CONST, parityv4si2)
+
+/* ISA 3.0 vector overloaded 1 argument functions. */
+BU_P9V_OVERLOAD_1 (VCTZ, "vctz")
+BU_P9V_OVERLOAD_1 (VCTZB, "vctzb")
+BU_P9V_OVERLOAD_1 (VCTZH, "vctzh")
+BU_P9V_OVERLOAD_1 (VCTZW, "vctzw")
+BU_P9V_OVERLOAD_1 (VCTZD, "vctzd")
+BU_P9V_OVERLOAD_1 (VPRTYB, "vprtyb")
+BU_P9V_OVERLOAD_1 (VPRTYBD, "vprtybd")
+BU_P9V_OVERLOAD_1 (VPRTYBQ, "vprtybq")
+BU_P9V_OVERLOAD_1 (VPRTYBW, "vprtybw")
+
/* 1 argument crypto functions. */
BU_CRYPTO_1 (VSBOX, "vsbox", CONST, crypto_vsbox)
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index 0985bb706fd..5b4ccf1f047 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -4215,6 +4215,43 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ P8V_BUILTIN_VEC_VCLZD, P8V_BUILTIN_VCLZD,
RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0, 0 },
+ { P9V_BUILTIN_VEC_VCTZ, P9V_BUILTIN_VCTZB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 },
+ { P9V_BUILTIN_VEC_VCTZ, P9V_BUILTIN_VCTZB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0, 0 },
+ { P9V_BUILTIN_VEC_VCTZ, P9V_BUILTIN_VCTZH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0, 0 },
+ { P9V_BUILTIN_VEC_VCTZ, P9V_BUILTIN_VCTZH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0, 0 },
+ { P9V_BUILTIN_VEC_VCTZ, P9V_BUILTIN_VCTZW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0, 0 },
+ { P9V_BUILTIN_VEC_VCTZ, P9V_BUILTIN_VCTZW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0, 0 },
+ { P9V_BUILTIN_VEC_VCTZ, P9V_BUILTIN_VCTZD,
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0, 0 },
+ { P9V_BUILTIN_VEC_VCTZ, P9V_BUILTIN_VCTZD,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0, 0 },
+
+ { P9V_BUILTIN_VEC_VCTZB, P9V_BUILTIN_VCTZB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 },
+ { P9V_BUILTIN_VEC_VCTZB, P9V_BUILTIN_VCTZB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0, 0 },
+
+ { P9V_BUILTIN_VEC_VCTZH, P9V_BUILTIN_VCTZH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0, 0 },
+ { P9V_BUILTIN_VEC_VCTZH, P9V_BUILTIN_VCTZH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0, 0 },
+
+ { P9V_BUILTIN_VEC_VCTZW, P9V_BUILTIN_VCTZW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0, 0 },
+ { P9V_BUILTIN_VEC_VCTZW, P9V_BUILTIN_VCTZW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0, 0 },
+
+ { P9V_BUILTIN_VEC_VCTZD, P9V_BUILTIN_VCTZD,
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0, 0 },
+ { P9V_BUILTIN_VEC_VCTZD, P9V_BUILTIN_VCTZD,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0, 0 },
+
{ P8V_BUILTIN_VEC_VGBBD, P8V_BUILTIN_VGBBD,
RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 },
{ P8V_BUILTIN_VEC_VGBBD, P8V_BUILTIN_VGBBD,
@@ -4344,6 +4381,42 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
{ P8V_BUILTIN_VEC_VPOPCNTD, P8V_BUILTIN_VPOPCNTD,
RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYB, P9V_BUILTIN_VPRTYBW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYB, P9V_BUILTIN_VPRTYBW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYB, P9V_BUILTIN_VPRTYBD,
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYB, P9V_BUILTIN_VPRTYBD,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYB, P9V_BUILTIN_VPRTYBQ,
+ RS6000_BTI_V1TI, RS6000_BTI_V1TI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYB, P9V_BUILTIN_VPRTYBQ,
+ RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYB, P9V_BUILTIN_VPRTYBQ,
+ RS6000_BTI_INTTI, RS6000_BTI_INTTI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYB, P9V_BUILTIN_VPRTYBQ,
+ RS6000_BTI_UINTTI, RS6000_BTI_UINTTI, 0, 0 },
+
+ { P9V_BUILTIN_VEC_VPRTYBW, P9V_BUILTIN_VPRTYBW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYBW, P9V_BUILTIN_VPRTYBW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0, 0 },
+
+ { P9V_BUILTIN_VEC_VPRTYBD, P9V_BUILTIN_VPRTYBD,
+ RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYBD, P9V_BUILTIN_VPRTYBD,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0, 0 },
+
+ { P9V_BUILTIN_VEC_VPRTYBQ, P9V_BUILTIN_VPRTYBQ,
+ RS6000_BTI_V1TI, RS6000_BTI_V1TI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYBQ, P9V_BUILTIN_VPRTYBQ,
+ RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYBQ, P9V_BUILTIN_VPRTYBQ,
+ RS6000_BTI_INTTI, RS6000_BTI_INTTI, 0, 0 },
+ { P9V_BUILTIN_VEC_VPRTYBQ, P9V_BUILTIN_VPRTYBQ,
+ RS6000_BTI_UINTTI, RS6000_BTI_UINTTI, 0, 0 },
+
{ P8V_BUILTIN_VEC_VPKUDUM, P8V_BUILTIN_VPKUDUM,
RS6000_BTI_V4SI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0 },
{ P8V_BUILTIN_VEC_VPKUDUM, P8V_BUILTIN_VPKUDUM,
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 5e465b3aa50..b24f5d92ab7 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -577,7 +577,9 @@
(V16QI "b")
(V8HI "h")
(V4SI "w")
- (V2DI "d")])
+ (V2DI "d")
+ (V1TI "q")
+ (TI "q")])
;; How many bits in this mode?
(define_mode_attr bits [(QI "8") (HI "16") (SI "32") (DI "64")])
diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md
index 02fb3e3d12f..3983c3b8f08 100644
--- a/gcc/config/rs6000/vector.md
+++ b/gcc/config/rs6000/vector.md
@@ -26,6 +26,13 @@
;; Vector int modes
(define_mode_iterator VEC_I [V16QI V8HI V4SI V2DI])
+;; Vector int modes for parity
+(define_mode_iterator VEC_IP [V8HI
+ V4SI
+ V2DI
+ V1TI
+ (TI "TARGET_VSX_TIMODE")])
+
;; Vector float modes
(define_mode_iterator VEC_F [V4SF V2DF])
@@ -738,12 +745,24 @@
(clz:VEC_I (match_operand:VEC_I 1 "register_operand" "")))]
"TARGET_P8_VECTOR")
+;; Vector count trailing zeros
+(define_expand "ctz<mode>2"
+ [(set (match_operand:VEC_I 0 "register_operand" "")
+ (ctz:VEC_I (match_operand:VEC_I 1 "register_operand" "")))]
+ "TARGET_P9_VECTOR")
+
;; Vector population count
(define_expand "popcount<mode>2"
[(set (match_operand:VEC_I 0 "register_operand" "")
(popcount:VEC_I (match_operand:VEC_I 1 "register_operand" "")))]
"TARGET_P8_VECTOR")
+;; Vector parity
+(define_expand "parity<mode>2"
+ [(set (match_operand:VEC_IP 0 "register_operand" "")
+ (parity:VEC_IP (match_operand:VEC_IP 1 "register_operand" "")))]
+ "TARGET_P9_VECTOR")
+
;; Same size conversions
(define_expand "float<VEC_int><mode>2"
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 02fdc1ea470..d54b83beb4c 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -16452,6 +16452,60 @@ int __builtin_bcdsub_gt (vector __int128_t, vector__int128_t);
int __builtin_bcdsub_ov (vector __int128_t, vector__int128_t);
@end smallexample
+If the ISA 3.00 additions to the vector/scalar (power9-vector)
+instruction set are available:
+
+@smallexample
+vector long long vec_vctz (vector long long);
+vector unsigned long long vec_vctz (vector unsigned long long);
+vector int vec_vctz (vector int);
+vector unsigned int vec_vctz (vector int);
+vector short vec_vctz (vector short);
+vector unsigned short vec_vctz (vector unsigned short);
+vector signed char vec_vctz (vector signed char);
+vector unsigned char vec_vctz (vector unsigned char);
+
+vector signed char vec_vctzb (vector signed char);
+vector unsigned char vec_vctzb (vector unsigned char);
+
+vector long long vec_vctzd (vector long long);
+vector unsigned long long vec_vctzd (vector unsigned long long);
+
+vector short vec_vctzh (vector short);
+vector unsigned short vec_vctzh (vector unsigned short);
+
+vector int vec_vctzw (vector int);
+vector unsigned int vec_vctzw (vector int);
+
+vector int vec_vprtyb (vector int);
+vector unsigned int vec_vprtyb (vector unsigned int);
+vector long long vec_vprtyb (vector long long);
+vector unsigned long long vec_vprtyb (vector unsigned long long);
+
+vector int vec_vprtybw (vector int);
+vector unsigned int vec_vprtybw (vector unsigned int);
+
+vector long long vec_vprtybd (vector long long);
+vector unsigned long long vec_vprtybd (vector unsigned long long);
+@end smallexample
+
+
+If the ISA 3.00 additions to the vector/scalar (power9-vector)
+instruction set are available for 64-bit targets:
+
+@smallexample
+vector long vec_vprtyb (vector long);
+vector unsigned long vec_vprtyb (vector unsigned long);
+vector __int128_t vec_vprtyb (vector __int128_t);
+vector __uint128_t vec_vprtyb (vector __uint128_t);
+
+vector long vec_vprtybd (vector long);
+vector unsigned long vec_vprtybd (vector unsigned long);
+
+vector __int128_t vec_vprtybq (vector __int128_t);
+vector __uint128_t vec_vprtybd (vector __uint128_t);
+@end smallexample
+
If the cryptographic instructions are enabled (@option{-mcrypto} or
@option{-mcpu=power8}), the following builtins are enabled.
diff --git a/gcc/testsuite/gcc.target/powerpc/ctz-3.c b/gcc/testsuite/gcc.target/powerpc/ctz-3.c
new file mode 100644
index 00000000000..468a1f93540
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/ctz-3.c
@@ -0,0 +1,62 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */
+
+#ifndef SIZE
+#define SIZE 1024
+#endif
+
+#ifndef ALIGN
+#define ALIGN 32
+#endif
+
+#define ALIGN_ATTR __attribute__((__aligned__(ALIGN)))
+
+#define DO_BUILTIN(PREFIX, TYPE, CTZ) \
+TYPE PREFIX ## _a[SIZE] ALIGN_ATTR; \
+TYPE PREFIX ## _b[SIZE] ALIGN_ATTR; \
+ \
+void \
+PREFIX ## _ctz (void) \
+{ \
+ unsigned long i; \
+ \
+ for (i = 0; i < SIZE; i++) \
+ PREFIX ## _a[i] = CTZ (PREFIX ## _b[i]); \
+}
+
+#if !defined(DO_LONG_LONG) && !defined(DO_LONG) && !defined(DO_INT) && !defined(DO_SHORT) && !defined(DO_CHAR)
+#define DO_INT 1
+#endif
+
+#if DO_LONG_LONG
+/* At the moment, only int is auto vectorized. */
+DO_BUILTIN (sll, long long, __builtin_ctzll)
+DO_BUILTIN (ull, unsigned long long, __builtin_ctzll)
+#endif
+
+#if defined(_ARCH_PPC64) && DO_LONG
+DO_BUILTIN (sl, long, __builtin_ctzl)
+DO_BUILTIN (ul, unsigned long, __builtin_ctzl)
+#endif
+
+#if DO_INT
+DO_BUILTIN (si, int, __builtin_ctz)
+DO_BUILTIN (ui, unsigned int, __builtin_ctz)
+#endif
+
+#if DO_SHORT
+DO_BUILTIN (ss, short, __builtin_ctz)
+DO_BUILTIN (us, unsigned short, __builtin_ctz)
+#endif
+
+#if DO_CHAR
+DO_BUILTIN (sc, signed char, __builtin_ctz)
+DO_BUILTIN (uc, unsigned char, __builtin_ctz)
+#endif
+
+/* { dg-final { scan-assembler-times "vctzw" 2 } } */
+/* { dg-final { scan-assembler-not "cnttzd" } } */
+/* { dg-final { scan-assembler-not "cnttzw" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ctz-4.c b/gcc/testsuite/gcc.target/powerpc/ctz-4.c
new file mode 100644
index 00000000000..2d04a9b6579
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/ctz-4.c
@@ -0,0 +1,110 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+#include <altivec.h>
+
+vector signed char
+count_trailing_zeros_v16qi_1s (vector signed char a)
+{
+ return vec_vctz (a);
+}
+
+vector signed char
+count_trailing_zeros_v16qi_2s (vector signed char a)
+{
+ return vec_vctzb (a);
+}
+
+vector unsigned char
+count_trailing_zeros_v16qi_1u (vector unsigned char a)
+{
+ return vec_vctz (a);
+}
+
+vector unsigned char
+count_trailing_zeros_v16qi_2u (vector unsigned char a)
+{
+ return vec_vctzb (a);
+}
+
+vector short
+count_trailing_zeros_v8hi_1s (vector short a)
+{
+ return vec_vctz (a);
+}
+
+vector short
+count_trailing_zeros_v8hi_2s (vector short a)
+{
+ return vec_vctzh (a);
+}
+
+vector unsigned short
+count_trailing_zeros_v8hi_1u (vector unsigned short a)
+{
+ return vec_vctz (a);
+}
+
+vector unsigned short
+count_trailing_zeros_v8hi_2u (vector unsigned short a)
+{
+ return vec_vctzh (a);
+}
+
+vector int
+count_trailing_zeros_v4si_1s (vector int a)
+{
+ return vec_vctz (a);
+}
+
+vector int
+count_trailing_zeros_v4si_2s (vector int a)
+{
+ return vec_vctzw (a);
+}
+
+vector unsigned int
+count_trailing_zeros_v4si_1u (vector unsigned int a)
+{
+ return vec_vctz (a);
+}
+
+vector unsigned int
+count_trailing_zeros_v4si_2u (vector unsigned int a)
+{
+ return vec_vctzw (a);
+}
+
+vector long long
+count_trailing_zeros_v2di_1s (vector long long a)
+{
+ return vec_vctz (a);
+}
+
+vector long long
+count_trailing_zeros_v2di_2s (vector long long a)
+{
+ return vec_vctzd (a);
+}
+
+vector unsigned long long
+count_trailing_zeros_v2di_1u (vector unsigned long long a)
+{
+ return vec_vctz (a);
+}
+
+vector unsigned long long
+count_trailing_zeros_v2di_2u (vector unsigned long long a)
+{
+ return vec_vctzd (a);
+}
+
+/* { dg-final { scan-assembler "vctzb" } } */
+/* { dg-final { scan-assembler "vctzd" } } */
+/* { dg-final { scan-assembler "vctzh" } } */
+/* { dg-final { scan-assembler "vctzw" } } */
+/* { dg-final { scan-assembler-not "cnttzd" } } */
+/* { dg-final { scan-assembler-not "cnttzw" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-vparity.c b/gcc/testsuite/gcc.target/powerpc/p9-vparity.c
new file mode 100644
index 00000000000..e4c20870717
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/p9-vparity.c
@@ -0,0 +1,107 @@
+/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2 -mlra -mvsx-timode" } */
+
+#include <altivec.h>
+
+vector int
+parity_v4si_1s (vector int a)
+{
+ return vec_vprtyb (a);
+}
+
+vector int
+parity_v4si_2s (vector int a)
+{
+ return vec_vprtybw (a);
+}
+
+vector unsigned int
+parity_v4si_1u (vector unsigned int a)
+{
+ return vec_vprtyb (a);
+}
+
+vector unsigned int
+parity_v4si_2u (vector unsigned int a)
+{
+ return vec_vprtybw (a);
+}
+
+vector long long
+parity_v2di_1s (vector long long a)
+{
+ return vec_vprtyb (a);
+}
+
+vector long long
+parity_v2di_2s (vector long long a)
+{
+ return vec_vprtybd (a);
+}
+
+vector unsigned long long
+parity_v2di_1u (vector unsigned long long a)
+{
+ return vec_vprtyb (a);
+}
+
+vector unsigned long long
+parity_v2di_2u (vector unsigned long long a)
+{
+ return vec_vprtybd (a);
+}
+
+vector __int128_t
+parity_v1ti_1s (vector __int128_t a)
+{
+ return vec_vprtyb (a);
+}
+
+vector __int128_t
+parity_v1ti_2s (vector __int128_t a)
+{
+ return vec_vprtybq (a);
+}
+
+__int128_t
+parity_ti_3s (__int128_t a)
+{
+ return vec_vprtyb (a);
+}
+
+__int128_t
+parity_ti_4s (__int128_t a)
+{
+ return vec_vprtybq (a);
+}
+
+vector __uint128_t
+parity_v1ti_1u (vector __uint128_t a)
+{
+ return vec_vprtyb (a);
+}
+
+vector __uint128_t
+parity_v1ti_2u (vector __uint128_t a)
+{
+ return vec_vprtybq (a);
+}
+
+__uint128_t
+parity_ti_3u (__uint128_t a)
+{
+ return vec_vprtyb (a);
+}
+
+__uint128_t
+parity_ti_4u (__uint128_t a)
+{
+ return vec_vprtybq (a);
+}
+
+/* { dg-final { scan-assembler "vprtybd" } } */
+/* { dg-final { scan-assembler "vprtybq" } } */
+/* { dg-final { scan-assembler "vprtybw" } } */