[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" } } */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.