diff options
author | Richard Biener <rguenther@suse.de> | 2024-03-19 12:24:08 +0100 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2024-03-19 13:11:42 +0100 |
commit | e0e9499aeffdaca88f0f29334384aa5f710a81a4 (patch) | |
tree | da3c844037a24c5973a1745a22ebd066f95dff21 | |
parent | 1f257714674cd8fd69db7367aecdd09b672d1db7 (diff) | |
download | gcc-e0e9499aeffdaca88f0f29334384aa5f710a81a4.zip gcc-e0e9499aeffdaca88f0f29334384aa5f710a81a4.tar.gz gcc-e0e9499aeffdaca88f0f29334384aa5f710a81a4.tar.bz2 |
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.
-rw-r--r-- | gcc/testsuite/gcc.dg/pr68317.c | 4 | ||||
-rw-r--r-- | 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 06cd2e1..bd053a7 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 1b2ed75..8b7982a 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: |