Add support for vector conitional not
Checks
Commit Message
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
Comments
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" } } */
On Mon, Aug 14, 2023 at 2:37 PM Richard Sandiford via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> 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.
Yes that should have been IFN_COND_NOT, when I was converting it to be
explicitly IFN_COND_NOT rather than depending on vec_cond, I had
missed that part of the conversion.
Thanks for noticing that.
>
> LGTM otherwise, but please give Richi 24hrs to comment.
Will do.
Thanks,
Andrew
>
> 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" } } */
On Mon, Aug 14, 2023 at 2:54 PM Andrew Pinski <pinskia@gmail.com> wrote:
>
> On Mon, Aug 14, 2023 at 2:37 PM Richard Sandiford via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
> >
> > 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.
>
> Yes that should have been IFN_COND_NOT, when I was converting it to be
> explicitly IFN_COND_NOT rather than depending on vec_cond, I had
> missed that part of the conversion.
> Thanks for noticing that.
>
> >
> > LGTM otherwise, but please give Richi 24hrs to comment.
>
> Will do.
Committed now with the above change (bootstrapped and tested to make
sure it worked after the change).
Thanks,
Andrew
>
> Thanks,
> Andrew
>
>
> >
> > 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" } } */
@@ -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)
@@ -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))))
+
/* Simplify:
a = a1 op a2
@@ -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")
new file mode 100644
@@ -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" } } */