On Fri, May 8, 2020 at 9:13 PM Bill Schmidt <wschm...@linux.ibm.com> wrote: > > 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. The above two should be altivec.md > * 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. I would add "Use it". > (BU_FUTURE_OVERLOAD_4): Likewise. I would add "Use it". > * 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. Inserting this value doesn't seem completely safe, but I guess that it works. > (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. Okay with those changes, plus any issues noticed by Segher. Thanks, David > --- > 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 >