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);
