https://gcc.gnu.org/g:ebe50ecf876fee0b5ce991d302eaef8670325710

commit r16-9100-gebe50ecf876fee0b5ce991d302eaef8670325710
Author: Richard Biener <[email protected]>
Date:   Mon Jun 8 10:50:35 2026 +0200

    tree-optimization/125652 - wrong code with SCEV
    
    The following fixes a latent issue in chrec_fold_plus_poly_poly
    which suffers from being prone to signed overflow UB in the way
    it associates additions when accumulating two polynomical CHRECs.
    Similar to r16-2781-gafafae097232e7 the following catches the
    obvious cases when constants are involved without trying to address
    the actual underlying issue.
    
            PR tree-optimization/125652
            * tree-chrec.cc (chrec_fold_plus_poly_poly): Avoid UB
            integer overflow in accumulating CHREC_RIGHT.
    
            * gcc.dg/torture/pr125652.c: New testcase.
    
    (cherry picked from commit de3a13dd7f6c2856e96fc2b7924f9b34b638940f)

Diff:
---
 gcc/testsuite/gcc.dg/torture/pr125652.c | 32 ++++++++++++++++++++++++++++++++
 gcc/tree-chrec.cc                       | 10 ++++++++++
 2 files changed, 42 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/torture/pr125652.c 
b/gcc/testsuite/gcc.dg/torture/pr125652.c
new file mode 100644
index 000000000000..a99da3fb5cad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr125652.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+#include <stdint.h>
+
+int a, b, c, d;
+
+void e(int64_t f, int64_t g)
+{
+  int64_t h = 1, *i, **j;
+  while (1)
+    {
+      i = &h;
+      j = &i;
+      if (h <= h + f - ~h)
+        break;
+      *i += g;
+    }
+  c *= 2;
+  d = a >> b + d;
+}
+
+int f123()
+{
+  e(-2147483627, 4611686018427387904);
+  return 0;
+}
+
+int main()
+{
+  return f123();
+}
diff --git a/gcc/tree-chrec.cc b/gcc/tree-chrec.cc
index 09dd81900bce..68e16abc8d26 100644
--- a/gcc/tree-chrec.cc
+++ b/gcc/tree-chrec.cc
@@ -127,6 +127,16 @@ chrec_fold_plus_poly_poly (enum tree_code code,
 
   if (chrec_zerop (right))
     return left;
+  /* When we have an evolution in a non-wrapping type and in the process of
+     accumulating CHREC_RIGHT there was overflow this indicates in the
+     association that happened in accumulating the CHRECs clearly involved UB.
+     Avoid this.  When accumulating two CHRECs we basically turn
+     (a + INCR1) + INCR2 into a + (INCR1 + INCR2) which is not always valid.
+     Note this check only catches few invalid cases.  */
+  else if ((INTEGRAL_TYPE_P (type) && ! TYPE_OVERFLOW_WRAPS (type))
+          && TREE_CODE (right) == INTEGER_CST
+          && TREE_OVERFLOW (right))
+    return chrec_dont_know;
   else
     return build_polynomial_chrec
       (CHREC_VARIABLE (poly0), left, right);

Reply via email to