https://gcc.gnu.org/g:3744f0db5dc3b9d290b1a7e58e1865fdbfbf8532

commit r17-4949-g3744f0db5dc3b9d290b1a7e58e1865fdbfbf8532
Author: Jakub Jelinek <[email protected]>
Date:   Wed Oct 7 10:14:06 2026 +0200

    match.pd: Check for overflow in x != CST1 ? x + CST2 : CST3 -> x + CST2 
[PR126459]
    
    r17-126 has changed the simplification in a way where it can now
    introduce signed integer overflow into a program which didn't have it 
before,
    e.g. x != (INT_MAX - 3) ? x + 5 : (INT_MIN + 1) when x is int
    doesn't invoke signed integer overflow for x equal to INT_MAX - 3 (it does
    for various other values and for many doesn't), while the simplified
    x + 5 invokes it even for that value.
    
    The following patch fixes it by checking for overflow on the CST1 + CST2
    addition, if TYPE_OVERFLOW_WRAPS or if CST1 + CST2 doesn't overflow,
    it does what it previously did, otherwise rewrites x + CST2 into
    unsigned.
    
    2026-10-07  Jakub Jelinek  <[email protected]>
    
            PR tree-optimization/126459
            * match.pd (x != CST1 ? x + CST2 : CST3 -> x + CST2): If
            CST1 + CST2 overflows and type overflow doesn't wrap,
            simplify into corresponding unsigned addition.
    
            * gcc.dg/torture/pr126459.c: New test.
    
    Reviewed-by: Andrea Pinski <[email protected]>

Diff:
---
 gcc/match.pd                            | 13 ++++++++++---
 gcc/testsuite/gcc.dg/torture/pr126459.c | 34 +++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index 648bda9bf11f..833ee23b8fcc 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -5369,9 +5369,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     tree cst1 = uniform_integer_cst_p (@1);
     tree cst2 = uniform_integer_cst_p (@3);
     tree cst3 = uniform_integer_cst_p (@4);
-  }
-  (if (wi::to_wide (cst1) + wi::to_wide (cst2) == wi::to_wide (cst3))
-   @2))))
+    wi::overflow_type ovf;
+   }
+   (if (wi::add (wi::to_wide (cst1), wi::to_wide (cst2),
+                TYPE_SIGN (TREE_TYPE (cst1)), &ovf) == wi::to_wide (cst3))
+    (if (!ovf || TYPE_OVERFLOW_WRAPS (TREE_TYPE (cst1)))
+     @2
+     (with {
+       tree utype = unsigned_type_for (type);
+      }
+      (convert (plus (convert:utype @0) (convert:utype @3)))))))))
 
 /* Simplifications of shift and rotates.  */
 
diff --git a/gcc/testsuite/gcc.dg/torture/pr126459.c 
b/gcc/testsuite/gcc.dg/torture/pr126459.c
new file mode 100644
index 000000000000..c91cb2123334
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr126459.c
@@ -0,0 +1,34 @@
+/* PR tree-optimization/126459 */
+/* { dg-do run } */
+
+#define INT_MAX __INT_MAX__
+#define INT_MIN (-(INT_MAX) - 1)
+
+__attribute__((noipa)) int
+foo (int x)
+{
+  return (x != INT_MAX ? x + 1 : INT_MIN) > x;
+}
+
+__attribute__((noipa)) int
+bar (int x)
+{
+  return (x != INT_MIN ? x - 1 : INT_MAX) < x;
+}
+
+__attribute__((noipa)) int
+baz (int x)
+{
+  return (x != INT_MIN ? x + INT_MIN : 0) < 0;
+}
+
+int
+main ()
+{
+  if (foo (INT_MAX) != 0 || foo (1) != 1)
+    __builtin_abort ();
+  if (bar (INT_MIN) != 0 || bar (2) != 1)
+    __builtin_abort ();
+  if (baz (INT_MIN) != 0 || baz (3) != 1)
+    __builtin_abort ();
+}

Reply via email to