The patch makes the following simplifications:
((X - 1) & ~X) < 0 -> X == 0
((X - 1) & ~X) >= 0 -> X != 0

On x86, the number of instructions is reduced from 4 to 3,
but on platforms like RISC-V, it reduces to a single instruction.

Bootstrapped and tested on x86-linux-gnu with no regressions.

gcc/ChangeLog:

        * match.pd: New pattern.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/fold_neg_and_zero_cmp.c: New test.


CONFIDENTIALITY: The contents of this e-mail are confidential and intended only 
for the above addressee(s). If you are not the intended recipient, or the 
person responsible for delivering it to the intended recipient, copying or 
delivering it to anyone else or using it in any unauthorized manner is 
prohibited and may be unlawful. If you receive this e-mail by mistake, please 
notify the sender and the systems administrator at straym...@rt-rk.com 
immediately.
The patch makes the following simplifications:
((X - 1) & ~X) < 0 -> X == 0
((X - 1) & ~X) >= 0 -> X != 0

On x86, the number of instructions is reduced from 4 to 3,
but on platforms like RISC-V, it reduces to a single instruction.

Bootstrapped and tested on x86-linux-gnu with no regressions.

gcc/ChangeLog:

	* match.pd: New pattern.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/fold_neg_and_zero_cmp.c: New test.

---
 gcc/match.pd                                  | 14 ++++++++++
 .../gcc.dg/tree-ssa/fold_neg_and_zero_cmp.c   | 28 +++++++++++++++++++
 2 files changed, 42 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fold_neg_and_zero_cmp.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 6d95ceaa194..1a92acda8ab 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2245,6 +2245,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (if (bitwise_equal_p (@0, @3))
    (convert (bit_ior (bit_and @1 (convert @2)) (convert @0))))))
 
+/* Fold ((X - 1) & ~X) </>= 0 into X ==/!= 0.  */
+(for cmp (lt ge)
+     eqne (eq ne)
+ (simplify
+ (cmp:c
+   (bit_and:c
+     (plus @0 integer_minus_onep)
+     (bit_not @0))
+   integer_zerop)
+ (if (!TYPE_UNSIGNED (TREE_TYPE (@0))
+      && INTEGRAL_TYPE_P (type)
+      && INTEGRAL_TYPE_P (TREE_TYPE (@0)))
+  (eqne @0 { build_zero_cst (TREE_TYPE (@0)); }))))
+
 /* (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) */
 (simplify
   (bit_and (bit_ior @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fold_neg_and_zero_cmp.c b/gcc/testsuite/gcc.dg/tree-ssa/fold_neg_and_zero_cmp.c
new file mode 100644
index 00000000000..e9400acf5f3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fold_neg_and_zero_cmp.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized-raw" } */
+
+int foo1_1(int a)
+{
+    return ((a - 1) & ~a) < 0;
+}
+
+int foo1_2(int a)
+{
+    return (((a - 1) & ~a) >> 31) != 0;
+}
+
+int foo2_1(int a)
+{
+    return ((a - 1) & ~a) >= 0;
+}
+
+int foo2_2(int a)
+{
+    return (((a - 1) & ~a) >> 31) == 0;
+}
+
+/* { dg-final { scan-tree-dump-not   "bit_and_expr, "   "optimized" } } */
+/* { dg-final { scan-tree-dump-not   "bit_not_expr, "   "optimized" } } */
+/* { dg-final { scan-tree-dump-times   "eq_expr, "  2  "optimized" } } */
+/* { dg-final { scan-tree-dump-times   "ne_expr, "  2  "optimized" } } */
+
-- 
2.43.0

Reply via email to