]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
match: Add `cmp - 1` simplification to `-icmp` [PR110949]
authorAndrew Pinski <quic_apinski@quicinc.com>
Sun, 20 Jul 2025 18:21:08 +0000 (11:21 -0700)
committerAndrew Pinski <quic_apinski@quicinc.com>
Mon, 21 Jul 2025 16:23:05 +0000 (09:23 -0700)
I have seen this a few places though the testcase from PR 95906
is an obvious place where this shows up for sure.
This convert `cmp - 1` into `-icmp` as that form is more useful
in many cases.

Changes since v1:
* v2: Add check for outer type's precision being greater than 1.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/110949
PR tree-optimization/95906

gcc/ChangeLog:

* match.pd (cmp - 1): New pattern.

gcc/testsuite/ChangeLog:

* gcc.dg/tree-ssa/cmp-2.c: New test.
* gcc.dg/tree-ssa/max-bitcmp-1.c: New test.

Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
gcc/match.pd
gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c [new file with mode: 0644]

index 7f84d5149f42ab5b24c58d8ca974c761317cb2fd..4903552c82a63c7392e10a6ebfca9dc17a954ac3 100644 (file)
@@ -7035,6 +7035,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (icmp @0 @1)
     (if (ic == ncmp)
      (ncmp @0 @1)))))
+ /* ((cast)cmp) - 1 -> -(cast)icmp . */
+ (simplify
+  (plus (convert? (cmp@2 @0 @1)) integer_minus_onep)
+  (if (TYPE_PRECISION (type) > 1
+       && INTEGRAL_TYPE_P (TREE_TYPE (@2)) && TYPE_PRECISION (TREE_TYPE (@2)) == 1)
+   /* Comparison inversion may be impossible for trapping math,
+      invert_tree_comparison will tell us.  But we can't use
+      a computed operator in the replacement tree thus we have
+      to play the trick below.  */
+   (with { enum tree_code ic = invert_tree_comparison
+             (cmp, HONOR_NANS (@0));
+           tree cmptype = TREE_TYPE (@2); }
+    (if (ic == icmp)
+     (negate (convert (icmp:cmptype @0 @1)))
+     (if (ic == ncmp)
+      (negate (convert (ncmp:cmptype @0 @1))))))))
  /* The following bits are handled by fold_binary_op_with_conditional_arg.  */
  (simplify
   (ne (cmp@2 @0 @1) integer_zerop)
@@ -11678,4 +11694,4 @@ and,
       && VECTOR_TYPE_P (type)
       && direct_internal_fn_supported_p (IFN_AVG_CEIL, type, OPTIMIZE_FOR_BOTH))
       (IFN_AVG_CEIL @0 @2)))
-#endif
\ No newline at end of file
+#endif
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c b/gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c
new file mode 100644 (file)
index 0000000..9b02901
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-forwprop" } */
+
+/* PR tree-optimization/110949 */
+/* Transform `(cmp) - 1` into `-icmp`. */
+
+int f1(int a)
+{
+  int t = a == 115;
+  return t - 1;
+}
+
+/* { dg-final { scan-tree-dump " != 115" "forwprop1" } } */
+/* { dg-final { scan-tree-dump-not " == 115" "forwprop1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c
new file mode 100644 (file)
index 0000000..81b5a27
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-forwprop -fdump-tree-optimized" } */
+
+/* PR tree-optimization/95906 */
+/* this should become MAX_EXPR<a,b> */
+
+int f2(int a, int b)
+{
+    int cmp = -(a > b);
+    return (cmp & a) | (~cmp & b);
+}
+
+/*  we should not end up with -_2 */
+/*  we should not end up and & nor a `+ -1` */
+/* In optimized we should have a max.  */
+/* { dg-final { scan-tree-dump-not " -\[a-zA-Z_\]" "forwprop1" } } */
+/* { dg-final { scan-tree-dump-not " & " "forwprop1" } } */
+/* { dg-final { scan-tree-dump-not " . -1" "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR " 1 "optimized" } } */