https://gcc.gnu.org/g:afafae097232e700bb7a74a453a048b83ebefccd
commit r16-2781-gafafae097232e700bb7a74a453a048b83ebefccd Author: Richard Biener <rguent...@suse.de> Date: Tue Aug 5 08:59:18 2025 +0200 tree-optimization/121370 - avoid UB in building a CHREC When there is obvious UB involved in the process of re-associating a series of IV increments to build up a CHREC, fail. This catches a few degenerate cases where SCEV introduces UB with its inherent re-associating of IV increments. PR tree-optimization/121370 * tree-scalar-evolution.cc (scev_dfs::add_to_evolution_1): Avoid UB integer overflow in accumulating CHREC_RIGHT. * gcc.dg/torture/pr121370.c: New testcase. Diff: --- gcc/testsuite/gcc.dg/torture/pr121370.c | 25 +++++++++++++++++++++++++ gcc/tree-scalar-evolution.cc | 11 +++++++++++ 2 files changed, 36 insertions(+) diff --git a/gcc/testsuite/gcc.dg/torture/pr121370.c b/gcc/testsuite/gcc.dg/torture/pr121370.c new file mode 100644 index 000000000000..d40f3b216add --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr121370.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-require-effective-target int32plus } */ + +int a; +int main() +{ + int c = -2147483647; + int d = -2147483647; + int e = 2147483647; + if (0) + f: + e = d + e - 2; +g: + if (d - c - e > 0) { + a = -c; + if (a + d) { + d = 1; + goto g; + } + return 0; + } + if (e) + goto f; + return 0; +} diff --git a/gcc/tree-scalar-evolution.cc b/gcc/tree-scalar-evolution.cc index 413ca49cb926..3b3748aba67f 100644 --- a/gcc/tree-scalar-evolution.cc +++ b/gcc/tree-scalar-evolution.cc @@ -670,6 +670,17 @@ scev_dfs::add_to_evolution_1 (tree chrec_before, tree to_add, gimple *at_stmt) to_add = chrec_convert (type, to_add, at_stmt); right = chrec_convert_rhs (type, right, at_stmt); right = chrec_fold_plus (chrec_type (right), right, to_add); + /* 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 building the CHREC clearly involved UB. Avoid this. + In building a CHREC we basically turn (a + INCR1) + INCR2 + into a + (INCR1 + INCR2) which is not always valid. + Note this check only catches few invalid cases. */ + if ((INTEGRAL_TYPE_P (type) && ! TYPE_OVERFLOW_WRAPS (type)) + && TREE_CODE (right) == INTEGER_CST + && TREE_OVERFLOW (right)) + return chrec_dont_know; return build_polynomial_chrec (var, left, right); } else