Message ID | ZXqwuCz6am3WB+9c@tucnak |
---|---|
State | New |
Headers | show |
Series | match.pd: Simplify (t * u) / (t * v) [PR112994] | expand |
> Am 14.12.2023 um 08:37 schrieb Jakub Jelinek <jakub@redhat.com>: > > Hi! > > On top of the previously posted patch, this simplifies say (x * 16) / (x * 4) > into 4. Unlike the previous pattern, this is something we didn't fold > previously on GENERIC, so I think it shouldn't be all wrapped with #if > GIMPLE. The question whether there should be fold_overflow_warning for the > TYPE_OVERFLOW_UNDEFINED case remains. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk > (with or without fold_overflow_warning)? Ok without the warning. Richard > 2023-12-13 Jakub Jelinek <jakub@redhat.com> > > PR tree-optimization/112994 > * match.pd ((t * u) / (t * v) -> (u / v)): New simplification. > > * gcc.dg/tree-ssa/pr112994-2.c: New test. > > --- gcc/match.pd.jj 2023-12-13 18:43:51.277839661 +0100 > +++ gcc/match.pd 2023-12-13 18:43:45.891913683 +0100 > @@ -962,6 +960,23 @@ (define_operator_list SYNC_FETCH_AND_AND > && range_op_handler (MULT_EXPR).overflow_free_p (vr0, vr1)) > (mult @0 (div! @1 @2)))) > #endif > + ))) > + /* Simplify (t * u) / (t * v) -> (u / v) if u is multiple of v. */ > + (simplify > + (div (mult @0 INTEGER_CST@1) (mult @0 INTEGER_CST@2)) > + (if (INTEGRAL_TYPE_P (type) > + && wi::multiple_of_p (wi::to_widest (@1), wi::to_widest (@2), SIGNED)) > + (if (TYPE_OVERFLOW_UNDEFINED (type) && !TYPE_OVERFLOW_SANITIZED (type)) > + (div @1 @2) > +#if GIMPLE > + (with {value_range vr0, vr1, vr2;} > + (if (get_range_query (cfun)->range_of_expr (vr0, @0) > + && get_range_query (cfun)->range_of_expr (vr1, @1) > + && get_range_query (cfun)->range_of_expr (vr2, @2) > + && range_op_handler (MULT_EXPR).overflow_free_p (vr0, vr1) > + && range_op_handler (MULT_EXPR).overflow_free_p (vr0, vr2)) > + (div @1 @2))) > +#endif > )))) > > #if GIMPLE > --- gcc/testsuite/gcc.dg/tree-ssa/pr112994-2.c.jj 2023-12-13 19:07:20.882475735 +0100 > +++ gcc/testsuite/gcc.dg/tree-ssa/pr112994-2.c 2023-12-13 19:07:02.597726855 +0100 > @@ -0,0 +1,15 @@ > +/* PR tree-optimization/112994 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > +/* { dg-final { scan-tree-dump-times "return 2;" 3 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "return 7;" 3 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "return -7;" 2 "optimized" } } */ > + > +int f1 (int x) { return (x * 4) / (x * 2); } > +int f2 (int x) { return (x * 56) / (x * 8); } > +int f3 (int x) { return (x * 56) / (x * -8); } > +int f4 (int x) { int y = x * 4; return y / (x * 2); } > +int f5 (int x) { int y = x * 56; return y / (x * 8); } > +int f6 (int x) { int y = x * 56; return y / (x * -8); } > +unsigned f7 (unsigned x) { if (x > ~0U / 4) __builtin_unreachable (); unsigned y = x * 4; return y / (x * 2); } > +unsigned f8 (unsigned x) { if (x > ~0U / 56) __builtin_unreachable (); unsigned y = x * 56; return y / (x * 8); } > > Jakub >
--- gcc/match.pd.jj 2023-12-13 18:43:51.277839661 +0100 +++ gcc/match.pd 2023-12-13 18:43:45.891913683 +0100 @@ -962,6 +960,23 @@ (define_operator_list SYNC_FETCH_AND_AND && range_op_handler (MULT_EXPR).overflow_free_p (vr0, vr1)) (mult @0 (div! @1 @2)))) #endif + ))) + /* Simplify (t * u) / (t * v) -> (u / v) if u is multiple of v. */ + (simplify + (div (mult @0 INTEGER_CST@1) (mult @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (type) + && wi::multiple_of_p (wi::to_widest (@1), wi::to_widest (@2), SIGNED)) + (if (TYPE_OVERFLOW_UNDEFINED (type) && !TYPE_OVERFLOW_SANITIZED (type)) + (div @1 @2) +#if GIMPLE + (with {value_range vr0, vr1, vr2;} + (if (get_range_query (cfun)->range_of_expr (vr0, @0) + && get_range_query (cfun)->range_of_expr (vr1, @1) + && get_range_query (cfun)->range_of_expr (vr2, @2) + && range_op_handler (MULT_EXPR).overflow_free_p (vr0, vr1) + && range_op_handler (MULT_EXPR).overflow_free_p (vr0, vr2)) + (div @1 @2))) +#endif )))) #if GIMPLE --- gcc/testsuite/gcc.dg/tree-ssa/pr112994-2.c.jj 2023-12-13 19:07:20.882475735 +0100 +++ gcc/testsuite/gcc.dg/tree-ssa/pr112994-2.c 2023-12-13 19:07:02.597726855 +0100 @@ -0,0 +1,15 @@ +/* PR tree-optimization/112994 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "return 2;" 3 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 7;" 3 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return -7;" 2 "optimized" } } */ + +int f1 (int x) { return (x * 4) / (x * 2); } +int f2 (int x) { return (x * 56) / (x * 8); } +int f3 (int x) { return (x * 56) / (x * -8); } +int f4 (int x) { int y = x * 4; return y / (x * 2); } +int f5 (int x) { int y = x * 56; return y / (x * 8); } +int f6 (int x) { int y = x * 56; return y / (x * -8); } +unsigned f7 (unsigned x) { if (x > ~0U / 4) __builtin_unreachable (); unsigned y = x * 4; return y / (x * 2); } +unsigned f8 (unsigned x) { if (x > ~0U / 56) __builtin_unreachable (); unsigned y = x * 56; return y / (x * 8); }