From 2c92551405bc8616f456e5cbc696ab0292c7ff00 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 14 Dec 2023 12:06:59 +0100 Subject: [PATCH] match.pd: Simplify (t * u) / (t * v) [PR112994] 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. 2023-12-14 Jakub Jelinek 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 | 18 +++++++++++++++++- gcc/testsuite/gcc.dg/tree-ssa/pr112994-2.c | 15 +++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr112994-2.c diff --git a/gcc/match.pd b/gcc/match.pd index 59548286555..562880aee4c 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -961,7 +961,23 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (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 (for div (trunc_div exact_div) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr112994-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr112994-2.c new file mode 100644 index 00000000000..f78a72f7850 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr112994-2.c @@ -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); }