/* Fold a constant sub-tree into a single node for C-compiler
- Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
#define BRANCH_COST 1
#endif
-/* Yield nonzero if a signed left shift of A by B bits overflows. */
-#define left_shift_overflows(a, b) ((a) != ((a) << (b)) >> (b))
-
/* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow.
Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1.
Then this yields nonzero if overflow occurred during the addition.
register tree arg1, arg2;
int notrunc;
{
+ STRIP_NOPS (arg1); STRIP_NOPS (arg2);
+
if (TREE_CODE (arg1) == INTEGER_CST)
{
register HOST_WIDE_INT int1l = TREE_INT_CST_LOW (arg1);
REAL_VALUE_TYPE x;
REAL_VALUE_TYPE l;
REAL_VALUE_TYPE u;
+ tree type1 = TREE_TYPE (arg1);
x = TREE_REAL_CST (arg1);
- l = real_value_from_int_cst (TYPE_MIN_VALUE (type));
- u = real_value_from_int_cst (TYPE_MAX_VALUE (type));
+ l = real_value_from_int_cst (type1, TYPE_MIN_VALUE (type));
+ u = real_value_from_int_cst (type1, TYPE_MAX_VALUE (type));
/* See if X will be in range after truncation towards 0.
To compensate for truncation, move the bounds away from 0,
but reject if X exactly equals the adjusted bounds. */
if (TREE_CODE (arg1) == REAL_CST)
{
if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
- return arg1;
+ {
+ t = arg1;
+ TREE_TYPE (arg1) = type;
+ return t;
+ }
else if (setjmp (float_error))
{
overflow = 1;
TREE_TYPE (t) = type;
TREE_OVERFLOW (t)
= (TREE_OVERFLOW (arg0)
- | force_fit_type (t, overflow));
+ | force_fit_type (t, overflow && !TREE_UNSIGNED (type)));
TREE_CONSTANT_OVERFLOW (t)
= TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0);
}
case BIT_IOR_EXPR:
bit_ior:
+ {
+ register enum tree_code code0, code1;
+
if (integer_all_onesp (arg1))
return omit_one_operand (type, arg1, arg0);
if (integer_zerop (arg1))
if (t1 != NULL_TREE)
return t1;
- /* (a << C1) | (a >> C2) if A is unsigned and C1+C2 is the size of A
+ /* (A << C1) | (A >> C2) if A is unsigned and C1+C2 is the size of A
is a rotate of A by C1 bits. */
+ /* (A << B) | (A >> (Z - B)) if A is unsigned and Z is the size of A
+ is a rotate of A by B bits. */
- if ((TREE_CODE (arg0) == RSHIFT_EXPR
- || TREE_CODE (arg0) == LSHIFT_EXPR)
- && (TREE_CODE (arg1) == RSHIFT_EXPR
- || TREE_CODE (arg1) == LSHIFT_EXPR)
- && TREE_CODE (arg0) != TREE_CODE (arg1)
+ code0 = TREE_CODE (arg0);
+ code1 = TREE_CODE (arg1);
+ if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
+ || (code1 == RSHIFT_EXPR && code0 == LSHIFT_EXPR))
&& operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1,0), 0)
- && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0)))
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
- && TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1)) == 0
- && TREE_INT_CST_HIGH (TREE_OPERAND (arg1, 1)) == 0
- && ((TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1))
- + TREE_INT_CST_LOW (TREE_OPERAND (arg1, 1)))
+ && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+ {
+ register tree tree01, tree11;
+ register enum tree_code code01, code11;
+
+ tree01 = TREE_OPERAND (arg0, 1);
+ tree11 = TREE_OPERAND (arg1, 1);
+ code01 = TREE_CODE (tree01);
+ code11 = TREE_CODE (tree11);
+ if (code01 == INTEGER_CST
+ && code11 == INTEGER_CST
+ && TREE_INT_CST_HIGH (tree01) == 0
+ && TREE_INT_CST_HIGH (tree11) == 0
+ && ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
- return build (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
- TREE_CODE (arg0) == LSHIFT_EXPR
- ? TREE_OPERAND (arg0, 1) : TREE_OPERAND (arg1, 1));
+ return build (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
+ code0 == LSHIFT_EXPR ? tree01 : tree11);
+ else if (code11 == MINUS_EXPR
+ && TREE_CODE (TREE_OPERAND (tree11, 0)) == INTEGER_CST
+ && TREE_INT_CST_HIGH (TREE_OPERAND (tree11, 0)) == 0
+ && TREE_INT_CST_LOW (TREE_OPERAND (tree11, 0))
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))
+ && operand_equal_p (tree01, TREE_OPERAND (tree11, 1), 0))
+ return build (code0 == LSHIFT_EXPR ? LROTATE_EXPR : RROTATE_EXPR,
+ type, TREE_OPERAND (arg0, 0), tree01);
+ else if (code01 == MINUS_EXPR
+ && TREE_CODE (TREE_OPERAND (tree01, 0)) == INTEGER_CST
+ && TREE_INT_CST_HIGH (TREE_OPERAND (tree01, 0)) == 0
+ && TREE_INT_CST_LOW (TREE_OPERAND (tree01, 0))
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))
+ && operand_equal_p (tree11, TREE_OPERAND (tree01, 1), 0))
+ return build (code0 != LSHIFT_EXPR ? LROTATE_EXPR : RROTATE_EXPR,
+ type, TREE_OPERAND (arg0, 0), tree11);
+ }
goto associate;
+ }
case BIT_XOR_EXPR:
if (integer_zerop (arg1))
tree c2 = integer_zero_node;
tree xarg0 = arg0;
- if (TREE_CODE (xarg0) == SAVE_EXPR)
+ if (TREE_CODE (xarg0) == SAVE_EXPR && SAVE_EXPR_RTL (xarg0) == 0)
have_save_expr = 1, xarg0 = TREE_OPERAND (xarg0, 0);
STRIP_NOPS (xarg0);
xarg0 = TREE_OPERAND (xarg0, 0);
}
- if (TREE_CODE (xarg0) == SAVE_EXPR)
+ if (TREE_CODE (xarg0) == SAVE_EXPR && SAVE_EXPR_RTL (xarg0) == 0)
have_save_expr = 1, xarg0 = TREE_OPERAND (xarg0, 0);
STRIP_NOPS (xarg0);