Commit 380ff34a by Richard Kenner

(const_binop): Rework to only make constants in one place; always use size_int…

(const_binop): Rework to only make constants in one place; always use size_int if small enough and of sizetype.

(const_binop): Rework to only make constants in
one place; always use size_int if small enough and of sizetype.
(size_int): Call force_fit_type.
(fold): Avoid ever changing type of input tree.

From-SVN: r13377
parent f7fa6ef9
/* Fold a constant sub-tree into a single node for C-compiler /* Fold a constant sub-tree into a single node for C-compiler
Copyright (C) 1987, 88, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
...@@ -1072,23 +1072,24 @@ const_binop (code, arg1, arg2, notrunc) ...@@ -1072,23 +1072,24 @@ const_binop (code, arg1, arg2, notrunc)
register tree t; register tree t;
int uns = TREE_UNSIGNED (TREE_TYPE (arg1)); int uns = TREE_UNSIGNED (TREE_TYPE (arg1));
int overflow = 0; int overflow = 0;
int no_overflow = 0;
switch (code) switch (code)
{ {
case BIT_IOR_EXPR: case BIT_IOR_EXPR:
t = build_int_2 (int1l | int2l, int1h | int2h); low = int1l | int2l, hi = int1h | int2h;
break; break;
case BIT_XOR_EXPR: case BIT_XOR_EXPR:
t = build_int_2 (int1l ^ int2l, int1h ^ int2h); low = int1l ^ int2l, hi = int1h ^ int2h;
break; break;
case BIT_AND_EXPR: case BIT_AND_EXPR:
t = build_int_2 (int1l & int2l, int1h & int2h); low = int1l & int2l, hi = int1h & int2h;
break; break;
case BIT_ANDTC_EXPR: case BIT_ANDTC_EXPR:
t = build_int_2 (int1l & ~int2l, int1h & ~int2h); low = int1l & ~int2l, hi = int1h & ~int2h;
break; break;
case RSHIFT_EXPR: case RSHIFT_EXPR:
...@@ -1101,14 +1102,8 @@ const_binop (code, arg1, arg2, notrunc) ...@@ -1101,14 +1102,8 @@ const_binop (code, arg1, arg2, notrunc)
TYPE_PRECISION (TREE_TYPE (arg1)), TYPE_PRECISION (TREE_TYPE (arg1)),
&low, &hi, &low, &hi,
!uns); !uns);
t = build_int_2 (low, hi); no_overflow = 1;
TREE_TYPE (t) = TREE_TYPE (arg1); break;
if (!notrunc)
force_fit_type (t, 0);
TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2);
TREE_CONSTANT_OVERFLOW (t)
= TREE_CONSTANT_OVERFLOW (arg1) | TREE_CONSTANT_OVERFLOW (arg2);
return t;
case RROTATE_EXPR: case RROTATE_EXPR:
int2l = - int2l; int2l = - int2l;
...@@ -1116,94 +1111,76 @@ const_binop (code, arg1, arg2, notrunc) ...@@ -1116,94 +1111,76 @@ const_binop (code, arg1, arg2, notrunc)
lrotate_double (int1l, int1h, int2l, lrotate_double (int1l, int1h, int2l,
TYPE_PRECISION (TREE_TYPE (arg1)), TYPE_PRECISION (TREE_TYPE (arg1)),
&low, &hi); &low, &hi);
t = build_int_2 (low, hi);
break; break;
case PLUS_EXPR: case PLUS_EXPR:
if (int1h == 0)
{
int2l += int1l;
if ((unsigned HOST_WIDE_INT) int2l < int1l)
{
hi = int2h++;
overflow = int2h < hi;
}
t = build_int_2 (int2l, int2h);
break;
}
if (int2h == 0)
{
int1l += int2l;
if ((unsigned HOST_WIDE_INT) int1l < int2l)
{
hi = int1h++;
overflow = int1h < hi;
}
t = build_int_2 (int1l, int1h);
break;
}
overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi); overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi);
t = build_int_2 (low, hi);
break; break;
case MINUS_EXPR: case MINUS_EXPR:
if (int2h == 0 && int2l == 0)
{
t = build_int_2 (int1l, int1h);
break;
}
neg_double (int2l, int2h, &low, &hi); neg_double (int2l, int2h, &low, &hi);
add_double (int1l, int1h, low, hi, &low, &hi); add_double (int1l, int1h, low, hi, &low, &hi);
overflow = overflow_sum_sign (hi, int2h, int1h); overflow = overflow_sum_sign (hi, int2h, int1h);
t = build_int_2 (low, hi);
break; break;
case MULT_EXPR: case MULT_EXPR:
overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi); overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi);
t = build_int_2 (low, hi);
break; break;
case TRUNC_DIV_EXPR: case TRUNC_DIV_EXPR:
case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR: case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:
case EXACT_DIV_EXPR: case EXACT_DIV_EXPR:
/* This is a shortcut for a common special case. /* This is a shortcut for a common special case. */
It reduces the number of tree nodes generated
and saves time. */
if (int2h == 0 && int2l > 0 if (int2h == 0 && int2l > 0
&& TREE_TYPE (arg1) == sizetype
&& ! TREE_CONSTANT_OVERFLOW (arg1) && ! TREE_CONSTANT_OVERFLOW (arg1)
&& ! TREE_CONSTANT_OVERFLOW (arg2) && ! TREE_CONSTANT_OVERFLOW (arg2)
&& int1h == 0 && int1l >= 0) && int1h == 0 && int1l >= 0)
{ {
if (code == CEIL_DIV_EXPR) if (code == CEIL_DIV_EXPR)
int1l += int2l-1; int1l += int2l - 1;
return size_int (int1l / int2l); low = int1l / int2l, hi = 0;
break;
} }
/* ... fall through ... */
case ROUND_DIV_EXPR: case ROUND_DIV_EXPR:
if (int2h == 0 && int2l == 1) if (int2h == 0 && int2l == 1)
{ {
t = build_int_2 (int1l, int1h); low = int1l, hi = int1h;
break; break;
} }
if (int1l == int2l && int1h == int2h) if (int1l == int2l && int1h == int2h
&& ! (int1l == 0 && int1h == 0))
{ {
if ((int1l | int1h) == 0) low = 1, hi = 0;
abort ();
t = build_int_2 (1, 0);
break; break;
} }
overflow = div_and_round_double (code, uns, overflow = div_and_round_double (code, uns,
int1l, int1h, int2l, int2h, int1l, int1h, int2l, int2h,
&low, &hi, &garbagel, &garbageh); &low, &hi, &garbagel, &garbageh);
t = build_int_2 (low, hi);
break; break;
case TRUNC_MOD_EXPR: case ROUND_MOD_EXPR: case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR: case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:
/* This is a shortcut for a common special case. */
if (int2h == 0 && int2l > 0
&& ! TREE_CONSTANT_OVERFLOW (arg1)
&& ! TREE_CONSTANT_OVERFLOW (arg2)
&& int1h == 0 && int1l >= 0)
{
if (code == CEIL_MOD_EXPR)
int1l += int2l - 1;
low = int1l % int2l, hi = 0;
break;
}
/* ... fall through ... */
case ROUND_MOD_EXPR:
overflow = div_and_round_double (code, uns, overflow = div_and_round_double (code, uns,
int1l, int1h, int2l, int2h, int1l, int1h, int2l, int2h,
&garbagel, &garbageh, &low, &hi); &garbagel, &garbageh, &low, &hi);
t = build_int_2 (low, hi);
break; break;
case MIN_EXPR: case MIN_EXPR:
...@@ -1225,18 +1202,29 @@ const_binop (code, arg1, arg2, notrunc) ...@@ -1225,18 +1202,29 @@ const_binop (code, arg1, arg2, notrunc)
< (unsigned HOST_WIDE_INT) int2l))); < (unsigned HOST_WIDE_INT) int2l)));
} }
if (low == (code == MIN_EXPR)) if (low == (code == MIN_EXPR))
t = build_int_2 (int1l, int1h); low = int1l, hi = int1h;
else else
t = build_int_2 (int2l, int2h); low = int2l, hi = int2h;
break; break;
default: default:
abort (); abort ();
} }
got_it: got_it:
TREE_TYPE (t) = TREE_TYPE (arg1); if (TREE_TYPE (arg1) == sizetype && hi == 0
&& low <= TREE_INT_CST_LOW (TYPE_MAX_VALUE (sizetype))
&& ! overflow
&& ! TREE_OVERFLOW (arg1) && ! TREE_OVERFLOW (arg2))
t = size_int (low);
else
{
t = build_int_2 (low, hi);
TREE_TYPE (t) = TREE_TYPE (arg1);
}
TREE_OVERFLOW (t) TREE_OVERFLOW (t)
= ((notrunc ? !uns && overflow : force_fit_type (t, overflow && !uns)) = ((notrunc ? !uns && overflow
: force_fit_type (t, overflow && !uns) && ! no_overflow)
| TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg1)
| TREE_OVERFLOW (arg2)); | TREE_OVERFLOW (arg2));
TREE_CONSTANT_OVERFLOW (t) = (TREE_OVERFLOW (t) TREE_CONSTANT_OVERFLOW (t) = (TREE_OVERFLOW (t)
...@@ -1430,6 +1418,7 @@ size_int (number) ...@@ -1430,6 +1418,7 @@ size_int (number)
{ {
t = build_int_2 (number, 0); t = build_int_2 (number, 0);
TREE_TYPE (t) = sizetype; TREE_TYPE (t) = sizetype;
TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0);
} }
return t; return t;
} }
...@@ -4018,7 +4007,6 @@ fold (expr) ...@@ -4018,7 +4007,6 @@ fold (expr)
} }
else if (TREE_CODE (arg0) == REAL_CST) else if (TREE_CODE (arg0) == REAL_CST)
t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0))); t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
TREE_TYPE (t) = type;
} }
else if (TREE_CODE (arg0) == NEGATE_EXPR) else if (TREE_CODE (arg0) == NEGATE_EXPR)
return TREE_OPERAND (arg0, 0); return TREE_OPERAND (arg0, 0);
...@@ -4057,7 +4045,6 @@ fold (expr) ...@@ -4057,7 +4045,6 @@ fold (expr)
t = build_real (type, t = build_real (type,
REAL_VALUE_NEGATE (TREE_REAL_CST (arg0))); REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
} }
TREE_TYPE (t) = type;
} }
else if (TREE_CODE (arg0) == ABS_EXPR || TREE_CODE (arg0) == NEGATE_EXPR) else if (TREE_CODE (arg0) == ABS_EXPR || TREE_CODE (arg0) == NEGATE_EXPR)
return build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0)); return build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0));
...@@ -4090,9 +4077,8 @@ fold (expr) ...@@ -4090,9 +4077,8 @@ fold (expr)
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
if (wins) if (wins)
{ {
if (TREE_CODE (arg0) == INTEGER_CST) t = build_int_2 (~ TREE_INT_CST_LOW (arg0),
t = build_int_2 (~ TREE_INT_CST_LOW (arg0), ~ TREE_INT_CST_HIGH (arg0));
~ TREE_INT_CST_HIGH (arg0));
TREE_TYPE (t) = type; TREE_TYPE (t) = type;
force_fit_type (t, 0); force_fit_type (t, 0);
TREE_OVERFLOW (t) = TREE_OVERFLOW (arg0); TREE_OVERFLOW (t) = TREE_OVERFLOW (arg0);
...@@ -4259,7 +4245,9 @@ fold (expr) ...@@ -4259,7 +4245,9 @@ fold (expr)
{ {
/* The return value should always have /* The return value should always have
the same type as the original expression. */ the same type as the original expression. */
TREE_TYPE (t1) = TREE_TYPE (t); if (TREE_TYPE (t1) != TREE_TYPE (t))
t1 = convert (TREE_TYPE (t), t1);
return t1; return t1;
} }
return t; return t;
...@@ -5091,6 +5079,9 @@ fold (expr) ...@@ -5091,6 +5079,9 @@ fold (expr)
case LE_EXPR: case LE_EXPR:
if (INTEGRAL_TYPE_P (TREE_TYPE (arg0))) if (INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
{ {
if (type == integer_type_node)
return integer_one_node;
t = build_int_2 (1, 0); t = build_int_2 (1, 0);
TREE_TYPE (t) = type; TREE_TYPE (t) = type;
return t; return t;
...@@ -5106,6 +5097,9 @@ fold (expr) ...@@ -5106,6 +5097,9 @@ fold (expr)
/* ... fall through ... */ /* ... fall through ... */
case GT_EXPR: case GT_EXPR:
case LT_EXPR: case LT_EXPR:
if (type == integer_type_node)
return integer_zero_node;
t = build_int_2 (0, 0); t = build_int_2 (0, 0);
TREE_TYPE (t) = type; TREE_TYPE (t) = type;
return t; return t;
......
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