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.
This commit is contained in:
parent
1f25771467
commit
e0e9499aef
2 changed files with 30 additions and 37 deletions
|
@ -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" } */
|
||||
}
|
||||
|
|
|
@ -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 ()))))
|
||||
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 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
|
||||
{
|
||||
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:
|
||||
|
|
Loading…
Add table
Reference in a new issue