From: Kelvin Nilsen <kel...@gcc.gnu.org>

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.

Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no
regressions, using a native POWER9 compiler.  Is this okay for
master?

Thanks,
Bill

[gcc]

2020-05-08  Kelvin Nilsen  <wschm...@linux.ibm.com>

        * config/rs6000/altivec.h (vec_ternarylogic): New #define.
        (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.
        (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-08  Kelvin Nilsen  <wschm...@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.
---
 gcc/config/rs6000/altivec.h                   |   1 +
 gcc/config/rs6000/altivec.md                  |  11 +
 gcc/config/rs6000/predicates.md               |   5 +
 gcc/config/rs6000/rs6000-builtin.def          |  23 ++
 gcc/config/rs6000/rs6000-c.c                  |  47 +++-
 gcc/config/rs6000/rs6000-call.c               | 251 ++++++++++++++++++
 gcc/config/rs6000/rs6000.h                    |  12 +-
 gcc/doc/extend.texi                           |  21 ++
 .../gcc.target/powerpc/vec-ternarylogic-0.c   | 120 +++++++++
 .../gcc.target/powerpc/vec-ternarylogic-1.c   | 119 +++++++++
 .../gcc.target/powerpc/vec-ternarylogic-10.c  | 129 +++++++++
 .../gcc.target/powerpc/vec-ternarylogic-2.c   | 105 ++++++++
 .../gcc.target/powerpc/vec-ternarylogic-3.c   | 106 ++++++++
 .../gcc.target/powerpc/vec-ternarylogic-4.c   | 104 ++++++++
 .../gcc.target/powerpc/vec-ternarylogic-5.c   | 103 +++++++
 .../gcc.target/powerpc/vec-ternarylogic-6.c   | 104 ++++++++
 .../gcc.target/powerpc/vec-ternarylogic-7.c   | 103 +++++++
 .../gcc.target/powerpc/vec-ternarylogic-8.c   | 128 +++++++++
 .../gcc.target/powerpc/vec-ternarylogic-9.c   | 129 +++++++++
 19 files changed, 1616 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-0.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-1.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-10.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-2.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-3.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-4.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-5.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-6.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-7.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-8.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-ternarylogic-9.c

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 @@ (define_c_enum "unspec"
    UNSPEC_VPEXTD
    UNSPEC_VCLRLB
    UNSPEC_VCLRRB
+   UNSPEC_XXEVAL
 ])
 
 (define_c_enum "unspecv"
@@ -3271,6 +3272,16 @@ (define_insn "vperm_v16qiv8hi"
   [(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 @@ (define_predicate "u7bit_cint_operand"
   (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..9b9562ce4c3 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)
@@ -9580,6 +9654,76 @@ cpu_expand_builtin (enum rs6000_builtins fcode, tree exp 
ATTRIBUTE_UNUSED,
   return target;
 }
 
+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)
 {
@@ -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/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} } } */
-- 
2.17.1

Reply via email to