On Wed, 6 Mar 2024, Jakub Jelinek wrote: > Hi! > > The following patch attempts to fix an optimization regression through > adding a simple simplification. We already have the > /* (m1 CMP m2) * d -> (m1 CMP m2) ? d : 0 */ > (if (!canonicalize_math_p ()) > (for cmp (tcc_comparison) > (simplify > (mult:c (convert (cmp@0 @1 @2)) @3) > (if (INTEGRAL_TYPE_P (type) > && INTEGRAL_TYPE_P (TREE_TYPE (@0))) > (cond @0 @3 { build_zero_cst (type); }))) > optimization which otherwise triggers during the a * !a multiplication, > but that is done only late and we aren't able through range assumptions > optimize it yet anyway. > > The patch adds a specific simplification for it. > If a is zero, then a * !a will be 0 * 1 (or for signed 1-bit 0 * -1) > and so 0. > If a is non-zero, then a * !a will be a * 0 and so again 0. > > I had to use a hack, TREE_TYPE (@0) in the condition as opposed to > using just type, because otherwise I get a false positive warning. > The captures parameter is marked ARG_UNUSED in gimple, but not in > generic and we end up with > tree > generic_simplify_168 (location_t ARG_UNUSED (loc), const tree ARG_UNUSED > (type), > tree ARG_UNUSED (_p0), tree ARG_UNUSED (_p1), tree *captures) > { > const bool debug_dump = dump_file && (dump_flags & TDF_FOLDING); > if (INTEGRAL_TYPE_P (type) > ) > { > if (TREE_SIDE_EFFECTS (_p1)) goto next_after_fail309; > if (UNLIKELY (!dbg_cnt (match))) goto next_after_fail309; > { > tree _r; > _r = build_zero_cst (type); > if (UNLIKELY (debug_dump)) generic_dump_logs ("match.pd", 216, > __FILE__, __LINE__, true); > return _r; > } > next_after_fail309:; > } > return NULL_TREE; > } > there. I've looked at similar cases and in > (simplify > (mod @0 integer_onep) > { build_zero_cst (type); }) > case we don't get captures unused because it is used a single time > and therefore evaluate it for side-effects instead of punting on them, > and in > (pointer_diff @@0 @0) > { build_zero_cst (type); }) > we do so as well. Though, using @@0 instead of @0 on either operand > of this simplification doesn't help. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK, though feel free to add ARG_UNUSED to 'captures' as well. 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). Thanks, Richard. > 2024-03-06 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/114009 > * match.pd (a * !a -> 0): New simplification. > > * gcc.dg/tree-ssa/pr114009.c: New test. > > --- gcc/match.pd.jj 2024-03-01 14:56:42.442810053 +0100 > +++ gcc/match.pd 2024-03-05 22:53:25.202579435 +0100 > @@ -1219,6 +1219,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > && 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))) > + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))) > + { 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-05 > 15:18:41.274541636 +0100 > +++ gcc/testsuite/gcc.dg/tree-ssa/pr114009.c 2024-03-05 15:16:09.056589675 > +0100 > @@ -0,0 +1,24 @@ > +/* PR tree-optimization/114009 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > +/* { dg-final { scan-tree-dump-times " return 0;" 3 "optimized" } } */ > + > +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; > +} > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)