summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKelvin Nilsen <kelvin@gcc.gnu.org>2020-05-11 16:25:03 -0500
committerBill Schmidt <wschmidt@linux.ibm.com>2020-05-11 16:25:03 -0500
commit840ac85ced0695fefecee433327e4298b4adb20a (patch)
tree2ead3d269a344ed5865c2b409fdf5830c530eab1
parent2202299c2aa69385ca5e7574914dabc84fb6a40a (diff)
rs6000: Add xxeval and vec_ternarylogic
Add the xxeval insn and access it via the vec_ternarylogic built-in function. As part of this, add support to the built-in function infrastructure for functions that take four arguments. [gcc] 2020-05-11 Kelvin Nilsen <wschmidt@linux.ibm.com> * config/rs6000/altivec.h (vec_ternarylogic): New #define. * config/rs6000/altivec.md (UNSPEC_XXEVAL): New constant. (xxeval): New insn. * config/rs6000/predicates.md (u8bit_cint_operand): New predicate. * config/rs6000/rs6000-builtin.def: Add handling of new macro RS6000_BUILTIN_4. (BU_FUTURE_V_4): New macro. Use it. (BU_FUTURE_OVERLOAD_4): Likewise. * config/rs6000/rs6000-c.c (altivec_build_resolved_builtin): Add handling for quaternary built-in functions. (altivec_resolve_overloaded_builtin): Add special-case handling for __builtin_vec_xxeval. * config/rs6000/rs6000-call.c: Add handling of new macro RS6000_BUILTIN_4 in initialization of rs6000_builtin_info, bdesc0_arg, bdesc1_arg, bdesc2_arg, bdesc_3arg, bdesc_altivec_preds, bdesc_abs, and bdesc_htm arrays. (altivec_overloaded_builtins): Add definitions for FUTURE_BUILTIN_VEC_XXEVAL. (bdesc_4arg): New array. (htm_expand_builtin): Add handling for quaternary built-in functions. (rs6000_expand_quaternop_builtin): New function. (rs6000_expand_builtin): Add handling for quaternary built-in functions. (rs6000_init_builtins): Initialize builtin_mode_to_type entries for unsigned QImode and unsigned HImode. (builtin_quaternary_function_type): New function. (rs6000_common_init_builtins): Add handling of quaternary operations. * config/rs6000/rs6000.h (RS6000_BTC_QUATERNARY): New defined constant. (RS6000_BTC_PREDICATE): Change value of constant. (RS6000_BTC_ABS): Likewise. (rs6000_builtins): Add support for new macro RS6000_BUILTIN_4. * doc/extend.texi (PowerPC AltiVec Built-In Functions Available for a Future Architecture): Add description of vec_ternarylogic built-in function. [gcc/testsuite] 2020-05-11 Kelvin Nilsen <wschmidt@linux.ibm.com> * gcc.target/powerpc/vec-ternarylogic-0.c: New. * gcc.target/powerpc/vec-ternarylogic-1.c: New. * gcc.target/powerpc/vec-ternarylogic-10.c: New. * gcc.target/powerpc/vec-ternarylogic-2.c: New. * gcc.target/powerpc/vec-ternarylogic-3.c: New. * gcc.target/powerpc/vec-ternarylogic-4.c: New. * gcc.target/powerpc/vec-ternarylogic-5.c: New. * gcc.target/powerpc/vec-ternarylogic-6.c: New. * gcc.target/powerpc/vec-ternarylogic-7.c: New. * gcc.target/powerpc/vec-ternarylogic-8.c: New. * gcc.target/powerpc/vec-ternarylogic-9.c: New.
-rw-r--r--gcc/ChangeLog40
-rw-r--r--gcc/config/rs6000/altivec.h1
-rw-r--r--gcc/config/rs6000/altivec.md11
-rw-r--r--gcc/config/rs6000/predicates.md5
-rw-r--r--gcc/config/rs6000/rs6000-builtin.def23
-rw-r--r--gcc/config/rs6000/rs6000-c.c47
-rw-r--r--gcc/config/rs6000/rs6000-call.c251
-rw-r--r--gcc/config/rs6000/rs6000.h12
-rw-r--r--gcc/doc/extend.texi21
-rw-r--r--gcc/testsuite/ChangeLog14
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-0.c120
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-1.c119
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-10.c129
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-2.c105
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-3.c106
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-4.c104
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-5.c103
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-6.c104
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-7.c103
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-8.c128
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-9.c129
21 files changed, 1670 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 02d74523769..f94dd522892 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,43 @@
+2020-05-11 Kelvin Nilsen <wschmidt@linux.ibm.com>
+
+ * config/rs6000/altivec.h (vec_ternarylogic): New #define.
+ * config/rs6000/altivec.md (UNSPEC_XXEVAL): New constant.
+ (xxeval): New insn.
+ * config/rs6000/predicates.md (u8bit_cint_operand): New predicate.
+ * config/rs6000/rs6000-builtin.def: Add handling of new macro
+ RS6000_BUILTIN_4.
+ (BU_FUTURE_V_4): New macro. Use it.
+ (BU_FUTURE_OVERLOAD_4): Likewise.
+ * config/rs6000/rs6000-c.c (altivec_build_resolved_builtin): Add
+ handling for quaternary built-in functions.
+ (altivec_resolve_overloaded_builtin): Add special-case handling
+ for __builtin_vec_xxeval.
+ * config/rs6000/rs6000-call.c: Add handling of new macro
+ RS6000_BUILTIN_4 in initialization of rs6000_builtin_info,
+ bdesc0_arg, bdesc1_arg, bdesc2_arg, bdesc_3arg,
+ bdesc_altivec_preds, bdesc_abs, and bdesc_htm arrays.
+ (altivec_overloaded_builtins): Add definitions for
+ FUTURE_BUILTIN_VEC_XXEVAL.
+ (bdesc_4arg): New array.
+ (htm_expand_builtin): Add handling for quaternary built-in
+ functions.
+ (rs6000_expand_quaternop_builtin): New function.
+ (rs6000_expand_builtin): Add handling for quaternary built-in
+ functions.
+ (rs6000_init_builtins): Initialize builtin_mode_to_type entries
+ for unsigned QImode and unsigned HImode.
+ (builtin_quaternary_function_type): New function.
+ (rs6000_common_init_builtins): Add handling of quaternary
+ operations.
+ * config/rs6000/rs6000.h (RS6000_BTC_QUATERNARY): New defined
+ constant.
+ (RS6000_BTC_PREDICATE): Change value of constant.
+ (RS6000_BTC_ABS): Likewise.
+ (rs6000_builtins): Add support for new macro RS6000_BUILTIN_4.
+ * doc/extend.texi (PowerPC AltiVec Built-In Functions Available
+ for a Future Architecture): Add description of vec_ternarylogic
+ built-in function.
+
2020-05-11 Kelvin Nilsen <kelvin@gcc.gnu.org>
* config/rs6000/rs6000-builtin.def (__builtin_pdepd): New built-in
diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index 74319f13fa6..addf7d0db52 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -699,6 +699,7 @@ __altivec_scalar_pred(vec_any_nle,
#define vec_gnb(a, b) __builtin_vec_gnb (a, b)
#define vec_clrl(a, b) __builtin_vec_clrl (a, b)
#define vec_clrr(a, b) __builtin_vec_clrr (a, b)
+#define vec_ternarylogic(a, b, c, d) __builtin_vec_xxeval (a, b, c, d)
#endif
#endif /* _ALTIVEC_H */
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 11d2dfe9426..7382d7c4b44 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -168,6 +168,7 @@
UNSPEC_VPEXTD
UNSPEC_VCLRLB
UNSPEC_VCLRRB
+ UNSPEC_XXEVAL
])
(define_c_enum "unspecv"
@@ -3271,6 +3272,16 @@
[(set_attr "type" "vecperm")
(set_attr "isa" "*,p9v")])
+(define_insn "xxeval"
+ [(set (match_operand:V2DI 0 "register_operand" "=wa")
+ (unspec:V2DI [(match_operand:V2DI 1 "altivec_register_operand" "wa")
+ (match_operand:V2DI 2 "altivec_register_operand" "wa")
+ (match_operand:V2DI 3 "altivec_register_operand" "wa")
+ (match_operand:QI 4 "u8bit_cint_operand" "n")]
+ UNSPEC_XXEVAL))]
+ "TARGET_FUTURE"
+ "xxeval %0,%1,%2,%3,%4"
+ [(set_attr "type" "vecsimple")])
(define_expand "vec_unpacku_hi_v16qi"
[(set (match_operand:V8HI 0 "register_operand" "=v")
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index bf04e4d431f..c3f460face2 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -234,6 +234,11 @@
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 0, 127)")))
+;; Return 1 if op is a unsigned 8-bit constant integer.
+(define_predicate "u8bit_cint_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 0, 255)")))
+
;; Return 1 if op is a signed 8-bit constant integer.
;; Integer multiplication complete more quickly
(define_predicate "s8bit_cint_operand"
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 4b06323a07f..7ff8db5dccc 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -28,6 +28,7 @@
RS6000_BUILTIN_1 -- 1 arg builtins
RS6000_BUILTIN_2 -- 2 arg builtins
RS6000_BUILTIN_3 -- 3 arg builtins
+ RS6000_BUILTIN_4 -- 4 arg builtins
RS6000_BUILTIN_A -- ABS builtins
RS6000_BUILTIN_D -- DST builtins
RS6000_BUILTIN_H -- HTM builtins
@@ -57,6 +58,10 @@
#error "RS6000_BUILTIN_3 is not defined."
#endif
+#ifndef RS6000_BUILTIN_4
+ #error "RS6000_BUILTIN_4 is not defined."
+#endif
+
#ifndef RS6000_BUILTIN_A
#error "RS6000_BUILTIN_A is not defined."
#endif
@@ -969,6 +974,14 @@
| RS6000_BTC_TERNARY), \
CODE_FOR_ ## ICODE) /* ICODE */
+#define BU_FUTURE_V_4(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_4 (FUTURE_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_altivec_" NAME, /* NAME */ \
+ RS6000_BTM_FUTURE, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_QUATERNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
#define BU_FUTURE_OVERLOAD_1(ENUM, NAME) \
RS6000_BUILTIN_1 (FUTURE_BUILTIN_VEC_ ## ENUM, /* ENUM */ \
"__builtin_vec_" NAME, /* NAME */ \
@@ -993,6 +1006,14 @@
| RS6000_BTC_TERNARY), \
CODE_FOR_nothing) /* ICODE */
+#define BU_FUTURE_OVERLOAD_4(ENUM, NAME) \
+ RS6000_BUILTIN_4 (FUTURE_BUILTIN_VEC_ ## ENUM, /* ENUM */ \
+ "__builtin_vec_" NAME, /* NAME */ \
+ RS6000_BTM_FUTURE, /* MASK */ \
+ (RS6000_BTC_OVERLOADED /* ATTR */ \
+ | RS6000_BTC_QUATERNARY), \
+ CODE_FOR_nothing) /* ICODE */
+
/* Miscellaneous (non-vector) builtins for instructions which may be
added at some point in the future. */
@@ -2589,11 +2610,13 @@ BU_FUTURE_V_2 (VCTZDM, "vctzdm", CONST, vctzdm)
BU_FUTURE_V_2 (VPDEPD, "vpdepd", CONST, vpdepd)
BU_FUTURE_V_2 (VPEXTD, "vpextd", CONST, vpextd)
BU_FUTURE_V_2 (VGNB, "vgnb", CONST, vgnb)
+BU_FUTURE_V_4 (XXEVAL, "xxeval", CONST, xxeval)
/* Future architecture overloaded vector built-ins. */
BU_FUTURE_OVERLOAD_2 (CLRL, "clrl")
BU_FUTURE_OVERLOAD_2 (CLRR, "clrr")
BU_FUTURE_OVERLOAD_2 (GNB, "gnb")
+BU_FUTURE_OVERLOAD_4 (XXEVAL, "xxeval")
/* 1 argument crypto functions. */
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index ee2db96f2bd..cacaea00bd4 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -846,7 +846,7 @@ altivec_build_resolved_builtin (tree *args, int n,
tree impl_fndecl = rs6000_builtin_decls[desc->overloaded_code];
tree ret_type = rs6000_builtin_type (desc->ret_type);
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (impl_fndecl));
- tree arg_type[3];
+ tree arg_type[4];
tree call;
int i;
@@ -895,6 +895,13 @@ altivec_build_resolved_builtin (tree *args, int n,
fully_fold_convert (arg_type[1], args[1]),
fully_fold_convert (arg_type[2], args[2]));
break;
+ case 4:
+ call = build_call_expr (impl_fndecl, 4,
+ fully_fold_convert (arg_type[0], args[0]),
+ fully_fold_convert (arg_type[1], args[1]),
+ fully_fold_convert (arg_type[2], args[2]),
+ fully_fold_convert (arg_type[3], args[3]));
+ break;
default:
gcc_unreachable ();
}
@@ -913,7 +920,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
enum rs6000_builtins fcode
= (enum rs6000_builtins) DECL_MD_FUNCTION_CODE (fndecl);
tree fnargs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- tree types[3], args[3];
+ tree types[4], args[4];
const struct altivec_builtin_types *desc;
unsigned int n;
@@ -1606,7 +1613,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
if (arg == error_mark_node)
return error_mark_node;
- if (n >= 3)
+ if (n >= 4)
abort ();
arg = default_conversion (arg);
@@ -1789,6 +1796,40 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
unsupported_builtin = true;
}
}
+ else if (fcode == FUTURE_BUILTIN_VEC_XXEVAL)
+ {
+ /* Need to special case __builtin_vec_xxeval because this takes
+ 4 arguments, and the existing infrastructure handles no
+ more than three. */
+ if (nargs != 4)
+ {
+ error ("builtin %qs requires 4 arguments",
+ "__builtin_vec_xxeval");
+ return error_mark_node;
+ }
+ for ( ; desc->code == fcode; desc++)
+ {
+ if (rs6000_builtin_type_compatible (types[0], desc->op1)
+ && rs6000_builtin_type_compatible (types[1], desc->op2)
+ && rs6000_builtin_type_compatible (types[2], desc->op3)
+ && rs6000_builtin_type_compatible (types[3],
+ RS6000_BTI_UINTQI))
+ {
+ if (rs6000_builtin_decls[desc->overloaded_code] == NULL_TREE)
+ unsupported_builtin = true;
+ else
+ {
+ result = altivec_build_resolved_builtin (args, n, desc);
+ if (rs6000_builtin_is_supported_p (desc->overloaded_code))
+ return result;
+ /* Allow loop to continue in case a different
+ definition is supported. */
+ overloaded_code = desc->overloaded_code;
+ unsupported_builtin = true;
+ }
+ }
+ }
+ }
else
{
/* For arguments after the last, we have RS6000_BTI_NOT_OPAQUE in
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 9da5b48463e..7c43db18d65 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -237,6 +237,7 @@ builtin_hasher::equal (builtin_hash_struct *p1, builtin_hash_struct *p2)
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
@@ -255,6 +256,9 @@ builtin_hasher::equal (builtin_hash_struct *p1, builtin_hash_struct *p2)
#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) \
{ NAME, ICODE, MASK, ATTR },
+#define RS6000_BUILTIN_4(ENUM, NAME, MASK, ATTR, ICODE) \
+ { NAME, ICODE, MASK, ATTR },
+
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) \
{ NAME, ICODE, MASK, ATTR },
@@ -286,6 +290,7 @@ static const struct rs6000_builtin_info_type rs6000_builtin_info[] =
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
@@ -5527,6 +5532,25 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_unsigned_V2DI, RS6000_BTI_UINTQI, 0 },
{ FUTURE_BUILTIN_VEC_GNB, FUTURE_BUILTIN_VGNB, RS6000_BTI_unsigned_long_long,
RS6000_BTI_unsigned_V1TI, RS6000_BTI_UINTQI, 0 },
+
+ /* The overloaded XXEVAL definitions are handled specially because the
+ fourth unsigned char operand is not encoded in this table. */
+ { FUTURE_BUILTIN_VEC_XXEVAL, FUTURE_BUILTIN_XXEVAL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI },
+ { FUTURE_BUILTIN_VEC_XXEVAL, FUTURE_BUILTIN_XXEVAL,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI },
+ { FUTURE_BUILTIN_VEC_XXEVAL, FUTURE_BUILTIN_XXEVAL,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI },
+ { FUTURE_BUILTIN_VEC_XXEVAL, FUTURE_BUILTIN_XXEVAL,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI,
+ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI },
+ { FUTURE_BUILTIN_VEC_XXEVAL, FUTURE_BUILTIN_XXEVAL,
+ RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI,
+ RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI },
+
{ RS6000_BUILTIN_NONE, RS6000_BUILTIN_NONE, 0, 0, 0, 0 }
};
@@ -8275,6 +8299,7 @@ def_builtin (const char *name, tree type, enum rs6000_builtins code)
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
@@ -8287,6 +8312,7 @@ def_builtin (const char *name, tree type, enum rs6000_builtins code)
#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) \
{ MASK, ICODE, NAME, ENUM },
+#define RS6000_BUILTIN_4(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
@@ -8298,12 +8324,44 @@ static const struct builtin_description bdesc_3arg[] =
#include "rs6000-builtin.def"
};
+/* Simple quaternary operations: VECd = foo (VECa, VECb, VECc, VECd). */
+
+#undef RS6000_BUILTIN_0
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_H
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_X
+
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_4(ENUM, NAME, MASK, ATTR, ICODE) \
+ { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
+static const struct builtin_description bdesc_4arg[] =
+{
+#include "rs6000-builtin.def"
+};
+
/* DST operations: void foo (void *, const int, const char). */
#undef RS6000_BUILTIN_0
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
@@ -8314,6 +8372,7 @@ static const struct builtin_description bdesc_3arg[] =
#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_4(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) \
{ MASK, ICODE, NAME, ENUM },
@@ -8333,6 +8392,7 @@ static const struct builtin_description bdesc_dst[] =
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
@@ -8345,6 +8405,7 @@ static const struct builtin_description bdesc_dst[] =
{ MASK, ICODE, NAME, ENUM },
#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_4(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
@@ -8360,6 +8421,7 @@ static const struct builtin_description bdesc_2arg[] =
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
@@ -8370,6 +8432,7 @@ static const struct builtin_description bdesc_2arg[] =
#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_4(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
@@ -8391,6 +8454,7 @@ static const struct builtin_description bdesc_altivec_preds[] =
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
@@ -8401,6 +8465,7 @@ static const struct builtin_description bdesc_altivec_preds[] =
#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_4(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) \
{ MASK, ICODE, NAME, ENUM },
@@ -8421,6 +8486,7 @@ static const struct builtin_description bdesc_abs[] =
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
@@ -8433,6 +8499,7 @@ static const struct builtin_description bdesc_abs[] =
#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_4(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
@@ -8450,6 +8517,7 @@ static const struct builtin_description bdesc_1arg[] =
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
@@ -8462,6 +8530,7 @@ static const struct builtin_description bdesc_1arg[] =
#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_4(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
@@ -8478,6 +8547,7 @@ static const struct builtin_description bdesc_0arg[] =
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
@@ -8488,6 +8558,7 @@ static const struct builtin_description bdesc_0arg[] =
#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_4(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) \
@@ -8505,6 +8576,7 @@ static const struct builtin_description bdesc_htm[] =
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
@@ -9404,6 +9476,8 @@ htm_expand_builtin (tree exp, rtx target, bool * expandedp)
expected_nopnds = 2;
else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_TERNARY)
expected_nopnds = 3;
+ else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_QUATERNARY)
+ expected_nopnds = 4;
if (!(attr & RS6000_BTC_VOID))
expected_nopnds += 1;
if (uses_spr)
@@ -9581,6 +9655,76 @@ cpu_expand_builtin (enum rs6000_builtins fcode, tree exp ATTRIBUTE_UNUSED,
}
static rtx
+rs6000_expand_quaternop_builtin (enum insn_code icode, tree exp, rtx target)
+{
+ rtx pat;
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
+ tree arg1 = CALL_EXPR_ARG (exp, 1);
+ tree arg2 = CALL_EXPR_ARG (exp, 2);
+ tree arg3 = CALL_EXPR_ARG (exp, 3);
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
+ rtx op2 = expand_normal (arg2);
+ rtx op3 = expand_normal (arg3);
+ machine_mode tmode = insn_data[icode].operand[0].mode;
+ machine_mode mode0 = insn_data[icode].operand[1].mode;
+ machine_mode mode1 = insn_data[icode].operand[2].mode;
+ machine_mode mode2 = insn_data[icode].operand[3].mode;
+ machine_mode mode3 = insn_data[icode].operand[4].mode;
+
+ if (icode == CODE_FOR_nothing)
+ /* Builtin not supported on this processor. */
+ return 0;
+
+ /* If we got invalid arguments bail out before generating bad rtl. */
+ if (arg0 == error_mark_node
+ || arg1 == error_mark_node
+ || arg2 == error_mark_node
+ || arg3 == error_mark_node)
+ return const0_rtx;
+
+ /* Check and prepare argument depending on the instruction code.
+
+ Note that a switch statement instead of the sequence of tests
+ would be incorrect as many of the CODE_FOR values could be
+ CODE_FOR_nothing and that would yield multiple alternatives
+ with identical values. We'd never reach here at runtime in
+ this case. */
+ if (icode == CODE_FOR_xxeval)
+ {
+ /* Only allow 8-bit unsigned literals. */
+ STRIP_NOPS (arg3);
+ if (TREE_CODE (arg3) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg3) & ~0xff)
+ {
+ error ("argument 4 must be an 8-bit unsigned literal");
+ return CONST0_RTX (tmode);
+ }
+ }
+
+ if (target == 0
+ || GET_MODE (target) != tmode
+ || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+ target = gen_reg_rtx (tmode);
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+ if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
+ if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
+ op2 = copy_to_mode_reg (mode2, op2);
+ if (! (*insn_data[icode].operand[4].predicate) (op3, mode3))
+ op3 = copy_to_mode_reg (mode3, op3);
+
+ pat = GEN_FCN (icode) (target, op0, op1, op2, op3);
+ if (! pat)
+ return 0;
+ emit_insn (pat);
+
+ return target;
+}
+
+static rtx
rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
{
rtx pat;
@@ -11613,6 +11757,7 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
case RS6000_BTC_UNARY: name3 = "unary"; break;
case RS6000_BTC_BINARY: name3 = "binary"; break;
case RS6000_BTC_TERNARY: name3 = "ternary"; break;
+ case RS6000_BTC_QUATERNARY:name3 = "quaternary";break;
case RS6000_BTC_PREDICATE: name3 = "predicate"; break;
case RS6000_BTC_ABS: name3 = "abs"; break;
case RS6000_BTC_DST: name3 = "dst"; break;
@@ -11795,6 +11940,7 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
gcc_assert (attr == RS6000_BTC_UNARY
|| attr == RS6000_BTC_BINARY
|| attr == RS6000_BTC_TERNARY
+ || attr == RS6000_BTC_QUATERNARY
|| attr == RS6000_BTC_SPECIAL);
/* Handle simple unary operations. */
@@ -11815,6 +11961,12 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
if (d->code == fcode)
return rs6000_expand_ternop_builtin (icode, exp, target);
+ /* Handle simple quaternary operations. */
+ d = bdesc_4arg;
+ for (i = 0; i < ARRAY_SIZE (bdesc_4arg); i++, d++)
+ if (d->code == fcode)
+ return rs6000_expand_quaternop_builtin (icode, exp, target);
+
/* Handle simple no-argument operations. */
d = bdesc_0arg;
for (i = 0; i < ARRAY_SIZE (bdesc_0arg); i++, d++)
@@ -11969,7 +12121,9 @@ rs6000_init_builtins (void)
/* Initialize the modes for builtin_function_type, mapping a machine mode to
tree type node. */
builtin_mode_to_type[QImode][0] = integer_type_node;
+ builtin_mode_to_type[QImode][1] = unsigned_intSI_type_node;
builtin_mode_to_type[HImode][0] = integer_type_node;
+ builtin_mode_to_type[HImode][1] = unsigned_intSI_type_node;
builtin_mode_to_type[SImode][0] = intSI_type_node;
builtin_mode_to_type[SImode][1] = unsigned_intSI_type_node;
builtin_mode_to_type[DImode][0] = intDI_type_node;
@@ -12850,6 +13004,46 @@ htm_init_builtins (void)
}
}
+/* Map types for builtin functions with an explicit return type and
+ exactly 4 arguments. Functions with fewer than 3 arguments use
+ builtin_function_type. The number of quaternary built-in
+ functions is very small. Handle each case specially. */
+static tree
+builtin_quaternary_function_type (machine_mode mode_ret,
+ machine_mode mode_arg0,
+ machine_mode mode_arg1,
+ machine_mode mode_arg2,
+ machine_mode mode_arg3,
+ enum rs6000_builtins builtin)
+{
+ tree function_type = NULL;
+
+ static tree v2udi_type = builtin_mode_to_type[V2DImode][1];
+ static tree uchar_type = builtin_mode_to_type[QImode][1];
+
+ static tree xxeval_type =
+ build_function_type_list (v2udi_type, v2udi_type, v2udi_type,
+ v2udi_type, uchar_type, NULL_TREE);
+
+ switch (builtin) {
+
+ case FUTURE_BUILTIN_XXEVAL:
+ gcc_assert ((mode_ret == V2DImode)
+ && (mode_arg0 == V2DImode)
+ && (mode_arg1 == V2DImode)
+ && (mode_arg2 == V2DImode)
+ && (mode_arg3 == QImode));
+ function_type = xxeval_type;
+ break;
+
+ default:
+ /* A case for each quaternary built-in must be provided above. */
+ gcc_unreachable ();
+ }
+
+ return function_type;
+}
+
/* Map types for builtin functions with an explicit return type and up to 3
arguments. Functions with fewer than 3 arguments use VOIDmode as the type
of the argument. */
@@ -13145,6 +13339,63 @@ rs6000_common_init_builtins (void)
if (TARGET_EXTRA_BUILTINS)
builtin_mask |= RS6000_BTM_COMMON;
+ /* Add the quaternary operators. */
+ d = bdesc_4arg;
+ for (i = 0; i < ARRAY_SIZE (bdesc_4arg); i++, d++)
+ {
+ tree type;
+ HOST_WIDE_INT mask = d->mask;
+
+ if ((mask & builtin_mask) != mask)
+ {
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "rs6000_builtin, skip quaternary %s\n", d->name);
+ continue;
+ }
+
+ if (rs6000_overloaded_builtin_p (d->code))
+ {
+ type = opaque_ftype_opaque_opaque_opaque;
+ if (!type)
+ type = opaque_ftype_opaque_opaque_opaque
+ = build_function_type_list (opaque_V4SI_type_node,
+ opaque_V4SI_type_node,
+ opaque_V4SI_type_node,
+ opaque_V4SI_type_node,
+ opaque_V4SI_type_node,
+ NULL_TREE);
+ }
+ else
+ {
+ enum insn_code icode = d->icode;
+ if (d->name == 0)
+ {
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "rs6000_builtin, bdesc_4arg[%ld] no name\n",
+ (long) i);
+ continue;
+ }
+
+ if (icode == CODE_FOR_nothing)
+ {
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr,
+ "rs6000_builtin, skip quaternary %s (no code)\n",
+ d->name);
+ continue;
+ }
+
+ type =
+ builtin_quaternary_function_type (insn_data[icode].operand[0].mode,
+ insn_data[icode].operand[1].mode,
+ insn_data[icode].operand[2].mode,
+ insn_data[icode].operand[3].mode,
+ insn_data[icode].operand[4].mode,
+ d->code);
+ }
+ def_builtin (d->name, type, d->code);
+ }
+
/* Add the ternary operators. */
d = bdesc_3arg;
for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 5603af994fa..1209a33173e 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -2254,9 +2254,14 @@ extern int frame_pointer_needed;
#define RS6000_BTC_UNARY 0x00000001 /* normal unary function. */
#define RS6000_BTC_BINARY 0x00000002 /* normal binary function. */
#define RS6000_BTC_TERNARY 0x00000003 /* normal ternary function. */
-#define RS6000_BTC_PREDICATE 0x00000004 /* predicate function. */
-#define RS6000_BTC_ABS 0x00000005 /* Altivec/VSX ABS function. */
+#define RS6000_BTC_QUATERNARY 0x00000004 /* normal quaternary
+ function. */
+
+#define RS6000_BTC_PREDICATE 0x00000005 /* predicate function. */
+#define RS6000_BTC_ABS 0x00000006 /* Altivec/VSX ABS
+ function. */
#define RS6000_BTC_DST 0x00000007 /* Altivec DST function. */
+
#define RS6000_BTC_TYPE_MASK 0x0000000f /* Mask to isolate types */
#define RS6000_BTC_MISC 0x00000000 /* No special attributes. */
@@ -2334,6 +2339,7 @@ extern int frame_pointer_needed;
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
@@ -2344,6 +2350,7 @@ extern int frame_pointer_needed;
#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
+#define RS6000_BUILTIN_4(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
@@ -2361,6 +2368,7 @@ enum rs6000_builtins
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_4
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_H
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 9602a310cbb..c66a9ac7c3d 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -22055,6 +22055,27 @@ else
@end smallexample
@end deftypefn
+@smallexample
+@exdent vector unsigned char
+@exdent vec_ternarylogic (vector unsigned char, vector unsigned char,
+ vector unsigned char, const unsigned char)
+@exdent vector unsigned short
+@exdent vec_ternarylogic (vector unsigned short, vector unsigned short,
+ vector unsigned short, const unsigned char)
+@exdent vector unsigned int
+@exdent vec_ternarylogic (vector unsigned int, vector unsigned int,
+ vector unsigned int, const unsigned char)
+@exdent vector unsigned long long int
+@exdent vec_ternarylogic (vector unsigned long long int, vector unsigned long long int,
+ vector unsigned long long int, const unsigned char)
+@exdent vector unsigned __int128
+@exdent vec_ternarylogic (vector unsigned __int128, vector unsigned __int128,
+ vector unsigned __int128, const unsigned char)
+@end smallexample
+Perform a 128-bit vector evaluate operation, as if implemented by the
+Future @code{xxeval} instruction. The fourth argument must be a literal
+integer value between 0 and 255 inclusive.
+@findex vec_ternarylogic
The following built-in functions are made available by @option{-mmmx}.
All of them generate the machine instruction that is part of the name.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 74e83323e6e..0c54c522b7a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,17 @@
+2020-05-11 Kelvin Nilsen <wschmidt@linux.ibm.com>
+
+ * gcc.target/powerpc/vec-ternarylogic-0.c: New.
+ * gcc.target/powerpc/vec-ternarylogic-1.c: New.
+ * gcc.target/powerpc/vec-ternarylogic-10.c: New.
+ * gcc.target/powerpc/vec-ternarylogic-2.c: New.
+ * gcc.target/powerpc/vec-ternarylogic-3.c: New.
+ * gcc.target/powerpc/vec-ternarylogic-4.c: New.
+ * gcc.target/powerpc/vec-ternarylogic-5.c: New.
+ * gcc.target/powerpc/vec-ternarylogic-6.c: New.
+ * gcc.target/powerpc/vec-ternarylogic-7.c: New.
+ * gcc.target/powerpc/vec-ternarylogic-8.c: New.
+ * gcc.target/powerpc/vec-ternarylogic-9.c: New.
+
2020-05-11 Kelvin Nilsen <kelvin@gcc.gnu.org>
* gcc.target/powerpc/pdep-0.c: New.
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-0.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-0.c
new file mode 100644
index 00000000000..bc1d05c008d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-0.c
@@ -0,0 +1,120 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define NumSamples 4
+
+void
+doTests00000001 (vector unsigned char a_sources [],
+ vector unsigned char b_sources [],
+ vector unsigned char c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned char a = a_sources [i];
+ vector unsigned char b = b_sources [j];
+ vector unsigned char c = c_sources [k];
+ vector unsigned char result = vec_ternarylogic (a, b, c, 0x01);
+ vector unsigned char intended = (a & b & c);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void
+doTests11100101 (vector unsigned char a_sources [],
+ vector unsigned char b_sources [],
+ vector unsigned char c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned char a = a_sources [i];
+ vector unsigned char b = b_sources [j];
+ vector unsigned char c = c_sources [k];
+ vector unsigned char result = vec_ternarylogic (a, b, c, 0xe5);
+ vector unsigned char intended =
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ // Supposed to be a ? c: nand (b,c)
+ for (int l = 0; l < 16; l++)
+ {
+ for (int m = 0; m < 8; m++)
+ {
+ unsigned char bit_selector = (0x01 << m);
+ if (a[l] & bit_selector)
+ intended [l] |= c [l] & bit_selector;
+ else if ((b [l] & c [l] & bit_selector) == 0)
+ intended [l] |= bit_selector;
+ }
+ }
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void
+doTests11110011 (vector unsigned char a_sources [],
+ vector unsigned char b_sources [],
+ vector unsigned char c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned char a = a_sources [i];
+ vector unsigned char b = b_sources [j];
+ vector unsigned char c = c_sources [k];
+ vector unsigned char result = vec_ternarylogic (a, b, c, 0xfb);
+ vector unsigned char intended = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ for (int i = 0; i < 16; i++)
+ intended [i] = b [i] | ~(a [i] & c [i]);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+int main (int argc, char *argv [])
+{
+ vector unsigned char a_sources [NumSamples] = {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 },
+ { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xcc, 0xcc, 0xcc, 0xcc, 0x55, 0x55, 0x55, 0x55,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+ 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69 },
+ };
+ vector unsigned char b_sources [NumSamples] = {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 },
+ { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xcc, 0xcc, 0xcc, 0xcc, 0x55, 0x55, 0x55, 0x55,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+ 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69 },
+ };
+ vector unsigned char c_sources [NumSamples] = {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 },
+ { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xcc, 0xcc, 0xcc, 0xcc, 0x55, 0x55, 0x55, 0x55,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+ 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69 },
+ };
+
+ doTests00000001 (a_sources, b_sources, c_sources);
+ doTests11100101 (a_sources, b_sources, c_sources);
+ doTests11110011 (a_sources, b_sources, c_sources);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler {\mxxeval\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-1.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-1.c
new file mode 100644
index 00000000000..8beb80fe60a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-1.c
@@ -0,0 +1,119 @@
+/* { dg-do run} */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define NumSamples 4
+
+void
+doTests00000001 (vector unsigned char a_sources [],
+ vector unsigned char b_sources [],
+ vector unsigned char c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned char a = a_sources [i];
+ vector unsigned char b = b_sources [j];
+ vector unsigned char c = c_sources [k];
+ vector unsigned char result = vec_ternarylogic (a, b, c, 0x01);
+ vector unsigned char intended = (a & b & c);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void
+doTests11100101 (vector unsigned char a_sources [],
+ vector unsigned char b_sources [],
+ vector unsigned char c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned char a = a_sources [i];
+ vector unsigned char b = b_sources [j];
+ vector unsigned char c = c_sources [k];
+ vector unsigned char result = vec_ternarylogic (a, b, c, 0xe5);
+ vector unsigned char intended =
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ // Supposed to be a ? c: nand (b,c)
+ for (int l = 0; l < 16; l++)
+ {
+ for (int m = 0; m < 8; m++)
+ {
+ unsigned char bit_selector = (0x01 << m);
+ if (a[l] & bit_selector)
+ intended [l] |= c [l] & bit_selector;
+ else if ((b [l] & c [l] & bit_selector) == 0)
+ intended [l] |= bit_selector;
+ }
+ }
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void
+doTests11110011 (vector unsigned char a_sources [],
+ vector unsigned char b_sources [],
+ vector unsigned char c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned char a = a_sources [i];
+ vector unsigned char b = b_sources [j];
+ vector unsigned char c = c_sources [k];
+ vector unsigned char result = vec_ternarylogic (a, b, c, 0xfb);
+ vector unsigned char intended = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ for (int i = 0; i < 16; i++)
+ intended [i] = b [i] | ~(a [i] & c [i]);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+int main (int argc, char *argv [])
+{
+ vector unsigned char a_sources [NumSamples] = {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 },
+ { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xcc, 0xcc, 0xcc, 0xcc, 0x55, 0x55, 0x55, 0x55,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+ 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69 },
+ };
+ vector unsigned char b_sources [NumSamples] = {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 },
+ { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xcc, 0xcc, 0xcc, 0xcc, 0x55, 0x55, 0x55, 0x55,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+ 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69 },
+ };
+ vector unsigned char c_sources [NumSamples] = {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 },
+ { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xcc, 0xcc, 0xcc, 0xcc, 0x55, 0x55, 0x55, 0x55,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+ 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69 },
+ };
+
+ doTests00000001 (a_sources, b_sources, c_sources);
+ doTests11100101 (a_sources, b_sources, c_sources);
+ doTests11110011 (a_sources, b_sources, c_sources);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-10.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-10.c
new file mode 100644
index 00000000000..868fb23c01b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-10.c
@@ -0,0 +1,129 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define NumSamples 4
+
+/* vec_all_eq not yet supported for arguments of type
+ vector unsigned __int128. */
+int
+vector_equal (vector unsigned __int128 a, vector unsigned __int128 b)
+{
+ return a[0] == b[0];
+}
+
+void
+doTests00000001 (vector unsigned __int128 a_sources [],
+ vector unsigned __int128 b_sources [],
+ vector unsigned __int128 c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned __int128 a = a_sources [i];
+ vector unsigned __int128 b = b_sources [j];
+ vector unsigned __int128 c = c_sources [k];
+ vector unsigned __int128 result;
+ result = vec_ternarylogic (a, b, c, 0xfff); /* { dg-error "8-bit unsigned literal" } */
+ vector unsigned __int128 intended = (a & b & c);
+ if (!vector_equal (result, intended))
+ abort ();
+ }
+}
+
+void
+doTests11100101 (vector unsigned __int128 a_sources [],
+ vector unsigned __int128 b_sources [],
+ vector unsigned __int128 c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned __int128 a = a_sources [i];
+ vector unsigned __int128 b = b_sources [j];
+ vector unsigned __int128 c = c_sources [k];
+ vector unsigned __int128 result;
+ result = vec_ternarylogic (a, b, c, -1); /* { dg-error "8-bit unsigned literal" } */
+ vector unsigned __int128 intended = { 0 };
+ // Supposed to be a ? c: nand (b,c)
+ for (int l = 0; l < 1; l++)
+ {
+ for (int m = 0; m < 128; m++)
+ {
+ unsigned __int128 bit_selector = 0x01;
+ bit_selector = bit_selector << m;
+
+ if (a[l] & bit_selector)
+ intended [l] |= c [l] & bit_selector;
+ else if ((b [l] & c [l] & bit_selector) == 0)
+ intended [l] |= bit_selector;
+ }
+ }
+ if (!vector_equal (result, intended))
+ abort ();
+ }
+}
+
+void
+doTests11110011 (vector unsigned __int128 a_sources [],
+ vector unsigned __int128 b_sources [],
+ vector unsigned __int128 c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned __int128 a = a_sources [i];
+ vector unsigned __int128 b = b_sources [j];
+ vector unsigned __int128 c = c_sources [k];
+ vector unsigned __int128 result;
+ result = vec_ternarylogic (a, b, c, i); /* { dg-error "8-bit unsigned literal" } */
+ vector unsigned __int128 intended = { 0 };
+ for (int i = 0; i < 1; i++)
+ intended [i] = b [i] | ~(a [i] & c [i]);
+ if (!vector_equal (result, intended))
+ abort ();
+ }
+}
+
+int main (int argc, int *argv [])
+{
+ vector unsigned __int128 a_sources [NumSamples];
+ vector unsigned __int128 b_sources [NumSamples];
+ vector unsigned __int128 c_sources [NumSamples];
+
+ a_sources [0][0] = 0x0123456789abcdefull;
+ a_sources [0][0] = a_sources [0][0] << 64 | 0x123456789abcdef0ull;
+ a_sources [1][0] = 0x5555555555555555ull;
+ a_sources [1][0] = a_sources [1][0] << 64 | 0xffffffffffffffffull;
+ a_sources [2][0] = 0xcccccccc55555555ull;
+ a_sources [2][0] = a_sources [2][0] << 64 | 0x0000000000000000ull;
+ a_sources [3][0] = 0xe7e7e7e7e7e7e7e7ull;
+ a_sources [3][0] = a_sources [3][0] << 64 | 0x6969696969696969ull;
+
+ b_sources [0][0] = 0x0123456789abcdefull;
+ b_sources [0][0] = b_sources [0][0] << 64 | 0x123456789abcdef0ull;
+ b_sources [1][0] = 0x5555555555555555ull;
+ b_sources [1][0] = b_sources [1][0] << 64 | 0xffffffffffffffffull;
+ b_sources [2][0] = 0xcccccccc55555555ull;
+ b_sources [2][0] = b_sources [2][0] << 64 | 0x0000000000000000ull;
+ b_sources [3][0] = 0xe7e7e7e7e7e7e7e7ull;
+ b_sources [3][0] = b_sources [3][0] << 64 | 0x6969696969696969ull;
+
+ c_sources [0][0] = 0x0123456789abcdefull;
+ c_sources [0][0] = c_sources [0][0] << 64 | 0x123456789abcdef0ull;
+ c_sources [1][0] = 0x5555555555555555ull;
+ c_sources [1][0] = c_sources [1][0] << 64 | 0xffffffffffffffffull;
+ c_sources [2][0] = 0xcccccccc55555555ull;
+ c_sources [2][0] = c_sources [2][0] << 64 | 0x0000000000000000ull;
+ c_sources [3][0] = 0xe7e7e7e7e7e7e7e7ull;
+ c_sources [3][0] = c_sources [3][0] << 64 | 0x6969696969696969ull;
+
+ doTests00000001 (a_sources, b_sources, c_sources);
+ doTests11100101 (a_sources, b_sources, c_sources);
+ doTests11110011 (a_sources, b_sources, c_sources);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-2.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-2.c
new file mode 100644
index 00000000000..0d482b8e672
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-2.c
@@ -0,0 +1,105 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define NumSamples 4
+
+void
+doTests00000001 (vector unsigned short int a_sources [],
+ vector unsigned short int b_sources [],
+ vector unsigned short int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned short a = a_sources [i];
+ vector unsigned short b = b_sources [j];
+ vector unsigned short c = c_sources [k];
+ vector unsigned short result = vec_ternarylogic (a, b, c, 0x01);
+ vector unsigned short intended = (a & b & c);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void doTests11100101 (vector unsigned short int a_sources [],
+ vector unsigned short int b_sources [],
+ vector unsigned short int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned short a = a_sources [i];
+ vector unsigned short b = b_sources [j];
+ vector unsigned short c = c_sources [k];
+ vector unsigned short result = vec_ternarylogic (a, b, c, 0xe5);
+ vector unsigned short intended =
+ { 0, 0, 0, 0, 0, 0, 0, 0 };
+ // Supposed to be a ? c: nand (b,c)
+ for (int l = 0; l < 8; l++)
+ {
+ for (int m = 0; m < 16; m++)
+ {
+ unsigned short int bit_selector = (0x01 << m);
+ if (a[l] & bit_selector)
+ intended [l] |= c [l] & bit_selector;
+ else if ((b [l] & c [l] & bit_selector) == 0)
+ intended [l] |= bit_selector;
+ }
+ }
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void doTests11110011 (vector unsigned short int a_sources [],
+ vector unsigned short int b_sources [],
+ vector unsigned short int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned short a = a_sources [i];
+ vector unsigned short b = b_sources [j];
+ vector unsigned short c = c_sources [k];
+ vector unsigned short result = vec_ternarylogic (a, b, c, 0xfb);
+ vector unsigned short intended = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ for (int i = 0; i < 8; i++)
+ intended [i] = b [i] | ~(a [i] & c [i]);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+int main (int argc, short *argv [])
+{
+ vector unsigned short int a_sources [NumSamples] = {
+ { 0x0123, 0x4567, 0x89ab, 0xcdef, 0x1234, 0x5678, 0x9abc, 0xdef0 },
+ { 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff },
+ { 0xcccc, 0xcccc, 0x5555, 0x5555, 0x0000, 0x0000, 0x0000, 0x0000 },
+ { 0xe7e7, 0xe7e7, 0xe7e7, 0xe7e7, 0x6969, 0x6969, 0x6969, 0x6969 },
+ };
+ vector unsigned short int b_sources [NumSamples] = {
+ { 0x0123, 0x4567, 0x89ab, 0xcdef, 0x1234, 0x5678, 0x9abc, 0xdef0 },
+ { 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff },
+ { 0xcccc, 0xcccc, 0x5555, 0x5555, 0x0000, 0x0000, 0x0000, 0x0000 },
+ { 0xe7e7, 0xe7e7, 0xe7e7, 0xe7e7, 0x6969, 0x6969, 0x6969, 0x6969 },
+ };
+ vector unsigned short int c_sources [NumSamples] = {
+ { 0x0123, 0x4567, 0x89ab, 0xcdef, 0x1234, 0x5678, 0x9abc, 0xdef0 },
+ { 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff },
+ { 0xcccc, 0xcccc, 0x5555, 0x5555, 0x0000, 0x0000, 0x0000, 0x0000 },
+ { 0xe7e7, 0xe7e7, 0xe7e7, 0xe7e7, 0x6969, 0x6969, 0x6969, 0x6969 },
+ };
+
+ doTests00000001 (a_sources, b_sources, c_sources);
+ doTests11100101 (a_sources, b_sources, c_sources);
+ doTests11110011 (a_sources, b_sources, c_sources);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler {\mxxeval\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-3.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-3.c
new file mode 100644
index 00000000000..a7245e51da2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-3.c
@@ -0,0 +1,106 @@
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define NumSamples 4
+
+void
+doTests00000001 (vector unsigned short int a_sources [],
+ vector unsigned short int b_sources [],
+ vector unsigned short int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned short a = a_sources [i];
+ vector unsigned short b = b_sources [j];
+ vector unsigned short c = c_sources [k];
+ vector unsigned short result = vec_ternarylogic (a, b, c, 0x01);
+ vector unsigned short intended = (a & b & c);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void doTests11100101 (vector unsigned short int a_sources [],
+ vector unsigned short int b_sources [],
+ vector unsigned short int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned short a = a_sources [i];
+ vector unsigned short b = b_sources [j];
+ vector unsigned short c = c_sources [k];
+ vector unsigned short result = vec_ternarylogic (a, b, c, 0xe5);
+ vector unsigned short intended =
+ { 0, 0, 0, 0, 0, 0, 0, 0 };
+ // Supposed to be a ? c: nand (b,c)
+ for (int l = 0; l < 8; l++)
+ {
+ for (int m = 0; m < 16; m++)
+ {
+ unsigned short int bit_selector = (0x01 << m);
+ if (a[l] & bit_selector)
+ intended [l] |= c [l] & bit_selector;
+ else if ((b [l] & c [l] & bit_selector) == 0)
+ intended [l] |= bit_selector;
+ }
+ }
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void doTests11110011 (vector unsigned short int a_sources [],
+ vector unsigned short int b_sources [],
+ vector unsigned short int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned short a = a_sources [i];
+ vector unsigned short b = b_sources [j];
+ vector unsigned short c = c_sources [k];
+ vector unsigned short result = vec_ternarylogic (a, b, c, 0xfb);
+ vector unsigned short intended = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ for (int i = 0; i < 8; i++)
+ intended [i] = b [i] | ~(a [i] & c [i]);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+int main (int argc, short *argv [])
+{
+ vector unsigned short int a_sources [NumSamples] = {
+ { 0x0123, 0x4567, 0x89ab, 0xcdef, 0x1234, 0x5678, 0x9abc, 0xdef0 },
+ { 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff },
+ { 0xcccc, 0xcccc, 0x5555, 0x5555, 0x0000, 0x0000, 0x0000, 0x0000 },
+ { 0xe7e7, 0xe7e7, 0xe7e7, 0xe7e7, 0x6969, 0x6969, 0x6969, 0x6969 },
+ };
+ vector unsigned short int b_sources [NumSamples] = {
+ { 0x0123, 0x4567, 0x89ab, 0xcdef, 0x1234, 0x5678, 0x9abc, 0xdef0 },
+ { 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff },
+ { 0xcccc, 0xcccc, 0x5555, 0x5555, 0x0000, 0x0000, 0x0000, 0x0000 },
+ { 0xe7e7, 0xe7e7, 0xe7e7, 0xe7e7, 0x6969, 0x6969, 0x6969, 0x6969 },
+ };
+ vector unsigned short int c_sources [NumSamples] = {
+ { 0x0123, 0x4567, 0x89ab, 0xcdef, 0x1234, 0x5678, 0x9abc, 0xdef0 },
+ { 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff },
+ { 0xcccc, 0xcccc, 0x5555, 0x5555, 0x0000, 0x0000, 0x0000, 0x0000 },
+ { 0xe7e7, 0xe7e7, 0xe7e7, 0xe7e7, 0x6969, 0x6969, 0x6969, 0x6969 },
+ };
+
+ doTests00000001 (a_sources, b_sources, c_sources);
+ doTests11100101 (a_sources, b_sources, c_sources);
+ doTests11110011 (a_sources, b_sources, c_sources);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler {\mxxeval\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-4.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-4.c
new file mode 100644
index 00000000000..dbd9ffb856e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-4.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define NumSamples 4
+
+void
+doTests00000001 (vector unsigned int a_sources [],
+ vector unsigned int b_sources [],
+ vector unsigned int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned int a = a_sources [i];
+ vector unsigned int b = b_sources [j];
+ vector unsigned int c = c_sources [k];
+ vector unsigned int result = vec_ternarylogic (a, b, c, 0x01);
+ vector unsigned int intended = (a & b & c);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void doTests11100101 (vector unsigned int a_sources [],
+ vector unsigned int b_sources [],
+ vector unsigned int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned int a = a_sources [i];
+ vector unsigned int b = b_sources [j];
+ vector unsigned int c = c_sources [k];
+ vector unsigned int result = vec_ternarylogic (a, b, c, 0xe5);
+ vector unsigned int intended = { 0, 0, 0, 0 };
+ // Supposed to be a ? c: nand (b,c)
+ for (int l = 0; l < 4; l++)
+ {
+ for (int m = 0; m < 32; m++)
+ {
+ unsigned int bit_selector = (0x01 << m);
+ if (a[l] & bit_selector)
+ intended [l] |= c [l] & bit_selector;
+ else if ((b [l] & c [l] & bit_selector) == 0)
+ intended [l] |= bit_selector;
+ }
+ }
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void doTests11110011 (vector unsigned int a_sources [],
+ vector unsigned int b_sources [],
+ vector unsigned int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned int a = a_sources [i];
+ vector unsigned int b = b_sources [j];
+ vector unsigned int c = c_sources [k];
+ vector unsigned int result = vec_ternarylogic (a, b, c, 0xfb);
+ vector unsigned int intended = { 0, 0, 0, 0 };
+ for (int i = 0; i < 4; i++)
+ intended [i] = b [i] | ~(a [i] & c [i]);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+int main (int argc, int *argv [])
+{
+ vector unsigned int a_sources [NumSamples] = {
+ { 0x01234567, 0x89abcdef, 0x12345678, 0x9abcdef0 },
+ { 0x55555555, 0x55555555, 0xffffffff, 0xffffffff },
+ { 0xcccccccc, 0x55555555, 0x00000000, 0x00000000 },
+ { 0xe7e7e7e7, 0xe7e7e7e7, 0x69696969, 0x69696969 },
+ };
+ vector unsigned int b_sources [NumSamples] = {
+ { 0x01234567, 0x89abcdef, 0x12345678, 0x9abcdef0 },
+ { 0x55555555, 0x55555555, 0xffffffff, 0xffffffff },
+ { 0xcccccccc, 0x55555555, 0x00000000, 0x00000000 },
+ { 0xe7e7e7e7, 0xe7e7e7e7, 0x69696969, 0x69696969 },
+ };
+ vector unsigned int c_sources [NumSamples] = {
+ { 0x01234567, 0x89abcdef, 0x12345678, 0x9abcdef0 },
+ { 0x55555555, 0x55555555, 0xffffffff, 0xffffffff },
+ { 0xcccccccc, 0x55555555, 0x00000000, 0x00000000 },
+ { 0xe7e7e7e7, 0xe7e7e7e7, 0x69696969, 0x69696969 },
+ };
+
+ doTests00000001 (a_sources, b_sources, c_sources);
+ doTests11100101 (a_sources, b_sources, c_sources);
+ doTests11110011 (a_sources, b_sources, c_sources);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler {\mxxeval\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-5.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-5.c
new file mode 100644
index 00000000000..4d5d8e5e0d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-5.c
@@ -0,0 +1,103 @@
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define NumSamples 4
+
+void
+doTests00000001 (vector unsigned int a_sources [],
+ vector unsigned int b_sources [],
+ vector unsigned int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned int a = a_sources [i];
+ vector unsigned int b = b_sources [j];
+ vector unsigned int c = c_sources [k];
+ vector unsigned int result = vec_ternarylogic (a, b, c, 0x01);
+ vector unsigned int intended = (a & b & c);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void doTests11100101 (vector unsigned int a_sources [],
+ vector unsigned int b_sources [],
+ vector unsigned int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned int a = a_sources [i];
+ vector unsigned int b = b_sources [j];
+ vector unsigned int c = c_sources [k];
+ vector unsigned int result = vec_ternarylogic (a, b, c, 0xe5);
+ vector unsigned int intended = { 0, 0, 0, 0 };
+ // Supposed to be a ? c: nand (b,c)
+ for (int l = 0; l < 4; l++)
+ {
+ for (int m = 0; m < 32; m++)
+ {
+ unsigned int bit_selector = (0x01 << m);
+ if (a[l] & bit_selector)
+ intended [l] |= c [l] & bit_selector;
+ else if ((b [l] & c [l] & bit_selector) == 0)
+ intended [l] |= bit_selector;
+ }
+ }
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void doTests11110011 (vector unsigned int a_sources [],
+ vector unsigned int b_sources [],
+ vector unsigned int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned int a = a_sources [i];
+ vector unsigned int b = b_sources [j];
+ vector unsigned int c = c_sources [k];
+ vector unsigned int result = vec_ternarylogic (a, b, c, 0xfb);
+ vector unsigned int intended = { 0, 0, 0, 0 };
+ for (int i = 0; i < 4; i++)
+ intended [i] = b [i] | ~(a [i] & c [i]);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+int main (int argc, int *argv [])
+{
+ vector unsigned int a_sources [NumSamples] = {
+ { 0x01234567, 0x89abcdef, 0x12345678, 0x9abcdef0 },
+ { 0x55555555, 0x55555555, 0xffffffff, 0xffffffff },
+ { 0xcccccccc, 0x55555555, 0x00000000, 0x00000000 },
+ { 0xe7e7e7e7, 0xe7e7e7e7, 0x69696969, 0x69696969 },
+ };
+ vector unsigned int b_sources [NumSamples] = {
+ { 0x01234567, 0x89abcdef, 0x12345678, 0x9abcdef0 },
+ { 0x55555555, 0x55555555, 0xffffffff, 0xffffffff },
+ { 0xcccccccc, 0x55555555, 0x00000000, 0x00000000 },
+ { 0xe7e7e7e7, 0xe7e7e7e7, 0x69696969, 0x69696969 },
+ };
+ vector unsigned int c_sources [NumSamples] = {
+ { 0x01234567, 0x89abcdef, 0x12345678, 0x9abcdef0 },
+ { 0x55555555, 0x55555555, 0xffffffff, 0xffffffff },
+ { 0xcccccccc, 0x55555555, 0x00000000, 0x00000000 },
+ { 0xe7e7e7e7, 0xe7e7e7e7, 0x69696969, 0x69696969 },
+ };
+
+ doTests00000001 (a_sources, b_sources, c_sources);
+ doTests11100101 (a_sources, b_sources, c_sources);
+ doTests11110011 (a_sources, b_sources, c_sources);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-6.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-6.c
new file mode 100644
index 00000000000..0114bacd5fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-6.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define NumSamples 4
+
+void
+doTests00000001 (vector unsigned long long int a_sources [],
+ vector unsigned long long int b_sources [],
+ vector unsigned long long int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned long long a = a_sources [i];
+ vector unsigned long long b = b_sources [j];
+ vector unsigned long long c = c_sources [k];
+ vector unsigned long long result = vec_ternarylogic (a, b, c, 0x01);
+ vector unsigned long long intended = (a & b & c);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void doTests11100101 (vector unsigned long long int a_sources [],
+ vector unsigned long long int b_sources [],
+ vector unsigned long long int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned long long a = a_sources [i];
+ vector unsigned long long b = b_sources [j];
+ vector unsigned long long c = c_sources [k];
+ vector unsigned long long result = vec_ternarylogic (a, b, c, 0xe5);
+ vector unsigned long long intended = { 0, 0 };
+ // Supposed to be a ? c: nand (b,c)
+ for (int l = 0; l < 2; l++)
+ {
+ for (int m = 0; m < 64; m++)
+ {
+ unsigned long long int bit_selector = (0x01ll << m);
+ if (a[l] & bit_selector)
+ intended [l] |= c [l] & bit_selector;
+ else if ((b [l] & c [l] & bit_selector) == 0)
+ intended [l] |= (0x01ll << m);
+ }
+ }
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void doTests11110011 (vector unsigned long long int a_sources [],
+ vector unsigned long long int b_sources [],
+ vector unsigned long long int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned long long a = a_sources [i];
+ vector unsigned long long b = b_sources [j];
+ vector unsigned long long c = c_sources [k];
+ vector unsigned long long result = vec_ternarylogic (a, b, c, 0xfb);
+ vector unsigned long long intended = { 0, 0 };
+ intended [0] = b [0] | ~(a [0] & c [0]);
+ intended [1] = b [1] | ~(a [1] & c [1]);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+int main (int argc, char *argv [])
+{
+ vector unsigned long long int a_sources [NumSamples] = {
+ { 0x0123456789abcdef, 0x123456789abcdef0 },
+ { 0x5555555555555555, 0xffffffffffffffff },
+ { 0xcccccccc55555555, 0x0000000000000000 },
+ { 0xe7e7e7e7e7e7e7e7, 0x6969696969696969 },
+ };
+ vector unsigned long long int b_sources [NumSamples] = {
+ { 0x0123456789abcdef, 0x123456789abcdef0 },
+ { 0x5555555555555555, 0xffffffffffffffff },
+ { 0xcccccccc55555555, 0x0000000000000000 },
+ { 0xe7e7e7e7e7e7e7e7, 0x6969696969696969 },
+ };
+ vector unsigned long long int c_sources [NumSamples] = {
+ { 0x0123456789abcdef, 0x123456789abcdef0 },
+ { 0x5555555555555555, 0xffffffffffffffff },
+ { 0xcccccccc55555555, 0x0000000000000000 },
+ { 0xe7e7e7e7e7e7e7e7, 0x6969696969696969 },
+ };
+
+ doTests00000001 (a_sources, b_sources, c_sources);
+ doTests11100101 (a_sources, b_sources, c_sources);
+ doTests11110011 (a_sources, b_sources, c_sources);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler {\mxxeval\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-7.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-7.c
new file mode 100644
index 00000000000..27ac4a22866
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-7.c
@@ -0,0 +1,103 @@
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define NumSamples 4
+
+void
+doTests00000001 (vector unsigned long long int a_sources [],
+ vector unsigned long long int b_sources [],
+ vector unsigned long long int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned long long a = a_sources [i];
+ vector unsigned long long b = b_sources [j];
+ vector unsigned long long c = c_sources [k];
+ vector unsigned long long result = vec_ternarylogic (a, b, c, 0x01);
+ vector unsigned long long intended = (a & b & c);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void doTests11100101 (vector unsigned long long int a_sources [],
+ vector unsigned long long int b_sources [],
+ vector unsigned long long int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned long long a = a_sources [i];
+ vector unsigned long long b = b_sources [j];
+ vector unsigned long long c = c_sources [k];
+ vector unsigned long long result = vec_ternarylogic (a, b, c, 0xe5);
+ vector unsigned long long intended = { 0, 0 };
+ // Supposed to be a ? c: nand (b,c)
+ for (int l = 0; l < 2; l++)
+ {
+ for (int m = 0; m < 64; m++)
+ {
+ unsigned long long int bit_selector = (0x01ll << m);
+ if (a[l] & bit_selector)
+ intended [l] |= c [l] & bit_selector;
+ else if ((b [l] & c [l] & bit_selector) == 0)
+ intended [l] |= (0x01ll << m);
+ }
+ }
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+void doTests11110011 (vector unsigned long long int a_sources [],
+ vector unsigned long long int b_sources [],
+ vector unsigned long long int c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned long long a = a_sources [i];
+ vector unsigned long long b = b_sources [j];
+ vector unsigned long long c = c_sources [k];
+ vector unsigned long long result = vec_ternarylogic (a, b, c, 0xfb);
+ vector unsigned long long intended = { 0, 0 };
+ intended [0] = b [0] | ~(a [0] & c [0]);
+ intended [1] = b [1] | ~(a [1] & c [1]);
+ if (!vec_all_eq (result, intended))
+ abort ();
+ }
+}
+
+int main (int argc, char *argv [])
+{
+ vector unsigned long long int a_sources [NumSamples] = {
+ { 0x0123456789abcdef, 0x123456789abcdef0 },
+ { 0x5555555555555555, 0xffffffffffffffff },
+ { 0xcccccccc55555555, 0x0000000000000000 },
+ { 0xe7e7e7e7e7e7e7e7, 0x6969696969696969 },
+ };
+ vector unsigned long long int b_sources [NumSamples] = {
+ { 0x0123456789abcdef, 0x123456789abcdef0 },
+ { 0x5555555555555555, 0xffffffffffffffff },
+ { 0xcccccccc55555555, 0x0000000000000000 },
+ { 0xe7e7e7e7e7e7e7e7, 0x6969696969696969 },
+ };
+ vector unsigned long long int c_sources [NumSamples] = {
+ { 0x0123456789abcdef, 0x123456789abcdef0 },
+ { 0x5555555555555555, 0xffffffffffffffff },
+ { 0xcccccccc55555555, 0x0000000000000000 },
+ { 0xe7e7e7e7e7e7e7e7, 0x6969696969696969 },
+ };
+
+ doTests00000001 (a_sources, b_sources, c_sources);
+ doTests11100101 (a_sources, b_sources, c_sources);
+ doTests11110011 (a_sources, b_sources, c_sources);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-8.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-8.c
new file mode 100644
index 00000000000..0d6b9e74239
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-8.c
@@ -0,0 +1,128 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define NumSamples 4
+
+/* vec_all_eq not yet supported for arguments of type
+ vector unsigned __int128. */
+int
+vector_equal (vector unsigned __int128 a, vector unsigned __int128 b)
+{
+ return a[0] == b[0];
+}
+
+void
+doTests00000001 (vector unsigned __int128 a_sources [],
+ vector unsigned __int128 b_sources [],
+ vector unsigned __int128 c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned __int128 a = a_sources [i];
+ vector unsigned __int128 b = b_sources [j];
+ vector unsigned __int128 c = c_sources [k];
+ vector unsigned __int128 result = vec_ternarylogic (a, b, c, 0x01);
+ vector unsigned __int128 intended = (a & b & c);
+ if (!vector_equal (result, intended))
+ abort ();
+ }
+}
+
+void
+doTests11100101 (vector unsigned __int128 a_sources [],
+ vector unsigned __int128 b_sources [],
+ vector unsigned __int128 c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned __int128 a = a_sources [i];
+ vector unsigned __int128 b = b_sources [j];
+ vector unsigned __int128 c = c_sources [k];
+ vector unsigned __int128 result = vec_ternarylogic (a, b, c, 0xe5);
+ vector unsigned __int128 intended = { 0 };
+ // Supposed to be a ? c: nand (b,c)
+ for (int l = 0; l < 1; l++)
+ {
+ for (int m = 0; m < 128; m++)
+ {
+ unsigned __int128 bit_selector = 0x01;
+ bit_selector = bit_selector << m;
+
+ if (a[l] & bit_selector)
+ intended [l] |= c [l] & bit_selector;
+ else if ((b [l] & c [l] & bit_selector) == 0)
+ intended [l] |= bit_selector;
+ }
+ }
+ if (!vector_equal (result, intended))
+ abort ();
+ }
+}
+
+void
+doTests11110011 (vector unsigned __int128 a_sources [],
+ vector unsigned __int128 b_sources [],
+ vector unsigned __int128 c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned __int128 a = a_sources [i];
+ vector unsigned __int128 b = b_sources [j];
+ vector unsigned __int128 c = c_sources [k];
+ vector unsigned __int128 result = vec_ternarylogic (a, b, c, 0xfb);
+ vector unsigned __int128 intended = { 0 };
+ for (int i = 0; i < 1; i++)
+ intended [i] = b [i] | ~(a [i] & c [i]);
+ if (!vector_equal (result, intended))
+ abort ();
+ }
+}
+
+int main (int argc, int *argv [])
+{
+ vector unsigned __int128 a_sources [NumSamples];
+ vector unsigned __int128 b_sources [NumSamples];
+ vector unsigned __int128 c_sources [NumSamples];
+
+ a_sources [0][0] = 0x0123456789abcdefull;
+ a_sources [0][0] = a_sources [0][0] << 64 | 0x123456789abcdef0ull;
+ a_sources [1][0] = 0x5555555555555555ull;
+ a_sources [1][0] = a_sources [1][0] << 64 | 0xffffffffffffffffull;
+ a_sources [2][0] = 0xcccccccc55555555ull;
+ a_sources [2][0] = a_sources [2][0] << 64 | 0x0000000000000000ull;
+ a_sources [3][0] = 0xe7e7e7e7e7e7e7e7ull;
+ a_sources [3][0] = a_sources [3][0] << 64 | 0x6969696969696969ull;
+
+ b_sources [0][0] = 0x0123456789abcdefull;
+ b_sources [0][0] = b_sources [0][0] << 64 | 0x123456789abcdef0ull;
+ b_sources [1][0] = 0x5555555555555555ull;
+ b_sources [1][0] = b_sources [1][0] << 64 | 0xffffffffffffffffull;
+ b_sources [2][0] = 0xcccccccc55555555ull;
+ b_sources [2][0] = b_sources [2][0] << 64 | 0x0000000000000000ull;
+ b_sources [3][0] = 0xe7e7e7e7e7e7e7e7ull;
+ b_sources [3][0] = b_sources [3][0] << 64 | 0x6969696969696969ull;
+
+ c_sources [0][0] = 0x0123456789abcdefull;
+ c_sources [0][0] = c_sources [0][0] << 64 | 0x123456789abcdef0ull;
+ c_sources [1][0] = 0x5555555555555555ull;
+ c_sources [1][0] = c_sources [1][0] << 64 | 0xffffffffffffffffull;
+ c_sources [2][0] = 0xcccccccc55555555ull;
+ c_sources [2][0] = c_sources [2][0] << 64 | 0x0000000000000000ull;
+ c_sources [3][0] = 0xe7e7e7e7e7e7e7e7ull;
+ c_sources [3][0] = c_sources [3][0] << 64 | 0x6969696969696969ull;
+
+ doTests00000001 (a_sources, b_sources, c_sources);
+ doTests11100101 (a_sources, b_sources, c_sources);
+ doTests11110011 (a_sources, b_sources, c_sources);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler {\mxxeval\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-9.c b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-9.c
new file mode 100644
index 00000000000..b6113596867
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-9.c
@@ -0,0 +1,129 @@
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+#define NumSamples 4
+
+/* vec_all_eq not yet supported for arguments of type
+ vector unsigned __int128. */
+int
+vector_equal (vector unsigned __int128 a, vector unsigned __int128 b)
+{
+ return a[0] == b[0];
+}
+
+void
+doTests00000001 (vector unsigned __int128 a_sources [],
+ vector unsigned __int128 b_sources [],
+ vector unsigned __int128 c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned __int128 a = a_sources [i];
+ vector unsigned __int128 b = b_sources [j];
+ vector unsigned __int128 c = c_sources [k];
+ vector unsigned __int128 result = vec_ternarylogic (a, b, c, 0x01);
+ vector unsigned __int128 intended = (a & b & c);
+ if (!vector_equal (result, intended))
+ abort ();
+ }
+}
+
+void
+doTests11100101 (vector unsigned __int128 a_sources [],
+ vector unsigned __int128 b_sources [],
+ vector unsigned __int128 c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned __int128 a = a_sources [i];
+ vector unsigned __int128 b = b_sources [j];
+ vector unsigned __int128 c = c_sources [k];
+ vector unsigned __int128 result = vec_ternarylogic (a, b, c, 0xe5);
+ vector unsigned __int128 intended = { 0 };
+ // Supposed to be a ? c: nand (b,c)
+ for (int l = 0; l < 1; l++)
+ {
+ for (int m = 0; m < 128; m++)
+ {
+ unsigned __int128 bit_selector = 0x01;
+ bit_selector = bit_selector << m;
+
+ if (a[l] & bit_selector)
+ intended [l] |= c [l] & bit_selector;
+ else if ((b [l] & c [l] & bit_selector) == 0)
+ intended [l] |= bit_selector;
+ }
+ }
+ if (!vector_equal (result, intended))
+ abort ();
+ }
+}
+
+void
+doTests11110011 (vector unsigned __int128 a_sources [],
+ vector unsigned __int128 b_sources [],
+ vector unsigned __int128 c_sources []) {
+ for (int i = 0; i < NumSamples; i++)
+ for (int j = 0; j < NumSamples; j++)
+ for (int k = 0; k < NumSamples; k++)
+ {
+ vector unsigned __int128 a = a_sources [i];
+ vector unsigned __int128 b = b_sources [j];
+ vector unsigned __int128 c = c_sources [k];
+ vector unsigned __int128 result = vec_ternarylogic (a, b, c, 0xfb);
+ vector unsigned __int128 intended = { 0 };
+ for (int i = 0; i < 1; i++)
+ intended [i] = b [i] | ~(a [i] & c [i]);
+ if (!vector_equal (result, intended))
+ abort ();
+ }
+}
+
+int main (int argc, int *argv [])
+{
+ vector unsigned __int128 a_sources [NumSamples];
+ vector unsigned __int128 b_sources [NumSamples];
+ vector unsigned __int128 c_sources [NumSamples];
+
+ a_sources [0][0] = 0x0123456789abcdefull;
+ a_sources [0][0] = a_sources [0][0] << 64 | 0x123456789abcdef0ull;
+ a_sources [1][0] = 0x5555555555555555ull;
+ a_sources [1][0] = a_sources [1][0] << 64 | 0xffffffffffffffffull;
+ a_sources [2][0] = 0xcccccccc55555555ull;
+ a_sources [2][0] = a_sources [2][0] << 64 | 0x0000000000000000ull;
+ a_sources [3][0] = 0xe7e7e7e7e7e7e7e7ull;
+ a_sources [3][0] = a_sources [3][0] << 64 | 0x6969696969696969ull;
+
+ b_sources [0][0] = 0x0123456789abcdefull;
+ b_sources [0][0] = b_sources [0][0] << 64 | 0x123456789abcdef0ull;
+ b_sources [1][0] = 0x5555555555555555ull;
+ b_sources [1][0] = b_sources [1][0] << 64 | 0xffffffffffffffffull;
+ b_sources [2][0] = 0xcccccccc55555555ull;
+ b_sources [2][0] = b_sources [2][0] << 64 | 0x0000000000000000ull;
+ b_sources [3][0] = 0xe7e7e7e7e7e7e7e7ull;
+ b_sources [3][0] = b_sources [3][0] << 64 | 0x6969696969696969ull;
+
+ c_sources [0][0] = 0x0123456789abcdefull;
+ c_sources [0][0] = c_sources [0][0] << 64 | 0x123456789abcdef0ull;
+ c_sources [1][0] = 0x5555555555555555ull;
+ c_sources [1][0] = c_sources [1][0] << 64 | 0xffffffffffffffffull;
+ c_sources [2][0] = 0xcccccccc55555555ull;
+ c_sources [2][0] = c_sources [2][0] << 64 | 0x0000000000000000ull;
+ c_sources [3][0] = 0xe7e7e7e7e7e7e7e7ull;
+ c_sources [3][0] = c_sources [3][0] << 64 | 0x6969696969696969ull;
+
+ doTests00000001 (a_sources, b_sources, c_sources);
+ doTests11100101 (a_sources, b_sources, c_sources);
+ doTests11110011 (a_sources, b_sources, c_sources);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler {\mxxeval\M} } } */