https://gcc.gnu.org/g:e0e9499aeffdaca88f0f29334384aa5f710a81a4
commit r14-9540-ge0e9499aeffdaca88f0f29334384aa5f710a81a4 Author: Richard Biener <rguent...@suse.de> Date: Tue Mar 19 12:24:08 2024 +0100 tree-optimization/114151 - revert PR114074 fix The following reverts the chrec_fold_multiply fix and only keeps handling of constant overflow which keeps the original testcase fixed. A better solution might involve ranger improvements or tracking of assumptions during SCEV analysis similar to what niter analysis does. PR tree-optimization/114151 PR tree-optimization/114269 PR tree-optimization/114322 PR tree-optimization/114074 * tree-chrec.cc (chrec_fold_multiply): Restrict the use of unsigned arithmetic when actual overflow on constant operands is observed. * gcc.dg/pr68317.c: Revert last change. Diff: --- gcc/testsuite/gcc.dg/pr68317.c | 4 +-- gcc/tree-chrec.cc | 63 +++++++++++++++++++----------------------- 2 files changed, 30 insertions(+), 37 deletions(-) diff --git a/gcc/testsuite/gcc.dg/pr68317.c b/gcc/testsuite/gcc.dg/pr68317.c index 06cd2e1da9c..bd053a7522b 100644 --- a/gcc/testsuite/gcc.dg/pr68317.c +++ b/gcc/testsuite/gcc.dg/pr68317.c @@ -12,8 +12,8 @@ foo () { int32_t index = 0; - for (index; index <= 10; index--) /* { dg-warning "iteration \[0-9\]+ invokes undefined behavior" } */ + for (index; index <= 10; index--) // expected warning here /* Result of the following multiply will overflow when converted to signed int32_t. */ - bar ((0xcafe + index) * 0xdead); + bar ((0xcafe + index) * 0xdead); /* { dg-warning "iteration \[0-9\]+ invokes undefined behavior" } */ } diff --git a/gcc/tree-chrec.cc b/gcc/tree-chrec.cc index 1b2ed753551..8b7982a2dbe 100644 --- a/gcc/tree-chrec.cc +++ b/gcc/tree-chrec.cc @@ -38,8 +38,6 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "tree-ssa-loop.h" #include "dumpfile.h" -#include "value-range.h" -#include "value-query.h" #include "tree-scalar-evolution.h" /* Extended folder for chrecs. */ @@ -475,41 +473,36 @@ chrec_fold_multiply (tree type, /* When overflow is undefined and CHREC_LEFT/RIGHT do not have the same sign or CHREC_LEFT is zero then folding the multiply into - the addition does not have the same behavior on overflow. Use - unsigned arithmetic in that case. */ - value_range rl, rr; - if (!ANY_INTEGRAL_TYPE_P (type) - || TYPE_OVERFLOW_WRAPS (type) - || integer_zerop (CHREC_LEFT (op0)) - || (TREE_CODE (CHREC_LEFT (op0)) == INTEGER_CST - && TREE_CODE (CHREC_RIGHT (op0)) == INTEGER_CST - && (tree_int_cst_sgn (CHREC_LEFT (op0)) - == tree_int_cst_sgn (CHREC_RIGHT (op0)))) - || (get_range_query (cfun)->range_of_expr (rl, CHREC_LEFT (op0)) - && !rl.undefined_p () - && (rl.nonpositive_p () || rl.nonnegative_p ()) - && get_range_query (cfun)->range_of_expr (rr, - CHREC_RIGHT (op0)) - && !rr.undefined_p () - && ((rl.nonpositive_p () && rr.nonpositive_p ()) - || (rl.nonnegative_p () && rr.nonnegative_p ())))) - { - tree left = chrec_fold_multiply (type, CHREC_LEFT (op0), op1); - tree right = chrec_fold_multiply (type, CHREC_RIGHT (op0), op1); - return build_polynomial_chrec (CHREC_VARIABLE (op0), left, right); - } - else + the addition does not have the same behavior on overflow. + Using unsigned arithmetic in that case causes too many performance + regressions, but catch the constant case where the multiplication + of the step overflows. */ + if (INTEGRAL_TYPE_P (type) + && TYPE_OVERFLOW_UNDEFINED (type) + && !integer_zerop (CHREC_LEFT (op0)) + && TREE_CODE (op1) == INTEGER_CST + && TREE_CODE (CHREC_RIGHT (op0)) == INTEGER_CST) { - tree utype = unsigned_type_for (type); - tree uop1 = chrec_convert_rhs (utype, op1); - tree uleft0 = chrec_convert_rhs (utype, CHREC_LEFT (op0)); - tree uright0 = chrec_convert_rhs (utype, CHREC_RIGHT (op0)); - tree left = chrec_fold_multiply (utype, uleft0, uop1); - tree right = chrec_fold_multiply (utype, uright0, uop1); - tree tem = build_polynomial_chrec (CHREC_VARIABLE (op0), - left, right); - return chrec_convert_rhs (type, tem); + wi::overflow_type ovf = wi::OVF_NONE; + wide_int res + = wi::mul (wi::to_wide (CHREC_RIGHT (op0)), + wi::to_wide (op1), TYPE_SIGN (type), &ovf); + if (ovf != wi::OVF_NONE) + { + tree utype = unsigned_type_for (type); + tree uop1 = chrec_convert_rhs (utype, op1); + tree uleft0 = chrec_convert_rhs (utype, CHREC_LEFT (op0)); + tree uright0 = chrec_convert_rhs (utype, CHREC_RIGHT (op0)); + tree left = chrec_fold_multiply (utype, uleft0, uop1); + tree right = chrec_fold_multiply (utype, uright0, uop1); + tree tem = build_polynomial_chrec (CHREC_VARIABLE (op0), + left, right); + return chrec_convert_rhs (type, tem); + } } + tree left = chrec_fold_multiply (type, CHREC_LEFT (op0), op1); + tree right = chrec_fold_multiply (type, CHREC_RIGHT (op0), op1); + return build_polynomial_chrec (CHREC_VARIABLE (op0), left, right); } CASE_CONVERT: