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 >