Hello !

I am suggesting a patch for PR126627 / tree - optimization via this email.

The expression '(a & -a) < 0' on a signed integer (or an unsigned
integer cast to a signed integer) is equivalent to checking if `a` is
the minimum signed value for its type. The only value where the lowest
set bit is the sign bit is 'INT_MIN'.

This patch introduces a simplification in `match.pd` to optimize this
pattern into a direct equality check ('a == INT_MIN' and 'a !=
INT_MIN').

It also explicitly guards the transformation with
'!TYPE_OVERFLOW_TRAPS' since '-a' could otherwise trap for 'INT_MIN',
which would incorrectly be removed if folded.

This patch has been locally built and regression tested on
'x86_64-pc-linux-gnu' ( As per the target shown in make file ).

OS : Windows 11, Version : 23H2, with WSL Ubuntu 22.04.05 LTS

Hopefully this is as per the expectations of the maintainers, this
would be my first contribution in the GCC toolchain so apologies for
any mistakes.

Kind regards
Uttam Bhadauriya
P.S.: Please check the patch details below.

>From 31ff0cbfe3481c58956c6609bb09c10444978737 Mon Sep 17 00:00:00 2001
From: Uttam Singh Bhadauriya <[email protected]>
Date: Sat, 10 Oct 2026 18:57:38 +0530
Subject: [PATCH] tree-optimization: Simplify (a & -a) < 0 to a == INT_MIN
 [PR126627]

The expression (a & -a) < 0 on a signed integer (or an unsigned integer cast
to a signed integer) is equivalent to checking if a is the minimum signed
value for its type. The only value where the lowest set bit is the sign bit
is INT_MIN. This patch introduces a simplification in match.pd to optimize
this pattern into a direct equality check.

It also guards the transformation with !TYPE_OVERFLOW_TRAPS since -a could
otherwise trap for INT_MIN, which would incorrectly be removed.

gcc/ChangeLog:

PR tree-optimization/126627
* match.pd: Simplify (a & -a) < 0 to a == INT_MIN and
(a & -a) >= 0 to a != INT_MIN.

gcc/testsuite/ChangeLog:

PR tree-optimization/126627
* gcc.dg/tree-ssa/pr126627.c: New test.

Signed-off-by: Uttam Singh Bhadauriya <[email protected]>
---
 gcc/match.pd                             | 18 +++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr126627.c | 25 ++++++++++++++++++++++++
 2 files changed, 43 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr126627.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 0a4f7b718b4..5cc08f36e9b 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -9269,6 +9269,24 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1)))
    (cmp @0 (convert @1)))))

+/* (a & -a) < 0 -> a == INT_MIN
+   (a & -a) >= 0 -> a != INT_MIN  */
+(for cmp (lt ge)
+     eqcmp (eq ne)
+ (simplify
+  (cmp (convert?@0 (bit_and:c (negate @1) @1)) integer_zerop)
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+       && INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       && TYPE_PRECISION (TREE_TYPE (@1)) > 1
+       && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1))
+       && !TYPE_UNSIGNED (TREE_TYPE (@0))
+       && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@1)))
+   (with {
+      unsigned int prec = TYPE_PRECISION (TREE_TYPE (@1));
+      wide_int min = wi::set_bit_in_zero (prec - 1, prec);
+    }
+    (eqcmp @1 { wide_int_to_tree (TREE_TYPE (@1), min); })))))
+
 /* Non-equality compare simplifications from fold_binary  */
 (for cmp (lt gt le ge)
  /* Comparisons with the highest or lowest possible integer of
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126627.c
b/gcc/testsuite/gcc.dg/tree-ssa/pr126627.c
new file mode 100644
index 00000000000..07c91bd7862
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126627.c
@@ -0,0 +1,25 @@
+/* PR tree-optimization/126627 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int test1(int a) {
+    return (a & -a) < 0;
+}
+
+int test2(int a) {
+    return (a & -a) >= 0;
+}
+
+int test3(unsigned int a) {
+    return (int)(a & -a) < 0;
+}
+
+int test4(unsigned int a) {
+    return (int)(a & -a) >= 0;
+}
+
+/* { dg-final { scan-tree-dump-not " & " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " < 0" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " >= 0" "optimized" } } */
+/* { dg-final { scan-tree-dump-times " == -2147483648" 2 "optimized"
{ target { ilp32 || lp64 } } } } */
+/* { dg-final { scan-tree-dump-times " == 2147483648" 2 "optimized" {
target { ilp32 || lp64 } } } } */
-- 
2.34.1

Reply via email to