Andrew Pinski via Gcc-patches <gcc-patches@gcc.gnu.org> writes: > Like the support conditional neg (r12-4470-g20dcda98ed376cb61c74b2c71), > this just adds conditional not too. > Also we should be able to turn `(a ? -1 : 0) ^ b` into a conditional > not. > > OK? Bootstrapped and tested on x86_64-linux-gnu and aarch64-linux-gnu. > > gcc/ChangeLog: > > * internal-fn.def (COND_NOT): New internal function. > * match.pd (UNCOND_UNARY, COND_UNARY): Add bit_not/not > to the lists. > (`vec (a ? -1 : 0) ^ b`): New pattern to convert > into conditional not. > * optabs.def (cond_one_cmpl): New optab. > (cond_len_one_cmpl): Likewise. > > gcc/testsuite/ChangeLog: > > PR target/110986 > * gcc.target/aarch64/sve/cond_unary_9.c: New test. > --- > gcc/internal-fn.def | 2 ++ > gcc/match.pd | 15 ++++++++++++-- > gcc/optabs.def | 2 ++ > .../gcc.target/aarch64/sve/cond_unary_9.c | 20 +++++++++++++++++++ > 4 files changed, 37 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/cond_unary_9.c > > diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def > index b3c410f4b6a..3e8693dfddb 100644 > --- a/gcc/internal-fn.def > +++ b/gcc/internal-fn.def > @@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. If not see > lround<srcmode><dstmode>2. > > - cond_binary: a conditional binary optab, such as cond_add<mode> > + - cond_unary: a conditional unary optab, such as cond_neg<mode> > - cond_ternary: a conditional ternary optab, such as cond_fma_rev<mode> > > - fold_left: for scalar = FN (scalar, vector), keyed off the vector mode > @@ -276,6 +277,7 @@ DEF_INTERNAL_COND_FN (FNMA, ECF_CONST, fnma, ternary) > DEF_INTERNAL_COND_FN (FNMS, ECF_CONST, fnms, ternary) > > DEF_INTERNAL_COND_FN (NEG, ECF_CONST, neg, unary) > +DEF_INTERNAL_COND_FN (NOT, ECF_CONST, one_cmpl, unary) > > DEF_INTERNAL_OPTAB_FN (RSQRT, ECF_CONST, rsqrt, unary) > > diff --git a/gcc/match.pd b/gcc/match.pd > index 6791060891d..2ee6d24ccee 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -84,9 +84,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > > /* Unary operations and their associated IFN_COND_* function. */ > (define_operator_list UNCOND_UNARY > - negate) > + negate bit_not) > (define_operator_list COND_UNARY > - IFN_COND_NEG) > + IFN_COND_NEG IFN_COND_NOT) > > /* Binary operations and their associated IFN_COND_* function. */ > (define_operator_list UNCOND_BINARY > @@ -8482,6 +8482,17 @@ and, > && is_truth_type_for (op_type, TREE_TYPE (@0))) > (cond_op (bit_not @0) @2 @1))))) > > +/* `(a ? -1 : 0) ^ b` can be converted into a conditional not. */ > +(simplify > + (bit_xor:c (vec_cond @0 uniform_integer_cst_p@1 uniform_integer_cst_p@2) @3) > + (if (canonicalize_math_after_vectorization_p () > + && vectorized_internal_fn_supported_p (IFN_COND_NOT, type) > + && is_truth_type_for (type, TREE_TYPE (@0))) > + (if (integer_all_onesp (@1) && integer_zerop (@2)) > + (IFN_COND_NOT @0 @3 @3)) > + (if (integer_all_onesp (@2) && integer_zerop (@1)) > + (vec_cond (bit_not @0) @3 @3))))
Looks like this should be IFN_COND_NOT rather than vec_cond. LGTM otherwise, but please give Richi 24hrs to comment. Thanks, Richard > + > /* Simplify: > > a = a1 op a2 > diff --git a/gcc/optabs.def b/gcc/optabs.def > index 1ea1947b3b5..a58819bc665 100644 > --- a/gcc/optabs.def > +++ b/gcc/optabs.def > @@ -254,6 +254,7 @@ OPTAB_D (cond_fms_optab, "cond_fms$a") > OPTAB_D (cond_fnma_optab, "cond_fnma$a") > OPTAB_D (cond_fnms_optab, "cond_fnms$a") > OPTAB_D (cond_neg_optab, "cond_neg$a") > +OPTAB_D (cond_one_cmpl_optab, "cond_one_cmpl$a") > OPTAB_D (cond_len_add_optab, "cond_len_add$a") > OPTAB_D (cond_len_sub_optab, "cond_len_sub$a") > OPTAB_D (cond_len_smul_optab, "cond_len_mul$a") > @@ -278,6 +279,7 @@ OPTAB_D (cond_len_fms_optab, "cond_len_fms$a") > OPTAB_D (cond_len_fnma_optab, "cond_len_fnma$a") > OPTAB_D (cond_len_fnms_optab, "cond_len_fnms$a") > OPTAB_D (cond_len_neg_optab, "cond_len_neg$a") > +OPTAB_D (cond_len_one_cmpl_optab, "cond_len_one_cmpl$a") > OPTAB_D (cmov_optab, "cmov$a6") > OPTAB_D (cstore_optab, "cstore$a4") > OPTAB_D (ctrap_optab, "ctrap$a4") > diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_9.c > b/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_9.c > new file mode 100644 > index 00000000000..d6bc0409630 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_9.c > @@ -0,0 +1,20 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=256 > -fdump-tree-optimized" } */ > + > +/* This is a reduced version of cond_unary_5.c */ > + > +void __attribute__ ((noipa)) > +f (short *__restrict r, > + short *__restrict a, > + short *__restrict pred) > +{ > + for (int i = 0; i < 1024; ++i) > + r[i] = pred[i] != 0 ? ~(a[i]) : a[i]; > +} > + > +/* { dg-final { scan-assembler-times {\tnot\tz[0-9]+\.h, p[0-7]/m,} 1 } } */ > + > +/* { dg-final { scan-assembler-not {\teor\tz} } } */ > +/* { dg-final { scan-assembler-not {\tmov\tz[0-9]+\.h, p[0-7]/m, #-1} } } */ > + > +/* { dg-final { scan-tree-dump-times ".COND_NOT " 1 "optimized" } } */