Commit 1af8dcbf by Richard Guenther Committed by Richard Biener

re PR middle-end/27116 (Incorrect integer division (wrong sign).)

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.

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

From-SVN: r114723
parent 2d0df1f9
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> 2006-06-16 Roger Sayle <roger@eyesopen.com>
PR middle-end/27802 PR middle-end/27802
......
...@@ -923,7 +923,7 @@ may_negate_without_overflow_p (tree t) ...@@ -923,7 +923,7 @@ may_negate_without_overflow_p (tree t)
} }
/* Determine whether an expression T can be cheaply negated using /* Determine whether an expression T can be cheaply negated using
the function negate_expr. */ the function negate_expr without introducing undefined overflow. */
static bool static bool
negate_expr_p (tree t) negate_expr_p (tree t)
...@@ -939,7 +939,8 @@ negate_expr_p (tree t) ...@@ -939,7 +939,8 @@ negate_expr_p (tree t)
switch (TREE_CODE (t)) switch (TREE_CODE (t))
{ {
case INTEGER_CST: case INTEGER_CST:
if (TYPE_UNSIGNED (type) || ! flag_trapv) if (TYPE_UNSIGNED (type)
|| (flag_wrapv && ! flag_trapv))
return true; return true;
/* Check that -CST will not overflow type. */ /* Check that -CST will not overflow type. */
...@@ -1030,28 +1031,22 @@ negate_expr_p (tree t) ...@@ -1030,28 +1031,22 @@ negate_expr_p (tree t)
return false; return false;
} }
/* Given T, an expression, return the negation of T. Allow for T to be /* Given T, an expression, return a folded tree for -T or NULL_TREE, if no
null, in which case return null. */ simplification is possible.
If negate_expr_p would return true for T, NULL_TREE will never be
returned. */
static tree static tree
negate_expr (tree t) fold_negate_expr (tree t)
{ {
tree type; tree type = TREE_TYPE (t);
tree tem; tree tem;
if (t == 0)
return 0;
type = TREE_TYPE (t);
STRIP_SIGN_NOPS (t);
switch (TREE_CODE (t)) switch (TREE_CODE (t))
{ {
/* Convert - (~A) to A + 1. */ /* Convert - (~A) to A + 1. */
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
if (INTEGRAL_TYPE_P (type) if (INTEGRAL_TYPE_P (type))
&& (TYPE_UNSIGNED (type)
|| (flag_wrapv && !flag_trapv)))
return fold_build2 (PLUS_EXPR, type, TREE_OPERAND (t, 0), return fold_build2 (PLUS_EXPR, type, TREE_OPERAND (t, 0),
build_int_cst (type, 1)); build_int_cst (type, 1));
break; break;
...@@ -1068,7 +1063,7 @@ negate_expr (tree t) ...@@ -1068,7 +1063,7 @@ negate_expr (tree t)
tem = fold_negate_const (t, type); tem = fold_negate_const (t, type);
/* Two's complement FP formats, such as c4x, may overflow. */ /* Two's complement FP formats, such as c4x, may overflow. */
if (! TREE_OVERFLOW (tem) || ! flag_trapping_math) if (! TREE_OVERFLOW (tem) || ! flag_trapping_math)
return fold_convert (type, tem); return tem;
break; break;
case COMPLEX_CST: case COMPLEX_CST:
...@@ -1085,7 +1080,7 @@ negate_expr (tree t) ...@@ -1085,7 +1080,7 @@ negate_expr (tree t)
break; break;
case NEGATE_EXPR: case NEGATE_EXPR:
return fold_convert (type, TREE_OPERAND (t, 0)); return TREE_OPERAND (t, 0);
case PLUS_EXPR: case PLUS_EXPR:
if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations) if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
...@@ -1096,18 +1091,16 @@ negate_expr (tree t) ...@@ -1096,18 +1091,16 @@ negate_expr (tree t)
TREE_OPERAND (t, 1))) TREE_OPERAND (t, 1)))
{ {
tem = negate_expr (TREE_OPERAND (t, 1)); tem = negate_expr (TREE_OPERAND (t, 1));
tem = fold_build2 (MINUS_EXPR, TREE_TYPE (t), return fold_build2 (MINUS_EXPR, type,
tem, TREE_OPERAND (t, 0)); tem, TREE_OPERAND (t, 0));
return fold_convert (type, tem);
} }
/* -(A + B) -> (-A) - B. */ /* -(A + B) -> (-A) - B. */
if (negate_expr_p (TREE_OPERAND (t, 0))) if (negate_expr_p (TREE_OPERAND (t, 0)))
{ {
tem = negate_expr (TREE_OPERAND (t, 0)); tem = negate_expr (TREE_OPERAND (t, 0));
tem = fold_build2 (MINUS_EXPR, TREE_TYPE (t), return fold_build2 (MINUS_EXPR, type,
tem, TREE_OPERAND (t, 1)); tem, TREE_OPERAND (t, 1));
return fold_convert (type, tem);
} }
} }
break; break;
...@@ -1116,33 +1109,27 @@ negate_expr (tree t) ...@@ -1116,33 +1109,27 @@ negate_expr (tree t)
/* - (A - B) -> B - A */ /* - (A - B) -> B - A */
if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations) if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
&& reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1))) && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
return fold_convert (type, return fold_build2 (MINUS_EXPR, type,
fold_build2 (MINUS_EXPR, TREE_TYPE (t), TREE_OPERAND (t, 1), TREE_OPERAND (t, 0));
TREE_OPERAND (t, 1),
TREE_OPERAND (t, 0)));
break; break;
case MULT_EXPR: case MULT_EXPR:
if (TYPE_UNSIGNED (TREE_TYPE (t))) if (TYPE_UNSIGNED (type))
break; break;
/* Fall through. */ /* Fall through. */
case RDIV_EXPR: 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); tem = TREE_OPERAND (t, 1);
if (negate_expr_p (tem)) if (negate_expr_p (tem))
return fold_convert (type, return fold_build2 (TREE_CODE (t), type,
fold_build2 (TREE_CODE (t), TREE_TYPE (t), TREE_OPERAND (t, 0), negate_expr (tem));
TREE_OPERAND (t, 0),
negate_expr (tem)));
tem = TREE_OPERAND (t, 0); tem = TREE_OPERAND (t, 0);
if (negate_expr_p (tem)) if (negate_expr_p (tem))
return fold_convert (type, return fold_build2 (TREE_CODE (t), type,
fold_build2 (TREE_CODE (t), TREE_TYPE (t), negate_expr (tem), TREE_OPERAND (t, 1));
negate_expr (tem),
TREE_OPERAND (t, 1)));
} }
break; break;
...@@ -1151,20 +1138,16 @@ negate_expr (tree t) ...@@ -1151,20 +1138,16 @@ negate_expr (tree t)
case FLOOR_DIV_EXPR: case FLOOR_DIV_EXPR:
case CEIL_DIV_EXPR: case CEIL_DIV_EXPR:
case EXACT_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); tem = TREE_OPERAND (t, 1);
if (negate_expr_p (tem)) if (negate_expr_p (tem))
return fold_convert (type, return fold_build2 (TREE_CODE (t), type,
fold_build2 (TREE_CODE (t), TREE_TYPE (t), TREE_OPERAND (t, 0), negate_expr (tem));
TREE_OPERAND (t, 0),
negate_expr (tem)));
tem = TREE_OPERAND (t, 0); tem = TREE_OPERAND (t, 0);
if (negate_expr_p (tem)) if (negate_expr_p (tem))
return fold_convert (type, return fold_build2 (TREE_CODE (t), type,
fold_build2 (TREE_CODE (t), TREE_TYPE (t), negate_expr (tem), TREE_OPERAND (t, 1));
negate_expr (tem),
TREE_OPERAND (t, 1)));
} }
break; break;
...@@ -1174,7 +1157,7 @@ negate_expr (tree t) ...@@ -1174,7 +1157,7 @@ negate_expr (tree t)
{ {
tem = strip_float_extensions (t); tem = strip_float_extensions (t);
if (tem != t && negate_expr_p (tem)) if (tem != t && negate_expr_p (tem))
return fold_convert (type, negate_expr (tem)); return negate_expr (tem);
} }
break; break;
...@@ -1215,7 +1198,27 @@ negate_expr (tree t) ...@@ -1215,7 +1198,27 @@ negate_expr (tree t)
break; 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); return fold_convert (type, tem);
} }
...@@ -7544,8 +7547,9 @@ fold_unary (enum tree_code code, tree type, tree op0) ...@@ -7544,8 +7547,9 @@ fold_unary (enum tree_code code, tree type, tree op0)
return fold_view_convert_expr (type, op0); return fold_view_convert_expr (type, op0);
case NEGATE_EXPR: case NEGATE_EXPR:
if (negate_expr_p (arg0)) tem = fold_negate_expr (arg0);
return fold_convert (type, negate_expr (arg0)); if (tem)
return fold_convert (type, tem);
return NULL_TREE; return NULL_TREE;
case ABS_EXPR: case ABS_EXPR:
......
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> 2006-06-16 Roger Sayle <roger@eyesopen.com>
PR middle-end/27802 PR middle-end/27802
...@@ -11,6 +11,11 @@ void b (int x) { ...@@ -11,6 +11,11 @@ void b (int x) {
link_error (); link_error ();
} }
void c (int x) {
if (!(- (~x) - x))
link_error ();
}
void d (int x) { void d (int x) {
if (!(~ (-x) - x)) if (!(~ (-x) - x))
link_error (); link_error ();
...@@ -29,6 +34,7 @@ void f (int x) { ...@@ -29,6 +34,7 @@ void f (int x) {
int main (int argc, char *argv[]) { int main (int argc, char *argv[]) {
a(argc); a(argc);
b(argc); b(argc);
c(argc);
d(argc); d(argc);
e(argc); e(argc);
f(argc); f(argc);
......
/* { dg-do run } */
extern void abort(void);
int main (void)
{
volatile long int n;
n = -2;
if ((-2147483647L - 1L) / (-n) != -1073741824L)
abort ();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment