diff options
author | Jakub Jelinek <jakub@redhat.com> | 2023-12-14 12:06:59 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2023-12-14 12:06:59 +0100 |
commit | 2c92551405bc8616f456e5cbc696ab0292c7ff00 (patch) | |
tree | 5e9678c8c6af5d2262b2385d77e520c46744117c | |
parent | 90c9403f89d3c55512ae83dd20e2023c2e4430f4 (diff) | |
download | gcc-2c92551405bc8616f456e5cbc696ab0292c7ff00.zip gcc-2c92551405bc8616f456e5cbc696ab0292c7ff00.tar.gz gcc-2c92551405bc8616f456e5cbc696ab0292c7ff00.tar.bz2 |
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 <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.
-rw-r--r-- | gcc/match.pd | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr112994-2.c | 15 |
2 files changed, 32 insertions, 1 deletions
diff --git a/gcc/match.pd b/gcc/match.pd index 5954828..562880a 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 0000000..f78a72f --- /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); } |