OSDN Git Service

2008-08-28 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 28 Aug 2008 08:31:37 +0000 (08:31 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 28 Aug 2008 08:31:37 +0000 (08:31 +0000)
PR middle-end/37005
* fold-const.c (maybe_canonicalize_comparison_1): Require
undefined overflow only for canonicalizing A +- CST cmp CST.
Make sure to not generate new constants that are not inside
their TYPE_MIN/MAX_VALUE range.
(maybe_canonicalize_comparison): Remove undefined overflow
checking from here.
(fold_binary): Remove now duplicate folding.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@139702 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c

index c57126f..6e94365 100644 (file)
@@ -1,3 +1,14 @@
+2008-08-28  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/37005
+       * fold-const.c (maybe_canonicalize_comparison_1): Require
+       undefined overflow only for canonicalizing A +- CST cmp CST.
+       Make sure to not generate new constants that are not inside
+       their TYPE_MIN/MAX_VALUE range.
+       (maybe_canonicalize_comparison): Remove undefined overflow
+       checking from here.
+       (fold_binary): Remove now duplicate folding.
+
 2008-08-27  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * c-typeck.c (convert_for_assignment): Adjust WARN_FOR_ASSIGNMENT
 2008-08-27  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * c-typeck.c (convert_for_assignment): Adjust WARN_FOR_ASSIGNMENT
index e6769a6..21142b8 100644 (file)
@@ -8289,9 +8289,14 @@ maybe_canonicalize_comparison_1 (enum tree_code code, tree type,
   int sgn0;
   bool swap = false;
 
   int sgn0;
   bool swap = false;
 
-  /* Match A +- CST code arg1 and CST code arg1.  */
-  if (!(((code0 == MINUS_EXPR
-          || code0 == PLUS_EXPR)
+  /* Match A +- CST code arg1 and CST code arg1.  We can change the
+     first form only if overflow is undefined.  */
+  if (!((TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
+        /* In principle pointers also have undefined overflow behavior,
+           but that causes problems elsewhere.  */
+        && !POINTER_TYPE_P (TREE_TYPE (arg0))
+        && (code0 == MINUS_EXPR
+            || code0 == PLUS_EXPR)
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        || code0 == INTEGER_CST))
     return NULL_TREE;
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        || code0 == INTEGER_CST))
     return NULL_TREE;
@@ -8352,9 +8357,21 @@ maybe_canonicalize_comparison_1 (enum tree_code code, tree type,
       *strict_overflow_p = true;
     }
 
       *strict_overflow_p = true;
     }
 
-  /* Now build the constant reduced in magnitude.  */
+  /* Now build the constant reduced in magnitude.  But not if that
+     would produce one outside of its types range.  */
+  if (INTEGRAL_TYPE_P (TREE_TYPE (cst0))
+      && ((sgn0 == 1
+          && TYPE_MIN_VALUE (TREE_TYPE (cst0))
+          && tree_int_cst_equal (cst0, TYPE_MIN_VALUE (TREE_TYPE (cst0))))
+         || (sgn0 == -1
+             && TYPE_MAX_VALUE (TREE_TYPE (cst0))
+             && tree_int_cst_equal (cst0, TYPE_MAX_VALUE (TREE_TYPE (cst0))))))
+    /* We cannot swap the comparison here as that would cause us to
+       endlessly recurse.  */
+    return NULL_TREE;
+
   t = int_const_binop (sgn0 == -1 ? PLUS_EXPR : MINUS_EXPR,
   t = int_const_binop (sgn0 == -1 ? PLUS_EXPR : MINUS_EXPR,
-                      cst0, build_int_cst (TREE_TYPE (cst0), 1), 0);
+                      cst0, build_int_cst (TREE_TYPE (cst0), 1), 0);
   if (code0 != INTEGER_CST)
     t = fold_build2 (code0, TREE_TYPE (arg0), TREE_OPERAND (arg0, 0), t);
 
   if (code0 != INTEGER_CST)
     t = fold_build2 (code0, TREE_TYPE (arg0), TREE_OPERAND (arg0, 0), t);
 
@@ -8380,12 +8397,6 @@ maybe_canonicalize_comparison (enum tree_code code, tree type,
   const char * const warnmsg = G_("assuming signed overflow does not occur "
                                  "when reducing constant in comparison");
 
   const char * const warnmsg = G_("assuming signed overflow does not occur "
                                  "when reducing constant in comparison");
 
-  /* In principle pointers also have undefined overflow behavior,
-     but that causes problems elsewhere.  */
-  if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
-      || POINTER_TYPE_P (TREE_TYPE (arg0)))
-    return NULL_TREE;
-
   /* Try canonicalization by simplifying arg0.  */
   strict_overflow_p = false;
   t = maybe_canonicalize_comparison_1 (code, type, arg0, arg1,
   /* Try canonicalization by simplifying arg0.  */
   strict_overflow_p = false;
   t = maybe_canonicalize_comparison_1 (code, type, arg0, arg1,
@@ -12424,29 +12435,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            }
        }
 
            }
        }
 
-      /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0.
-        This transformation affects the cases which are handled in later
-        optimizations involving comparisons with non-negative constants.  */
-      if (TREE_CODE (arg1) == INTEGER_CST
-         && TREE_CODE (arg0) != INTEGER_CST
-         && tree_int_cst_sgn (arg1) > 0)
-       {
-         if (code == GE_EXPR)
-           {
-             arg1 = const_binop (MINUS_EXPR, arg1,
-                                 build_int_cst (TREE_TYPE (arg1), 1), 0);
-             return fold_build2 (GT_EXPR, type, arg0,
-                                 fold_convert (TREE_TYPE (arg0), arg1));
-           }
-         if (code == LT_EXPR)
-           {
-             arg1 = const_binop (MINUS_EXPR, arg1,
-                                 build_int_cst (TREE_TYPE (arg1), 1), 0);
-             return fold_build2 (LE_EXPR, type, arg0,
-                                 fold_convert (TREE_TYPE (arg0), arg1));
-           }
-       }
-
       /* Comparisons with the highest or lowest possible integer of
         the specified precision will have known values.  */
       {
       /* Comparisons with the highest or lowest possible integer of
         the specified precision will have known values.  */
       {