/* 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.
register tree t;
int uns = TREE_UNSIGNED (TREE_TYPE (arg1));
int overflow = 0;
+ int no_overflow = 0;
switch (code)
{
case BIT_IOR_EXPR:
- t = build_int_2 (int1l | int2l, int1h | int2h);
+ low = int1l | int2l, hi = int1h | int2h;
break;
case BIT_XOR_EXPR:
- t = build_int_2 (int1l ^ int2l, int1h ^ int2h);
+ low = int1l ^ int2l, hi = int1h ^ int2h;
break;
case BIT_AND_EXPR:
- t = build_int_2 (int1l & int2l, int1h & int2h);
+ low = int1l & int2l, hi = int1h & int2h;
break;
case BIT_ANDTC_EXPR:
- t = build_int_2 (int1l & ~int2l, int1h & ~int2h);
+ low = int1l & ~int2l, hi = int1h & ~int2h;
break;
case RSHIFT_EXPR:
TYPE_PRECISION (TREE_TYPE (arg1)),
&low, &hi,
!uns);
- t = build_int_2 (low, hi);
- TREE_TYPE (t) = TREE_TYPE (arg1);
- 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;
+ no_overflow = 1;
+ break;
case RROTATE_EXPR:
int2l = - int2l;
lrotate_double (int1l, int1h, int2l,
TYPE_PRECISION (TREE_TYPE (arg1)),
&low, &hi);
- t = build_int_2 (low, hi);
break;
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);
- t = build_int_2 (low, hi);
break;
case MINUS_EXPR:
- if (int2h == 0 && int2l == 0)
- {
- t = build_int_2 (int1l, int1h);
- break;
- }
neg_double (int2l, int2h, &low, &hi);
add_double (int1l, int1h, low, hi, &low, &hi);
overflow = overflow_sum_sign (hi, int2h, int1h);
- t = build_int_2 (low, hi);
break;
case MULT_EXPR:
overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi);
- t = build_int_2 (low, hi);
break;
case TRUNC_DIV_EXPR:
case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:
case EXACT_DIV_EXPR:
- /* This is a shortcut for a common special case.
- It reduces the number of tree nodes generated
- and saves time. */
+ /* This is a shortcut for a common special case. */
if (int2h == 0 && int2l > 0
- && TREE_TYPE (arg1) == sizetype
&& ! TREE_CONSTANT_OVERFLOW (arg1)
&& ! TREE_CONSTANT_OVERFLOW (arg2)
&& int1h == 0 && int1l >= 0)
{
if (code == CEIL_DIV_EXPR)
- int1l += int2l-1;
- return size_int (int1l / int2l);
+ int1l += int2l - 1;
+ low = int1l / int2l, hi = 0;
+ break;
}
+
+ /* ... fall through ... */
+
case ROUND_DIV_EXPR:
if (int2h == 0 && int2l == 1)
{
- t = build_int_2 (int1l, int1h);
+ low = int1l, hi = int1h;
break;
}
- if (int1l == int2l && int1h == int2h)
+ if (int1l == int2l && int1h == int2h
+ && ! (int1l == 0 && int1h == 0))
{
- if ((int1l | int1h) == 0)
- abort ();
- t = build_int_2 (1, 0);
+ low = 1, hi = 0;
break;
}
overflow = div_and_round_double (code, uns,
int1l, int1h, int2l, int2h,
&low, &hi, &garbagel, &garbageh);
- t = build_int_2 (low, hi);
break;
- case TRUNC_MOD_EXPR: case ROUND_MOD_EXPR:
+ case TRUNC_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,
int1l, int1h, int2l, int2h,
&garbagel, &garbageh, &low, &hi);
- t = build_int_2 (low, hi);
break;
case MIN_EXPR:
< (unsigned HOST_WIDE_INT) int2l)));
}
if (low == (code == MIN_EXPR))
- t = build_int_2 (int1l, int1h);
+ low = int1l, hi = int1h;
else
- t = build_int_2 (int2l, int2h);
+ low = int2l, hi = int2h;
break;
default:
abort ();
}
got_it:
- TREE_TYPE (t) = TREE_TYPE (arg1);
+ if (TREE_TYPE (arg1) == sizetype && hi == 0
+ && low >= 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)
- = ((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 (arg2));
TREE_CONSTANT_OVERFLOW (t) = (TREE_OVERFLOW (t)
{
t = build_int_2 (number, 0);
TREE_TYPE (t) = sizetype;
+ TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0);
}
return t;
}
STRIP_NOPS (arg0);
STRIP_NOPS (arg1);
- /* If ARG0 and ARG1 are the same SAVE_EXPR, they are necessarily equal.
- We don't care about side effects in that case because the SAVE_EXPR
- takes care of that for us. */
- if (TREE_CODE (arg0) == SAVE_EXPR && arg0 == arg1)
- return ! only_const;
-
- if (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1))
+ if (TREE_CODE (arg0) != TREE_CODE (arg1)
+ /* This is needed for conversions and for COMPONENT_REF.
+ Might as well play it safe and always test this. */
+ || TYPE_MODE (TREE_TYPE (arg0)) != TYPE_MODE (TREE_TYPE (arg1)))
return 0;
- if (TREE_CODE (arg0) == TREE_CODE (arg1)
- && TREE_CODE (arg0) == ADDR_EXPR
- && TREE_OPERAND (arg0, 0) == TREE_OPERAND (arg1, 0))
- return 1;
-
- if (TREE_CODE (arg0) == TREE_CODE (arg1)
- && TREE_CODE (arg0) == INTEGER_CST
- && TREE_INT_CST_LOW (arg0) == TREE_INT_CST_LOW (arg1)
- && TREE_INT_CST_HIGH (arg0) == TREE_INT_CST_HIGH (arg1))
+ /* If ARG0 and ARG1 are the same SAVE_EXPR, they are necessarily equal.
+ We don't care about side effects in that case because the SAVE_EXPR
+ takes care of that for us. In all other cases, two expressions are
+ equal if they have no side effects. If we have two identical
+ expressions with side effects that should be treated the same due
+ to the only side effects being identical SAVE_EXPR's, that will
+ be detected in the recursive calls below. */
+ if (arg0 == arg1 && ! only_const
+ && (TREE_CODE (arg0) == SAVE_EXPR
+ || (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1))))
return 1;
- /* Detect when real constants are equal. */
- if (TREE_CODE (arg0) == TREE_CODE (arg1)
- && TREE_CODE (arg0) == REAL_CST)
- return !bcmp ((char *) &TREE_REAL_CST (arg0),
- (char *) &TREE_REAL_CST (arg1),
- sizeof (REAL_VALUE_TYPE));
+ /* Next handle constant cases, those for which we can return 1 even
+ if ONLY_CONST is set. */
+ if (TREE_CONSTANT (arg0) && TREE_CONSTANT (arg1))
+ switch (TREE_CODE (arg0))
+ {
+ case INTEGER_CST:
+ return (! TREE_CONSTANT_OVERFLOW (arg0)
+ && ! TREE_CONSTANT_OVERFLOW (arg1)
+ && TREE_INT_CST_LOW (arg0) == TREE_INT_CST_LOW (arg1)
+ && TREE_INT_CST_HIGH (arg0) == TREE_INT_CST_HIGH (arg1));
+
+ case REAL_CST:
+ return (! TREE_CONSTANT_OVERFLOW (arg0)
+ && ! TREE_CONSTANT_OVERFLOW (arg1)
+ && REAL_VALUES_EQUAL (TREE_REAL_CST (arg0),
+ TREE_REAL_CST (arg1)));
+
+ case COMPLEX_CST:
+ return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1),
+ only_const)
+ && operand_equal_p (TREE_IMAGPART (arg0), TREE_IMAGPART (arg1),
+ only_const));
+
+ case STRING_CST:
+ return (TREE_STRING_LENGTH (arg0) == TREE_STRING_LENGTH (arg1)
+ && ! strncmp (TREE_STRING_POINTER (arg0),
+ TREE_STRING_POINTER (arg1),
+ TREE_STRING_LENGTH (arg0)));
+
+ case ADDR_EXPR:
+ return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0),
+ 0);
+ }
if (only_const)
return 0;
- if (arg0 == arg1)
- return 1;
-
- if (TREE_CODE (arg0) != TREE_CODE (arg1))
- return 0;
- /* This is needed for conversions and for COMPONENT_REF.
- Might as well play it safe and always test this. */
- if (TYPE_MODE (TREE_TYPE (arg0)) != TYPE_MODE (TREE_TYPE (arg1)))
- return 0;
-
switch (TREE_CODE_CLASS (TREE_CODE (arg0)))
{
case '1':
case '<':
case '2':
- return (operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0), 0)
+ if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0)
+ && operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1),
+ 0))
+ return 1;
+
+ /* For commutative ops, allow the other order. */
+ return ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MULT_EXPR
+ || TREE_CODE (arg0) == MIN_EXPR || TREE_CODE (arg0) == MAX_EXPR
+ || TREE_CODE (arg0) == BIT_IOR_EXPR
+ || TREE_CODE (arg0) == BIT_XOR_EXPR
+ || TREE_CODE (arg0) == BIT_AND_EXPR
+ || TREE_CODE (arg0) == NE_EXPR || TREE_CODE (arg0) == EQ_EXPR)
+ && operand_equal_p (TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 1), 0)
&& operand_equal_p (TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1), 0));
+ TREE_OPERAND (arg1, 0), 0));
case 'r':
switch (TREE_CODE (arg0))
enum machine_mode lmode, rmode, lnmode, rnmode;
int lunsignedp, runsignedp;
int lvolatilep = 0, rvolatilep = 0;
+ int alignment;
tree linner, rinner;
tree mask;
tree offset;
if the same as the size of the underlying object, we aren't doing an
extraction at all and so can do nothing. */
linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
- &lunsignedp, &lvolatilep);
+ &lunsignedp, &lvolatilep, &alignment);
if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
|| offset != 0)
return 0;
{
/* If this is not a constant, we can only do something if bit positions,
sizes, and signedness are the same. */
- rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset,
- &rmode, &runsignedp, &rvolatilep);
+ rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
+ &runsignedp, &rvolatilep, &alignment);
if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
|| lunsignedp != runsignedp || offset != 0)
tree mask, inner, offset;
tree unsigned_type;
int precision;
+ int alignment;
/* All the optimizations using this function assume integer fields.
There are problems with FP fields since the type_for_size call
inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
- punsignedp, pvolatilep);
+ punsignedp, pvolatilep, &alignment);
if ((inner == exp && and_mask == 0)
|| *pbitsize < 0 || offset != 0)
return 0;
for neither. Then compute our result treating them as never equal
and comparing bounds to non-bounds as above. */
sgn0 = arg0 != 0 ? 0 : (upper0_p ? 1 : -1);
- sgn1 = arg1 != 0 ? 1 : (upper1_p ? 1 : -1);
+ sgn1 = arg1 != 0 ? 0 : (upper1_p ? 1 : -1);
switch (code)
{
case EQ_EXPR: case NE_EXPR:
{
code = TREE_CODE (exp);
arg0 = TREE_OPERAND (exp, 0), arg1 = TREE_OPERAND (exp, 1);
- if (arg0 != 0 && tree_code_length[(int) code] > 0)
+ if (TREE_CODE_CLASS (code) == '<' || TREE_CODE_CLASS (code) == '1'
+ || TREE_CODE_CLASS (code) == '2')
type = TREE_TYPE (arg0);
switch (code)
break;
}
+ /* If EXP is a constant, we can evaluate whether this is true or false. */
+ if (TREE_CODE (exp) == INTEGER_CST)
+ {
+ in_p = in_p == (integer_onep (range_binop (GE_EXPR, integer_type_node,
+ exp, 0, low, 0))
+ && integer_onep (range_binop (LE_EXPR, integer_type_node,
+ exp, 1, high, 1)));
+ low = high = 0;
+ exp = 0;
+ }
+
*pin_p = in_p, *plow = low, *phigh = high;
return exp;
}
/* If they don't overlap, the result is the first range. If the
second range is a subset of the first, we can't describe this as
a single range unless both ranges end at the same place. If both
- ranges also start in the same place, then the result is false.
+ ranges start in the same place, then the result is false.
Otherwise, we go from the start of the first range to just before
the start of the second. */
if (no_overlap)
&& integer_zerop (range_binop (EQ_EXPR, integer_type_node,
high0, 1, high1, 0)))
return 0;
- else if (subset
- && integer_onep (range_binop (EQ_EXPR, integer_type_node,
- low0, 0, low1, 0)))
+ else if (integer_onep (range_binop (EQ_EXPR, integer_type_node,
+ low0, 0, low1, 0)))
in_p = 0, low = high = 0;
else
{
in0_p = ! in0_p, in1_p = ! in1_p;
/* If both expressions are the same, if we can merge the ranges, and we
- can build the range test, return it or it inverted. */
- if (operand_equal_p (lhs, rhs, 0)
+ can build the range test, return it or it inverted. If one of the
+ ranges is always true or always false, consider it to be the same
+ expression as the other. */
+ if ((lhs == 0 || rhs == 0 || operand_equal_p (lhs, rhs, 0))
&& merge_ranges (&in_p, &low, &high, in0_p, low0, high0,
in1_p, low1, high1)
- && 0 != (tem = (build_range_check (TREE_TYPE (exp), lhs,
+ && 0 != (tem = (build_range_check (TREE_TYPE (exp),
+ lhs != 0 ? lhs
+ : rhs != 0 ? rhs : integer_zero_node,
in_p, low, high))))
return or_op ? invert_truthvalue (tem) : tem;
if (p == modesize || unsignedp)
return c;
- if (TREE_UNSIGNED (type))
- c = convert (signed_type (type), c);
-
/* We work by getting just the sign bit into the low-order bit, then
into the high-order bit, then sign-extend. We then XOR that value
with C. */
temp = const_binop (RSHIFT_EXPR, c, size_int (p - 1), 0);
temp = const_binop (BIT_AND_EXPR, temp, size_int (1), 0);
+
+ /* We must use a signed type in order to get an arithmetic right shift.
+ However, we must also avoid introducing accidental overflows, so that
+ a subsequent call to integer_zerop will work. Hence we must
+ do the type conversion here. At this point, the constant is either
+ zero or one, and the conversion to a signed type can never overflow.
+ We could get an overflow if this conversion is done anywhere else. */
+ if (TREE_UNSIGNED (type))
+ temp = convert (signed_type (type), temp);
+
temp = const_binop (LSHIFT_EXPR, temp, size_int (modesize - 1), 0);
temp = const_binop (RSHIFT_EXPR, temp, size_int (modesize - p - 1), 0);
if (mask != 0)
temp = const_binop (BIT_AND_EXPR, temp, convert (TREE_TYPE (c), mask), 0);
+ /* If necessary, convert the type back to match the type of C. */
+ if (TREE_UNSIGNED (type))
+ temp = convert (type, temp);
return convert (type, const_binop (BIT_XOR_EXPR, c, temp, 0));
}
fold (build (code, type,
arg0, TREE_OPERAND (arg1, 1))));
else if (TREE_CODE (arg1) == COND_EXPR
- || TREE_CODE_CLASS (TREE_CODE (arg1)) == '<')
+ || (TREE_CODE_CLASS (TREE_CODE (arg1)) == '<'
+ && TREE_CODE_CLASS (code) != '<'))
{
tree test, true_value, false_value;
return build (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
fold (build (code, type, TREE_OPERAND (arg0, 1), arg1)));
else if (TREE_CODE (arg0) == COND_EXPR
- || TREE_CODE_CLASS (TREE_CODE (arg0)) == '<')
+ || (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
+ && TREE_CODE_CLASS (code) != '<'))
{
tree test, true_value, false_value;
}
else if (TREE_CODE (arg0) == REAL_CST)
t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
- TREE_TYPE (t) = type;
}
else if (TREE_CODE (arg0) == NEGATE_EXPR)
return TREE_OPERAND (arg0, 0);
t = build_real (type,
REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
}
- TREE_TYPE (t) = type;
}
else if (TREE_CODE (arg0) == ABS_EXPR || TREE_CODE (arg0) == NEGATE_EXPR)
return build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0));
case BIT_NOT_EXPR:
if (wins)
{
- if (TREE_CODE (arg0) == INTEGER_CST)
- t = build_int_2 (~ TREE_INT_CST_LOW (arg0),
- ~ TREE_INT_CST_HIGH (arg0));
+ t = build_int_2 (~ TREE_INT_CST_LOW (arg0),
+ ~ TREE_INT_CST_HIGH (arg0));
TREE_TYPE (t) = type;
force_fit_type (t, 0);
TREE_OVERFLOW (t) = TREE_OVERFLOW (arg0);
{
/* The return value should always have
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 t;
must be evaluated. */
if (integer_zerop (arg1))
return omit_one_operand (type, arg1, arg0);
+ /* Likewise for first arg, but note that only the TRUTH_AND_EXPR
+ case will be handled here. */
+ if (integer_zerop (arg0))
+ return omit_one_operand (type, arg0, arg1);
truth_andor:
/* We only do these simplifications if we are optimizing. */
evaluate first arg. */
if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1))
return omit_one_operand (type, arg1, arg0);
+ /* Likewise for first arg, but note this only occurs here for
+ TRUTH_OR_EXPR. */
+ if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
+ return omit_one_operand (type, arg0, arg1);
goto truth_andor;
case TRUTH_XOR_EXPR:
case LE_EXPR:
if (INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
{
+ if (type == integer_type_node)
+ return integer_one_node;
+
t = build_int_2 (1, 0);
TREE_TYPE (t) = type;
return t;
/* ... fall through ... */
case GT_EXPR:
case LT_EXPR:
+ if (type == integer_type_node)
+ return integer_zero_node;
+
t = build_int_2 (0, 0);
TREE_TYPE (t) = type;
return t;
0);
}
+#if 0 /* This is no longer useful, but breaks some real code. */
/* Assume a nonexplicit constant cannot equal an explicit one,
since such code would be undefined anyway.
Exception: on sysvr4, using #pragma weak,
&& TREE_CODE (arg0) == ADDR_EXPR
&& code == EQ_EXPR)
t1 = build_int_2 (0, 0);
-
+#endif
/* Two real constants can be compared explicitly. */
else if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
{