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? 2024-03-06 Jakub Jelinek <ja...@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