https://gcc.gnu.org/g:e2e798b86074010a8d5da16ce0b199fcec70a50e

commit r15-4601-ge2e798b86074010a8d5da16ce0b199fcec70a50e
Author: Richard Sandiford <richard.sandif...@arm.com>
Date:   Thu Oct 24 14:22:31 2024 +0100

    Use get_nonzero_bits to simplify trunc_div to exact_div
    
    There are a limited number of existing rules that benefit from
    knowing that a division is exact.  Later patches will add more.
    
    gcc/
            * match.pd: Simplify X / (1 << C) to X /[ex] (1 << C) if the
            low C bits of X are clear
    
    gcc/testsuite/
            * gcc.dg/tree-ssa/cmpexactdiv-6.c: New test.

Diff:
---
 gcc/match.pd                                  |  9 +++++++++
 gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-6.c | 29 +++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index 9024277e5d34..2e7f06ecbe45 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -5456,6 +5456,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
                                                    TYPE_PRECISION (type)), 0))
    (convert @0)))
 
+#if GIMPLE
+/* X / (1 << C) -> X /[ex] (1 << C) if the low C bits of X are clear.  */
+(simplify
+ (trunc_div (with_possible_nonzero_bits2 @0) integer_pow2p@1)
+ (if (INTEGRAL_TYPE_P (type)
+      && !TYPE_UNSIGNED (type)
+      && wi::multiple_of_p (get_nonzero_bits (@0), wi::to_wide (@1), SIGNED))
+  (exact_div @0 @1)))
+#endif
 
 /* (X /[ex] A) * A -> X.  */
 (simplify
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-6.c 
b/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-6.c
new file mode 100644
index 000000000000..82d517b05abd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-6.c
@@ -0,0 +1,29 @@
+/* { dg-options "-O2 -fdump-tree-optimized-raw" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+
+int
+f1 (int x, int y)
+{
+  if ((x & 1) || (y & 1))
+    __builtin_unreachable ();
+  x /= 2;
+  y /= 2;
+  return x < y;
+}
+
+int
+f2 (void *ptr1, void *ptr2, void *ptr3)
+{
+  ptr1 = __builtin_assume_aligned (ptr1, 4);
+  ptr2 = __builtin_assume_aligned (ptr2, 4);
+  ptr3 = __builtin_assume_aligned (ptr3, 4);
+  intptr_t diff1 = (intptr_t) ptr1 - (intptr_t) ptr2;
+  intptr_t diff2 = (intptr_t) ptr1 - (intptr_t) ptr3;
+  diff1 /= 2;
+  diff2 /= 2;
+  return diff1 < diff2;
+}
+
+/* { dg-final { scan-tree-dump-not {<[a-z]*_div_expr,} "optimized" } } */
+/* { dg-final { scan-tree-dump-not {<rshift_expr,} "optimized" } } */

Reply via email to