[gcc r17-3295] match.pd: fold the inequality spelling of divisibility
Kyrylo Tkachov via Gcc-cvs <[email protected]>
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:23797f88d1635d38ce68c8d180a0f90a1ea34740 commit r17-3295-g23797f88d1635d38ce68c8d180a0f90a1ea34740 Author: Kyrylo Tkachov <[email protected]> Date: Mon Aug 10 20:41:36 2026 +0200 match.pd: fold the inequality spelling of divisibility GCC folds: x / y * y == x to: x % y == 0 Apply the same simplification to inequality. int divisible_by_3 (unsigned int x) { return x / 3 * 3 != x; } aarch64 -O2: before: divisible_by_3: mov w1, 43691 movk w1, 0xaaaa, lsl 16 umull x1, w0, w1 lsr x1, x1, 33 add w1, w1, w1, lsl 1 cmp w1, w0 cset w0, ne ret after: divisible_by_3: mov w1, 43691 movk w1, 0xaaaa, lsl 16 mul w0, w0, w1 mov w1, 1431655765 cmp w0, w1 cset w0, hi ret Bootstrapped and tested on aarch64-none-linux-gnu. gcc/ChangeLog: * match.pd (x / y * y == x): Extend to inequality. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/divmul-mod-1.c: New test. Signed-off-by: Kyrylo Tkachov <[email protected]> Diff: --- gcc/match.pd | 9 ++++--- gcc/testsuite/gcc.dg/tree-ssa/divmul-mod-1.c | 38 ++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/gcc/match.pd b/gcc/match.pd index 26cb2c9e155b..02684d8a302b 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -6033,16 +6033,17 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (plus:c (mult:c (div @0 @1) @1) (mod @0 @1)) @0)) -/* x / y * y == x -> x % y == 0. */ -(simplify - (eq:c (mult:c (trunc_div:s @0 @1) @1) @0) +/* x / y * y == x -> x % y == 0, and likewise for !=. */ +(for cmp (eq ne) + (simplify + (cmp:c (mult:c (trunc_div:s @0 @1) @1) @0) (if (TREE_CODE (TREE_TYPE (@0)) != COMPLEX_TYPE && (!VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (@0))) || !target_supports_op_p (TREE_TYPE (@0), TRUNC_DIV_EXPR, optab_vector) || target_supports_op_p (TREE_TYPE (@0), TRUNC_MOD_EXPR, optab_vector))) - (eq (trunc_mod @0 @1) { build_zero_cst (TREE_TYPE (@0)); }))) + (cmp (trunc_mod @0 @1) { build_zero_cst (TREE_TYPE (@0)); })))) /* ((X /[ex] C1) +- C2) * (C1 * C3) --> (X * C3) +- (C1 * C2 * C3). */ (for op (plus minus) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/divmul-mod-1.c b/gcc/testsuite/gcc.dg/tree-ssa/divmul-mod-1.c new file mode 100644 index 000000000000..f65a28d23355 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/divmul-mod-1.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +typedef int v4si __attribute__ ((vector_size (16))); +typedef unsigned int v4ui __attribute__ ((vector_size (16))); + +int +eq (unsigned int a, unsigned int b) +{ + return a / b * b == a; +} + +int +ne (unsigned int a, unsigned int b) +{ + return a / b * b != a; +} + +int +nes (int a, int b) +{ + return a / b * b != a; +} + +v4si +veq (v4ui a, v4ui b) +{ + return a / b * b == a; +} + +v4si +vne (v4ui a, v4ui b) +{ + return a / b * b != a; +} + +/* { dg-final { scan-tree-dump-not " \\* " "optimized" } } */ +/* { dg-final { scan-tree-dump " % " "optimized" } } */