[gcc r17-3234] match: Fix recent pattern for signed integer overflow dealing with - [PR126418]

Andrea Pinski via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:610f1166538ad2e637c913be78b074100270cc5c

commit r17-3234-g610f1166538ad2e637c913be78b074100270cc5c
Author: Andrea Pinski <[email protected]>
Date:   Mon Jul 27 20:11:33 2026 -0700

    match: Fix recent pattern for signed integer overflow dealing with - [PR126418]
    
    A recent match patterns were added that introduce signed integer overflow where
    there was none before.  `cmp + (-cmp ^ x)` has no signed integer overflow when
    x is INT_MIN when cmp is 0. This gets translated into cmp ? -x : x.
    But this has now introduced an signed integer overflow for INT_MIN.
    The fix is to use unsigned type for the negative.
    
    Bootstrapped and tested on x86_64-linux-gnu.
    
    Changes since v1:
    * v2: Remove the abs patterns since a signed integer overflow would have happened anyways.
    
            PR tree-optimization/126418
    
    gcc/ChangeLog:
    
            * match.pd (`(A ^ -cmp) + cmp`): Cast to unsigned type
            before taking the negative.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/tree-ssa/pr126418-1.c: New test.
    
    Signed-off-by: Andrea Pinski <[email protected]>

Diff:
---
 gcc/match.pd                               |  8 +++++++-
 gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c | 11 +++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index eee44365ea37..3f476cc4baad 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4987,7 +4987,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (if (INTEGRAL_TYPE_P (type)
       && !TYPE_SATURATING (type)
       && (GIMPLE || !TREE_SIDE_EFFECTS (@0)))
-  (cond (convert:boolean_type_node @1) (negate @0) @0)))
+  /* Do the negate in unsigned type always; otherwise
+     we would be introducing an overflow.  */
+  (with { tree utype = unsigned_type_for (type); }
+   (cond
+    (convert:boolean_type_node @1)
+    (convert:type (negate (convert:utype @0)))
+    @0))))
 
 /* Transform A & (B*cmp) into (A&B)*cmp.  */
 (simplify
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c
new file mode 100644
index 000000000000..3714069b43f8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-forwprop1" } */
+
+int f_cmp_gt_commuted(int x, int y)
+{
+  int cmp = x > y;
+  return cmp + (-cmp ^ x);
+}
+
+/* { dg-final { scan-tree-dump-times "\\(unsigned int\\) " 1 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times "\\(int\\) " 1 "forwprop1" } } */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.