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:
Richard Biener 2024-03-19 12:24:08 +01:00
parent 1f25771467
commit e0e9499aef
2 changed files with 30 additions and 37 deletions

View file

@ -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" } */
}

View file

@ -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: