The single_use restriction on the X +- C1 CMP C2 -> X CMP C2 -+ C1
simplification (for eq/ne) prevents folding patterns like (++*a == 1)
into (*a == 0) when the defining SSA value has multiple uses.

Comparing against zero is cheaper on most targets (beqz on RISC-V,
cbz on AArch64), so the transform is profitable even when the
defining SSA has multiple uses.  Relax single_use when the folded
comparison constant is zero.

For example, given:
  _1 = *a;
  _2 = _1 + 1;
  *a = _2;
  if (_2 == 1)

match.pd now produces:
  if (_1 == 0)

which generates beqz/cbz instead of li+beq/cmp+b.eq.

This is a partial fix towards the issue described in PR120283.

gcc/ChangeLog:

        * match.pd: Relax single_use for eq/ne when folded constant
        is zero.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/forwprop-pre-incr-cmp.c: New test.

diff --git a/gcc/match.pd b/gcc/match.pd
index 7f16fd4e0814..c8601ea6878a 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -9864,7 +9864,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
      (if (TREE_OVERFLOW (res)
          && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
       { constant_boolean_node (cmp == NE_EXPR, type); }
-      (if (single_use (@3))
+      (if (single_use (@3) || wi::to_wide (res) == 0)
        (cmp @0 { TREE_OVERFLOW (res)
                 ? drop_tree_overflow (res) : res; }))))))))
 (for cmp (lt le gt ge)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-pre-incr-cmp.c 
b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-pre-incr-cmp.c
new file mode 100644
index 000000000000..cfa6afe304c9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-pre-incr-cmp.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-forwprop2" } */
+
+/* Verify that the X +- C1 CMP C2 -> X CMP C2 -+ C1 pattern fires
+   when the folded constant is zero, even without single use.
+   PR tree-optimization/120283.  */
+
+void g ();
+
+/* Unsigned EQ: ++*a == 1 -> *a == 0.  */
+void f1 (unsigned int *a)
+{
+  if (++*a == 1)
+    g ();
+}
+
+/* Unsigned NE: ++*a != 1 -> *a != 0.  */
+void f2 (unsigned int *a)
+{
+  if (++*a != 1)
+    g ();
+}
+
+/* Unsigned EQ with addend > 1: (*a += 3) == 3 -> *a == 0.  */
+void f3 (unsigned int *a)
+{
+  if ((*a += 3) == 3)
+    g ();
+}
+
+/* Positive: f1, f3 should fold to == 0, f2 should fold to != 0.  */
+/* { dg-final { scan-tree-dump-times "== 0" 2 "forwprop2" } } */
+/* { dg-final { scan-tree-dump-times "!= 0" 1 "forwprop2" } } */
-- 
2.34.1

Reply via email to