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