On Tue, Aug 13, 2024 at 6:31 AM Andrew Pinski <quic_apin...@quicinc.com> wrote:
>
> This adds a pattern to convert `(a ? b : 0) | (a ? 0 : c)` into `a ? b : c`
> which is simplier. It adds both for cond and vec_cond; even though vec_cond is
> handled via a different pattern currently but requires extra steps for 
> matching
> so this should be slightly faster.
>
> Also handle it for xor and plus too since those can be handled the same way.
>
> Bootstrapped and tested on x86_64-linux-gnu with no regressions.

OK.

>         PR tree-optimization/103660
>
> gcc/ChangeLog:
>
>         * match.pd (`(a ? b : 0) | (a ? 0 : c)`): New pattern.
>
> gcc/testsuite/ChangeLog:
>
>         * g++.dg/tree-ssa/pr103660-4.C: New test.
>         * gcc.dg/tree-ssa/pr103660-4.c: New test.
>
> Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> ---
>  gcc/match.pd                               | 10 +++++
>  gcc/testsuite/g++.dg/tree-ssa/pr103660-4.C | 35 ++++++++++++++++++
>  gcc/testsuite/gcc.dg/tree-ssa/pr103660-4.c | 43 ++++++++++++++++++++++
>  3 files changed, 88 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr103660-4.C
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr103660-4.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index b43ceb6def0..65a3aae2243 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -2339,6 +2339,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>   (if (INTEGRAL_TYPE_P (type))
>    (bit_and @0 @1)))
>
> +/* Fold `(a ? b : 0) | (a ? 0 : c)` into (a ? b : c).
> +    Handle also ^ and + in replacement of `|`. */
> +(for cnd (cond vec_cond)
> + (for op (bit_ior bit_xor plus)
> +  (simplify
> +   (op:c
> +    (cnd:s @0 @00 integer_zerop)
> +    (cnd:s @0 integer_zerop @01))
> +   (cnd @0 @00 @01))))
> +
>  (for cmp (tcc_comparison)
>       icmp (inverted_tcc_comparison)
>   /* Fold (((a < b) & c) | ((a >= b) & d)) into (a < b ? c : d) & 1.  */
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr103660-4.C 
> b/gcc/testsuite/g++.dg/tree-ssa/pr103660-4.C
> new file mode 100644
> index 00000000000..47727f86e24
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/tree-ssa/pr103660-4.C
> @@ -0,0 +1,35 @@
> +/* PR tree-optimization/103660 */
> +/* Vector type version. */
> +/* { dg-do compile } */
> +/* { dg-options "-O1 -fdump-tree-forwprop2-raw -Wno-psabi" } */
> +
> +typedef int v4si __attribute((__vector_size__(4 * sizeof(int))));
> +#define funcs(OP,n)                    \
> +v4si min_##n(v4si a, v4si b) {         \
> +  v4si t = {0,0,0,0};                  \
> +  v4si X = a < b ? a : t;              \
> +  v4si Y = a < b ? t : b;              \
> +  return (X OP Y);                     \
> +}                                      \
> +v4si f_##n(v4si a, v4si b,             \
> +          v4si c, v4si d) {            \
> +  v4si t = {0,0,0,0};                  \
> +  v4si X = a < b ? c : t;              \
> +  v4si Y = a < b ? t : d;              \
> +  return (X OP Y);                     \
> +}
> +
> +
> +funcs(|, ior)
> +funcs(^, xor)
> +funcs(+, plus)
> +
> +/* min_ior/min_xor/min_plus should produce min<a,b> or `a < b ? a : b` 
> depending on if the target
> +   supports min on the vector type or not. */
> +/* f_ior/f_xor/f_plus should produce (a < b) ? c : d */
> +/* { dg-final { scan-tree-dump-not   "bit_xor_expr, "     "forwprop2" } } */
> +/* { dg-final { scan-tree-dump-not   "bit_ior_expr, "     "forwprop2" } } */
> +/* { dg-final { scan-tree-dump-not   "plus_expr, "        "forwprop2" } } */
> +/* { dg-final { scan-tree-dump-not   "bit_ior_expr, "     "forwprop2" } } */
> +/* { dg-final { scan-tree-dump-times "(?:lt_expr|min_expr), "        6 
> "forwprop2" } } */
> +/* { dg-final { scan-tree-dump-times "(?:vec_cond_expr|min_expr), "  6 
> "forwprop2" } } */
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr103660-4.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/pr103660-4.c
> new file mode 100644
> index 00000000000..26c956fdcec
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr103660-4.c
> @@ -0,0 +1,43 @@
> +/* PR tree-optimization/103660 */
> +/* { dg-do compile } */
> +/* { dg-options "-O1 -fgimple -fdump-tree-forwprop1-raw" } */
> +
> +#define funcs(OP,n)            \
> +__GIMPLE()                     \
> +int min_##n(int a, int b) {    \
> +  _Bool X;                     \
> +  int t;                       \
> +  int t1;                      \
> +  int t2;                      \
> +  X = a < b;                   \
> +  t1 = X ? a : 0;              \
> +  t2 = X ? 0 : b;              \
> +  t = t1 OP t2;                        \
> +  return t;                    \
> +}                              \
> +__GIMPLE()                     \
> +int f_##n(int a, int b, int c, \
> +        int d) {               \
> +  _Bool X;                     \
> +  int t;                       \
> +  int t1;                      \
> +  int t2;                      \
> +  X = a < b;                   \
> +  t1 = X ? c : 0;              \
> +  t2 = X ? 0 : d;              \
> +  t = t1 OP t2;                        \
> +  return t;                    \
> +}
> +
> +funcs(|, ior)
> +funcs(^, xor)
> +funcs(+, plus)
> +
> +/* min_i/min_ioror/min_plus should produce min<a,b> */
> +/* f_xor/f_ior/f_plus should produce (a < b) ? c : d */
> +/* { dg-final { scan-tree-dump-not   "bit_xor_expr, " "forwprop1" } } */
> +/* { dg-final { scan-tree-dump-not   "bit_ior_expr, " "forwprop1" } } */
> +/* { dg-final { scan-tree-dump-not   "plus_expr, "    "forwprop1" } } */
> +/* { dg-final { scan-tree-dump-times "min_expr, "   3 "forwprop1" } } */
> +/* { dg-final { scan-tree-dump-times "lt_expr, "    3 "forwprop1" } } */
> +/* { dg-final { scan-tree-dump-times "cond_expr, "  3 "forwprop1" } } */
> --
> 2.43.0
>

Reply via email to