summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/fold-const.c104
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/pr15785-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr27116-2.c13
5 files changed, 93 insertions, 50 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 17355cefd1a..5ced5be717d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 4b49fa92c02..57a72489121 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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);
}
@@ -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:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 31c1fad9a38..f4a6ed447e4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/pr15785-1.c b/gcc/testsuite/gcc.dg/pr15785-1.c
index 5e79ec50bbb..47cd3d7b01b 100644
--- a/gcc/testsuite/gcc.dg/pr15785-1.c
+++ b/gcc/testsuite/gcc.dg/pr15785-1.c
@@ -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
index 00000000000..9c748b245f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr27116-2.c
@@ -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;
+}