From: Richard Biener Date: Tue, 5 Aug 2025 06:59:18 +0000 (+0200) Subject: tree-optimization/121370 - avoid UB in building a CHREC X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e1dd907e1dff10da8cc6013345c4037184891655;p=thirdparty%2Fgcc.git 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. (cherry picked from commit afafae097232e700bb7a74a453a048b83ebefccd) --- diff --git a/gcc/testsuite/gcc.dg/torture/pr121370.c b/gcc/testsuite/gcc.dg/torture/pr121370.c new file mode 100644 index 00000000000..d40f3b216ad --- /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 b0a5e09a77c..a3511c55c70 100644 --- a/gcc/tree-scalar-evolution.cc +++ b/gcc/tree-scalar-evolution.cc @@ -669,6 +669,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