]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/114151 - revert PR114074 fix
authorRichard Biener <rguenther@suse.de>
Tue, 19 Mar 2024 11:24:08 +0000 (12:24 +0100)
committerRichard Biener <rguenther@suse.de>
Tue, 19 Mar 2024 12:11:42 +0000 (13:11 +0100)
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.

gcc/testsuite/gcc.dg/pr68317.c
gcc/tree-chrec.cc

index 06cd2e1da9ca8346ee6f853152599536b2eb0519..bd053a7522bcbc7dc0ef2ae30d48f51566b5c1ae 100644 (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" } */
 }
index 1b2ed7535512ad5a8a4acb5a80fcbf597a037461..8b7982a2dbe99d154cae261598f9d4b30b6e1724 100644 (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 ()))))
-           {
-             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: