2006-06-16 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 16 Jun 2006 14:56:34 +0000 (14:56 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 16 Jun 2006 14:56:34 +0000 (14:56 +0000)
PR middle-end/27116
* fold-const.c (negate_expr_p): Do not introduce undefined
overflow in negating INTEGER_CSTs.
(fold_negate_expr): Rename from negate_expr.  Revert last
change for folding BIT_NOT_EXPR.  Change semantics to
return NULL_TREE for non-simplified negations.  Do not
strip type conversions and unify type handling.
(negate_expr): New function, wrap around fold_negate_expr
but ensure building a tree always.  Strip type conversions
here, fold to result type.
(fold_unary): Use fold_negate_expr for folding NEGATE_EXPR.

* gcc.dg/pr15785-1.c: Revert last change.
* gcc.dg/torture/pr27116-2.c: New testcase.

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

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr15785-1.c
gcc/testsuite/gcc.dg/torture/pr27116-2.c [new file with mode: 0644]

index 17355ce..5ced5be 100644 (file)
@@ -1,3 +1,17 @@
+2006-06-16  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/27116
+       * fold-const.c (negate_expr_p): Do not introduce undefined
+       overflow in negating INTEGER_CSTs.
+       (fold_negate_expr): Rename from negate_expr.  Revert last
+       change for folding BIT_NOT_EXPR.  Change semantics to
+       return NULL_TREE for non-simplified negations.  Do not
+       strip type conversions and unify type handling.
+       (negate_expr): New function, wrap around fold_negate_expr
+       but ensure building a tree always.  Strip type conversions
+       here, fold to result type.
+       (fold_unary): Use fold_negate_expr for folding NEGATE_EXPR.
+
 2006-06-16  Roger Sayle  <roger@eyesopen.com>
 
        PR middle-end/27802
index 4b49fa9..57a7248 100644 (file)
@@ -923,7 +923,7 @@ may_negate_without_overflow_p (tree t)
 }
 
 /* Determine whether an expression T can be cheaply negated using
-   the function negate_expr.  */
+   the function negate_expr without introducing undefined overflow.  */
 
 static bool
 negate_expr_p (tree t)
@@ -939,7 +939,8 @@ negate_expr_p (tree t)
   switch (TREE_CODE (t))
     {
     case INTEGER_CST:
-      if (TYPE_UNSIGNED (type) || ! flag_trapv)
+      if (TYPE_UNSIGNED (type)
+         || (flag_wrapv && ! flag_trapv))
        return true;
 
       /* Check that -CST will not overflow type.  */
@@ -1030,28 +1031,22 @@ negate_expr_p (tree t)
   return false;
 }
 
-/* Given T, an expression, return the negation of T.  Allow for T to be
-   null, in which case return null.  */
+/* Given T, an expression, return a folded tree for -T or NULL_TREE, if no
+   simplification is possible.
+   If negate_expr_p would return true for T, NULL_TREE will never be
+   returned.  */
 
 static tree
-negate_expr (tree t)
+fold_negate_expr (tree t)
 {
-  tree type;
+  tree type = TREE_TYPE (t);
   tree tem;
 
-  if (t == 0)
-    return 0;
-
-  type = TREE_TYPE (t);
-  STRIP_SIGN_NOPS (t);
-
   switch (TREE_CODE (t))
     {
     /* Convert - (~A) to A + 1.  */
     case BIT_NOT_EXPR:
-      if (INTEGRAL_TYPE_P (type)
-         && (TYPE_UNSIGNED (type)
-             || (flag_wrapv && !flag_trapv)))
+      if (INTEGRAL_TYPE_P (type))
         return fold_build2 (PLUS_EXPR, type, TREE_OPERAND (t, 0),
                             build_int_cst (type, 1));
       break;
@@ -1068,7 +1063,7 @@ negate_expr (tree t)
       tem = fold_negate_const (t, type);
       /* Two's complement FP formats, such as c4x, may overflow.  */
       if (! TREE_OVERFLOW (tem) || ! flag_trapping_math)
-       return fold_convert (type, tem);
+       return tem;
       break;
 
     case COMPLEX_CST:
@@ -1085,7 +1080,7 @@ negate_expr (tree t)
       break;
 
     case NEGATE_EXPR:
-      return fold_convert (type, TREE_OPERAND (t, 0));
+      return TREE_OPERAND (t, 0);
 
     case PLUS_EXPR:
       if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
@@ -1096,18 +1091,16 @@ negate_expr (tree t)
                                     TREE_OPERAND (t, 1)))
            {
              tem = negate_expr (TREE_OPERAND (t, 1));
-             tem = fold_build2 (MINUS_EXPR, TREE_TYPE (t),
-                                tem, TREE_OPERAND (t, 0));
-             return fold_convert (type, tem);
+             return fold_build2 (MINUS_EXPR, type,
+                                 tem, TREE_OPERAND (t, 0));
            }
 
          /* -(A + B) -> (-A) - B.  */
          if (negate_expr_p (TREE_OPERAND (t, 0)))
            {
              tem = negate_expr (TREE_OPERAND (t, 0));
-             tem = fold_build2 (MINUS_EXPR, TREE_TYPE (t),
-                                tem, TREE_OPERAND (t, 1));
-             return fold_convert (type, tem);
+             return fold_build2 (MINUS_EXPR, type,
+                                 tem, TREE_OPERAND (t, 1));
            }
        }
       break;
@@ -1116,33 +1109,27 @@ negate_expr (tree t)
       /* - (A - B) -> B - A  */
       if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
          && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
-       return fold_convert (type,
-                            fold_build2 (MINUS_EXPR, TREE_TYPE (t),
-                                         TREE_OPERAND (t, 1),
-                                         TREE_OPERAND (t, 0)));
+       return fold_build2 (MINUS_EXPR, type,
+                           TREE_OPERAND (t, 1), TREE_OPERAND (t, 0));
       break;
 
     case MULT_EXPR:
-      if (TYPE_UNSIGNED (TREE_TYPE (t)))
+      if (TYPE_UNSIGNED (type))
         break;
 
       /* Fall through.  */
 
     case RDIV_EXPR:
-      if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (t))))
+      if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type)))
        {
          tem = TREE_OPERAND (t, 1);
          if (negate_expr_p (tem))
-           return fold_convert (type,
-                                fold_build2 (TREE_CODE (t), TREE_TYPE (t),
-                                             TREE_OPERAND (t, 0),
-                                             negate_expr (tem)));
+           return fold_build2 (TREE_CODE (t), type,
+                               TREE_OPERAND (t, 0), negate_expr (tem));
          tem = TREE_OPERAND (t, 0);
          if (negate_expr_p (tem))
-           return fold_convert (type,
-                                fold_build2 (TREE_CODE (t), TREE_TYPE (t),
-                                             negate_expr (tem),
-                                             TREE_OPERAND (t, 1)));
+           return fold_build2 (TREE_CODE (t), type,
+                               negate_expr (tem), TREE_OPERAND (t, 1));
        }
       break;
 
@@ -1151,20 +1138,16 @@ negate_expr (tree t)
     case FLOOR_DIV_EXPR:
     case CEIL_DIV_EXPR:
     case EXACT_DIV_EXPR:
-      if (!TYPE_UNSIGNED (TREE_TYPE (t)) && !flag_wrapv)
+      if (!TYPE_UNSIGNED (type) && !flag_wrapv)
         {
           tem = TREE_OPERAND (t, 1);
           if (negate_expr_p (tem))
-            return fold_convert (type,
-                                 fold_build2 (TREE_CODE (t), TREE_TYPE (t),
-                                              TREE_OPERAND (t, 0),
-                                              negate_expr (tem)));
+            return fold_build2 (TREE_CODE (t), type,
+                               TREE_OPERAND (t, 0), negate_expr (tem));
           tem = TREE_OPERAND (t, 0);
           if (negate_expr_p (tem))
-            return fold_convert (type,
-                                 fold_build2 (TREE_CODE (t), TREE_TYPE (t),
-                                              negate_expr (tem),
-                                              TREE_OPERAND (t, 1)));
+            return fold_build2 (TREE_CODE (t), type,
+                               negate_expr (tem), TREE_OPERAND (t, 1));
         }
       break;
 
@@ -1174,7 +1157,7 @@ negate_expr (tree t)
        {
          tem = strip_float_extensions (t);
          if (tem != t && negate_expr_p (tem))
-           return fold_convert (type, negate_expr (tem));
+           return negate_expr (tem);
        }
       break;
 
@@ -1215,7 +1198,27 @@ negate_expr (tree t)
       break;
     }
 
-  tem = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
+  return NULL_TREE;
+}
+
+/* Like fold_negate_expr, but return a NEGATE_EXPR tree, if T can not be
+   negated in a simpler way.  Also allow for T to be NULL_TREE, in which case
+   return NULL_TREE. */
+
+static tree
+negate_expr (tree t)
+{
+  tree type, tem;
+
+  if (t == NULL_TREE)
+    return NULL_TREE;
+
+  type = TREE_TYPE (t);
+  STRIP_SIGN_NOPS (t);
+
+  tem = fold_negate_expr (t);
+  if (!tem)
+    tem = build1 (NEGATE_EXPR, TREE_TYPE (t), t);
   return fold_convert (type, tem);
 }
 \f
@@ -7544,8 +7547,9 @@ fold_unary (enum tree_code code, tree type, tree op0)
       return fold_view_convert_expr (type, op0);
 
     case NEGATE_EXPR:
-      if (negate_expr_p (arg0))
-       return fold_convert (type, negate_expr (arg0));
+      tem = fold_negate_expr (arg0);
+      if (tem)
+       return fold_convert (type, tem);
       return NULL_TREE;
 
     case ABS_EXPR:
index 31c1fad..f4a6ed4 100644 (file)
@@ -1,3 +1,9 @@
+2006-06-16  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/27116
+       * gcc.dg/pr15785-1.c: Revert last change.
+       * gcc.dg/torture/pr27116-2.c: New testcase.
+
 2006-06-16  Roger Sayle  <roger@eyesopen.com>
 
        PR middle-end/27802
index 5e79ec5..47cd3d7 100644 (file)
@@ -11,6 +11,11 @@ void b (int x) {
                link_error ();
 }
 
+void c (int x) {
+       if (!(- (~x) - x))
+               link_error ();
+}
+
 void d (int x) {
        if (!(~ (-x) - x))
                link_error ();
@@ -29,6 +34,7 @@ void f (int x) {
 int main (int argc, char *argv[]) {
        a(argc);
        b(argc);
+       c(argc);
        d(argc);
        e(argc);
        f(argc);
diff --git a/gcc/testsuite/gcc.dg/torture/pr27116-2.c b/gcc/testsuite/gcc.dg/torture/pr27116-2.c
new file mode 100644 (file)
index 0000000..9c748b2
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+
+extern void abort(void);
+
+int main (void)
+{
+    volatile long int n;
+    n = -2;
+
+    if ((-2147483647L - 1L) / (-n) != -1073741824L)
+       abort ();
+    return 0;
+}