diff mbox series

tree-optimization/114151 - revert PR114074 fix

Message ID 20240319120713.6F20C3858402@sourceware.org
State New
Headers show
Series tree-optimization/114151 - revert PR114074 fix | expand

Commit Message

Richard Biener March 19, 2024, 12:06 p.m. UTC
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.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

OK for trunk?  Or do you prefer to not fix the INTEGER_CST case
either?

Thanks,
Richard.

	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.
---
 gcc/testsuite/gcc.dg/pr68317.c |  4 +--
 gcc/tree-chrec.cc              | 63 +++++++++++++++-------------------
 2 files changed, 30 insertions(+), 37 deletions(-)
diff mbox series

Patch

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: