Message ID | ZehsBg/ts9JvUXDl@tucnak |
---|---|
State | New |
Headers | show |
Series | match.pd, v2: Optimize a * !a to 0 [PR114009] | expand |
On Wed, 6 Mar 2024, Jakub Jelinek wrote: > On Wed, Mar 06, 2024 at 11:45:42AM +0100, Richard Biener wrote: > > OK, though feel free to add ARG_UNUSED to 'captures' as well. > > Ok, done below. > > > I think the INTEGRAL_TYPE_P should be redundant - the pattern > > should work for vectors and complex as well (with integer components > > which integer_zerop constrains). > > Guess you're right. I think it is correct as is for both complex and > int vector, while float etc. shouldn't appear there because of the > integer_zerop and pointer because we don't do multiplication on pointer > types. > > That said, it won't really actually match the vector int case actually > emitted, where we have a VEC_COND_EXPR, added those as new patterns. > And it doesn't match what is emitted for _Complex, though I think it > isn't that important to simplify that. > _Complex int > freddy (_Complex int x) > { > return x * !x; > } > > _Complex int > garply (_Complex int x) > { > return x * (x == 0); > } > > results in original in: > return COMPLEX_EXPR <REALPART_EXPR <SAVE_EXPR <x>> == 0 && IMAGPART_EXPR <SAVE_EXPR <x>> == 0, 0> * x; > and > return (x == __complex__ (0, 0) ? __complex__ (1, 0) : __complex__ (0, 0)) * x; > but after gimplification it is already something that is really > too hard to optimize. > > So, is the following still ok if it passes bootstrap/regtest? OK. Thanks, Richard. > 2024-03-06 Jakub Jelinek <jakub@redhat.com> > > PR tree-optimization/114009 > * genmatch.cc (decision_tree::gen): Emit ARG_UNUSED for captures > argument even for GENERIC, not just for GIMPLE. > * match.pd (a * !a -> 0): New simplifications. > > * gcc.dg/tree-ssa/pr114009.c: New test. > > --- gcc/genmatch.cc.jj 2024-02-26 10:09:16.594613314 +0100 > +++ gcc/genmatch.cc 2024-03-06 13:47:35.001458638 +0100 > @@ -4071,7 +4071,7 @@ decision_tree::gen (vec <FILE *> &files, > for (unsigned i = 0; > i < as_a <expr *>(s->s->s->match)->ops.length (); ++i) > fp_decl (f, " tree ARG_UNUSED (_p%d),", i); > - fp_decl (f, " tree *captures"); > + fp_decl (f, " tree *ARG_UNUSED (captures)"); > } > for (unsigned i = 0; i < s->s->s->for_subst_vec.length (); ++i) > { > --- gcc/match.pd.jj 2024-03-06 09:34:36.608271525 +0100 > +++ gcc/match.pd 2024-03-06 13:58:27.400588289 +0100 > @@ -1219,6 +1219,17 @@ (define_operator_list SYNC_FETCH_AND_AND > && tree_nop_conversion_p (type, TREE_TYPE (@1))) > (lshift @0 @2))) > > +/* Fold a * !a into 0. */ > +(simplify > + (mult:c @0 (convert? (eq @0 integer_zerop))) > + { build_zero_cst (type); }) > +(simplify > + (mult:c @0 (vec_cond (eq @0 integer_zerop) @1 integer_zerop)) > + { build_zero_cst (type); }) > +(simplify > + (mult:c @0 (vec_cond (ne @0 integer_zerop) integer_zerop @1)) > + { build_zero_cst (type); }) > + > /* Shifts by precision or greater result in zero. */ > (for shift (lshift rshift) > (simplify > --- gcc/testsuite/gcc.dg/tree-ssa/pr114009.c.jj 2024-03-06 13:44:33.481924326 +0100 > +++ gcc/testsuite/gcc.dg/tree-ssa/pr114009.c 2024-03-06 14:04:09.724918390 +0100 > @@ -0,0 +1,33 @@ > +/* PR tree-optimization/114009 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -Wno-psabi -fdump-tree-forwprop1" } */ > +/* { dg-final { scan-tree-dump-times " return 0;" 3 "forwprop1" } } */ > +/* { dg-final { scan-tree-dump-times " (?:return|<retval> =) { 0, 0, 0, 0 };" 1 "forwprop1" } } */ > + > +int > +foo (int x) > +{ > + x = (x / 2) * 2; > + return (!x) * x; > +} > + > +int > +bar (int x, int y) > +{ > + (void) x; > + return y * !y; > +} > + > +unsigned long long > +baz (unsigned long long x) > +{ > + return (!x) * x; > +} > + > +typedef int V __attribute__((vector_size (4 * sizeof (int)))); > + > +V > +qux (V x) > +{ > + return x * (x == 0); > +} > > > Jakub > >
--- gcc/genmatch.cc.jj 2024-02-26 10:09:16.594613314 +0100 +++ gcc/genmatch.cc 2024-03-06 13:47:35.001458638 +0100 @@ -4071,7 +4071,7 @@ decision_tree::gen (vec <FILE *> &files, for (unsigned i = 0; i < as_a <expr *>(s->s->s->match)->ops.length (); ++i) fp_decl (f, " tree ARG_UNUSED (_p%d),", i); - fp_decl (f, " tree *captures"); + fp_decl (f, " tree *ARG_UNUSED (captures)"); } for (unsigned i = 0; i < s->s->s->for_subst_vec.length (); ++i) { --- gcc/match.pd.jj 2024-03-06 09:34:36.608271525 +0100 +++ gcc/match.pd 2024-03-06 13:58:27.400588289 +0100 @@ -1219,6 +1219,17 @@ (define_operator_list SYNC_FETCH_AND_AND && tree_nop_conversion_p (type, TREE_TYPE (@1))) (lshift @0 @2))) +/* Fold a * !a into 0. */ +(simplify + (mult:c @0 (convert? (eq @0 integer_zerop))) + { build_zero_cst (type); }) +(simplify + (mult:c @0 (vec_cond (eq @0 integer_zerop) @1 integer_zerop)) + { build_zero_cst (type); }) +(simplify + (mult:c @0 (vec_cond (ne @0 integer_zerop) integer_zerop @1)) + { build_zero_cst (type); }) + /* Shifts by precision or greater result in zero. */ (for shift (lshift rshift) (simplify --- gcc/testsuite/gcc.dg/tree-ssa/pr114009.c.jj 2024-03-06 13:44:33.481924326 +0100 +++ gcc/testsuite/gcc.dg/tree-ssa/pr114009.c 2024-03-06 14:04:09.724918390 +0100 @@ -0,0 +1,33 @@ +/* PR tree-optimization/114009 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wno-psabi -fdump-tree-forwprop1" } */ +/* { dg-final { scan-tree-dump-times " return 0;" 3 "forwprop1" } } */ +/* { dg-final { scan-tree-dump-times " (?:return|<retval> =) { 0, 0, 0, 0 };" 1 "forwprop1" } } */ + +int +foo (int x) +{ + x = (x / 2) * 2; + return (!x) * x; +} + +int +bar (int x, int y) +{ + (void) x; + return y * !y; +} + +unsigned long long +baz (unsigned long long x) +{ + return (!x) * x; +} + +typedef int V __attribute__((vector_size (4 * sizeof (int)))); + +V +qux (V x) +{ + return x * (x == 0); +}