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
This commit is contained in:
parent
2d0df1f9a8
commit
1af8dcbf0b
|
@ -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
|
||||
|
|
104
gcc/fold-const.c
104
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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue