On 10/10/26 7:59 AM, Uttam Bhadauriya wrote:
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]>
So have you verified this test produces the expected output?  LLM review flagged the test as potentially incorrect and my own experimentation confirms that.  I get this in the .optimized dump on riscv64-elf using -O2:

jlaw@x11-dpi:~/test/obj/rv/gcc/gcc$ grep 214 j*.optimized
 _1 = a_2(D) == -2147483648;
 _1 = a_2(D) != -2147483648;
 _1 = a_2(D) == 2147483648;
 _1 = a_2(D) != 2147483648;



That won't match your test scans:
+/* { dg-final { scan-tree-dump-times " == -2147483648" 2 "optimized" { target { ilp32 || lp64 } } } } */ +/* { dg-final { scan-tree-dump-times " == 2147483648" 2 "optimized" { target { ilp32 || lp64 } } } } */

I'm also a bit unsure on your target selectors.  Is { target int32 } sufficient?    Your test doesn't do anything with other types such as longs or pointers.

---
  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
What's the purpose of the precision test > 1?  I *think* the transformation works for single bit boolean types.

I think you're basically on the right track, but we definitely need a V2 and I'd like Andrea to have a chance to chime in as she's better with match.pd than I am.

Jeff

Reply via email to