/* Fold a constant sub-tree into a single node for C-compiler
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "flags.h"
#include "tree.h"
#include "rtl.h"
+#include "expr.h"
#include "tm_p.h"
#include "toplev.h"
#include "ggc.h"
static int multiple_of_p PARAMS ((tree, tree, tree));
static tree constant_boolean_node PARAMS ((int, tree));
static int count_cond PARAMS ((tree, int));
-
+static tree fold_binary_op_with_conditional_arg
+ PARAMS ((enum tree_code, tree, tree, tree, int));
+
#ifndef BRANCH_COST
#define BRANCH_COST 1
#endif
TREE_INT_CST_LOW (t) &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
}
- /* Unsigned types do not suffer sign extension or overflow. */
- if (TREE_UNSIGNED (TREE_TYPE (t)))
+ /* Unsigned types do not suffer sign extension or overflow unless they
+ are a sizetype. */
+ if (TREE_UNSIGNED (TREE_TYPE (t))
+ && ! (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (TREE_TYPE (t))))
return overflow;
/* If the value's sign bit is set, extend the sign. */
encode (arg1, l1, h1);
encode (arg2, l2, h2);
- bzero ((char *) prod, sizeof prod);
+ memset ((char *) prod, 0, sizeof prod);
for (i = 0; i < 4; i++)
{
goto finish_up;
}
- bzero ((char *) quo, sizeof quo);
+ memset ((char *) quo, 0, sizeof quo);
- bzero ((char *) num, sizeof num); /* to zero 9th element */
- bzero ((char *) den, sizeof den);
+ memset ((char *) num, 0, sizeof num); /* to zero 9th element */
+ memset ((char *) den, 0, sizeof den);
encode (num, lnum, hnum);
encode (den, lden, hden);
{
/* Don't do the optimization if there was an arithmetic error. */
fail:
- set_float_handler (NULL_PTR);
+ set_float_handler (NULL);
return 0;
}
set_float_handler (float_error);
#endif
/* Output the reciprocal and return success flag. */
- set_float_handler (NULL_PTR);
+ set_float_handler (NULL);
*r = y.d;
return 1;
}
-/* Convert C9X hexadecimal floating point string constant S. Return
+/* Convert C99 hexadecimal floating point string constant S. Return
real value type in mode MODE. This function uses the host computer's
floating point arithmetic when there is no REAL_ARITHMETIC. */
case MINUS_EXPR:
/* - (A - B) -> B - A */
- if (! FLOAT_TYPE_P (type) || flag_fast_math)
+ if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
return convert (type,
fold (build (MINUS_EXPR, TREE_TYPE (t),
TREE_OPERAND (t, 1),
if (TREE_CODE (in) == INTEGER_CST || TREE_CODE (in) == REAL_CST)
*litp = in;
- else if (TREE_CONSTANT (in))
- *conp = in;
-
else if (TREE_CODE (in) == code
|| (! FLOAT_TYPE_P (TREE_TYPE (in))
/* We can associate addition and subtraction together (even
if (neg_conp_p) *conp = negate_expr (*conp);
if (neg_var_p) var = negate_expr (var);
}
+ else if (TREE_CONSTANT (in))
+ *conp = in;
else
var = in;
abort ();
}
- if (forsize && hi == 0 && low < 10000)
+ if (forsize && hi == 0 && low < 10000
+ && overflow == 0 && ! TREE_OVERFLOW (arg1) && ! TREE_OVERFLOW (arg2))
return size_int_type_wide (low, TREE_TYPE (arg1));
else
{
static int init_p = 0;
tree t;
- if (ggc_p && ! init_p)
+ if (! init_p)
{
ggc_add_tree_root ((tree *) size_table,
sizeof size_table / sizeof (tree));
/* If this is a positive number that fits in the table we use to hold
cached entries, see if it is already in the table and put it there
if not. */
- if (number >= 0 && number < (int) (sizeof size_table / sizeof size_table[0]))
+ if (number >= 0 && number < (int) ARRAY_SIZE (size_table))
{
if (size_table[number] != 0)
for (t = size_table[number]; t != 0; t = TREE_CHAIN (t))
if (TREE_TYPE (t) == type)
return t;
- if (! ggc_p)
- {
- /* Make this a permanent node. */
- push_obstacks_nochange ();
- end_temporary_allocation ();
- }
-
t = build_int_2 (number, 0);
TREE_TYPE (t) = type;
TREE_CHAIN (t) = size_table[number];
size_table[number] = t;
- if (! ggc_p)
- pop_obstacks ();
-
return t;
}
/* If we are trying to make a sizetype for a small integer, use
size_int to pick up cached types to reduce duplicate nodes. */
- if (TREE_CODE (type) == INTEGER_CST && TYPE_IS_SIZETYPE (type)
+ if (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)
+ && !TREE_CONSTANT_OVERFLOW (arg1)
&& compare_tree_int (arg1, 10000) < 0)
return size_int_type_wide (TREE_INT_CST_LOW (arg1), type);
if (TREE_CODE_CLASS (code) == '<')
{
if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
- && !flag_fast_math && code != NE_EXPR && code != EQ_EXPR)
+ && !flag_unsafe_math_optimizations
+ && code != NE_EXPR
+ && code != EQ_EXPR)
return build1 (TRUTH_NOT_EXPR, type, arg);
else
return build (invert_tree_comparison (code), type,
short-circuited branch and the underlying object on both sides
is the same, make a non-short-circuit operation. */
else if (BRANCH_COST >= 2
+ && lhs != 0 && rhs != 0
&& (TREE_CODE (exp) == TRUTH_ANDIF_EXPR
|| TREE_CODE (exp) == TRUTH_ORIF_EXPR)
&& operand_equal_p (lhs, rhs, 0))
|| TREE_CODE_CLASS (TREE_CODE (op0)) == '2'
|| TREE_CODE_CLASS (TREE_CODE (op0)) == 'e')
&& TREE_UNSIGNED (TREE_TYPE (op0))
- && ! TYPE_IS_SIZETYPE (TREE_TYPE (op0))
+ && ! (TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (TREE_TYPE (op0)))
&& (GET_MODE_SIZE (TYPE_MODE (ctype))
> GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))))
break;
if (SAVE_EXPR_RTL (t) == 0 && ! TREE_SIDE_EFFECTS (TREE_OPERAND (t, 0))
&& 0 != (t1 = extract_muldiv (TREE_OPERAND (t, 0), c, code,
wide_type)))
- return save_expr (t1);
+ {
+ t1 = save_expr (t1);
+ if (SAVE_EXPR_PERSISTENT_P (t) && TREE_CODE (t1) == SAVE_EXPR)
+ SAVE_EXPR_PERSISTENT_P (t1) = 1;
+ if (is_pending_size (t))
+ put_pending_size (t1);
+ return t1;
+ }
break;
case LSHIFT_EXPR: case RSHIFT_EXPR:
constant. */
t1 = extract_muldiv (op0, c, code, wide_type);
t2 = extract_muldiv (op1, c, code, wide_type);
- if (t1 != 0 && t2 != 0)
+ if (t1 != 0 && t2 != 0
+ && (code == MULT_EXPR
+ /* If not multiplication, we can only do this if either operand
+ is divisible by c. */
+ || multiple_of_p (ctype, op0, c)
+ || multiple_of_p (ctype, op1, c)))
return fold (build (tcode, ctype, convert (ctype, t1),
convert (ctype, t2)));
the operation since it will change the result if the original
computation overflowed. */
if (TREE_UNSIGNED (ctype)
- && ! TYPE_IS_SIZETYPE (ctype)
+ && ! (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype))
&& ctype != type)
break;
this since it will change the result if the original computation
overflowed. */
if ((! TREE_UNSIGNED (ctype)
- || TYPE_IS_SIZETYPE (ctype))
+ || (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype)))
&& ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
|| (tcode == MULT_EXPR
&& code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR
tree expr;
int lim;
{
- int true, false;
+ int ctrue, cfalse;
if (TREE_CODE (expr) != COND_EXPR)
return 0;
else if (lim <= 0)
return 0;
- true = count_cond (TREE_OPERAND (expr, 1), lim - 1);
- false = count_cond (TREE_OPERAND (expr, 2), lim - 1 - true);
- return MIN (lim, 1 + true + false);
+ ctrue = count_cond (TREE_OPERAND (expr, 1), lim - 1);
+ cfalse = count_cond (TREE_OPERAND (expr, 2), lim - 1 - ctrue);
+ return MIN (lim, 1 + ctrue + cfalse);
}
+
+/* Transform `a + (b ? x : y)' into `x ? (a + b) : (a + y)'.
+ Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'. Here
+ CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
+ expression, and ARG to `a'. If COND_FIRST_P is non-zero, then the
+ COND is the first argument to CODE; otherwise (as in the example
+ given here), it is the second argument. TYPE is the type of the
+ original expression. */
+
+static tree
+fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
+ enum tree_code code;
+ tree type;
+ tree cond;
+ tree arg;
+ int cond_first_p;
+{
+ tree test, true_value, false_value;
+ tree lhs = NULL_TREE;
+ tree rhs = NULL_TREE;
+ /* In the end, we'll produce a COND_EXPR. Both arms of the
+ conditional expression will be binary operations. The left-hand
+ side of the expression to be executed if the condition is true
+ will be pointed to by TRUE_LHS. Similarly, the right-hand side
+ of the expression to be executed if the condition is true will be
+ pointed to by TRUE_RHS. FALSE_LHS and FALSE_RHS are analagous --
+ but apply to the expression to be executed if the conditional is
+ false. */
+ tree *true_lhs;
+ tree *true_rhs;
+ tree *false_lhs;
+ tree *false_rhs;
+ /* These are the codes to use for the left-hand side and right-hand
+ side of the COND_EXPR. Normally, they are the same as CODE. */
+ enum tree_code lhs_code = code;
+ enum tree_code rhs_code = code;
+ /* And these are the types of the expressions. */
+ tree lhs_type = type;
+ tree rhs_type = type;
+
+ if (cond_first_p)
+ {
+ true_rhs = false_rhs = &arg;
+ true_lhs = &true_value;
+ false_lhs = &false_value;
+ }
+ else
+ {
+ true_lhs = false_lhs = &arg;
+ true_rhs = &true_value;
+ false_rhs = &false_value;
+ }
+
+ if (TREE_CODE (cond) == COND_EXPR)
+ {
+ test = TREE_OPERAND (cond, 0);
+ true_value = TREE_OPERAND (cond, 1);
+ false_value = TREE_OPERAND (cond, 2);
+ /* If this operand throws an expression, then it does not make
+ sense to try to perform a logical or arithmetic operation
+ involving it. Instead of building `a + throw 3' for example,
+ we simply build `a, throw 3'. */
+ if (VOID_TYPE_P (TREE_TYPE (true_value)))
+ {
+ lhs_code = COMPOUND_EXPR;
+ if (!cond_first_p)
+ lhs_type = void_type_node;
+ }
+ if (VOID_TYPE_P (TREE_TYPE (false_value)))
+ {
+ rhs_code = COMPOUND_EXPR;
+ if (!cond_first_p)
+ rhs_type = void_type_node;
+ }
+ }
+ else
+ {
+ tree testtype = TREE_TYPE (cond);
+ test = cond;
+ true_value = convert (testtype, integer_one_node);
+ false_value = convert (testtype, integer_zero_node);
+ }
+
+ /* If ARG is complex we want to make sure we only evaluate
+ it once. Though this is only required if it is volatile, it
+ might be more efficient even if it is not. However, if we
+ succeed in folding one part to a constant, we do not need
+ to make this SAVE_EXPR. Since we do this optimization
+ primarily to see if we do end up with constant and this
+ SAVE_EXPR interferes with later optimizations, suppressing
+ it when we can is important.
+
+ If we are not in a function, we can't make a SAVE_EXPR, so don't
+ try to do so. Don't try to see if the result is a constant
+ if an arm is a COND_EXPR since we get exponential behavior
+ in that case. */
+
+ if (TREE_CODE (arg) != SAVE_EXPR && ! TREE_CONSTANT (arg)
+ && global_bindings_p () == 0
+ && ((TREE_CODE (arg) != VAR_DECL
+ && TREE_CODE (arg) != PARM_DECL)
+ || TREE_SIDE_EFFECTS (arg)))
+ {
+ if (TREE_CODE (true_value) != COND_EXPR)
+ lhs = fold (build (lhs_code, lhs_type, *true_lhs, *true_rhs));
+
+ if (TREE_CODE (false_value) != COND_EXPR)
+ rhs = fold (build (rhs_code, rhs_type, *false_lhs, *false_rhs));
+
+ if ((lhs == 0 || ! TREE_CONSTANT (lhs))
+ && (rhs == 0 || !TREE_CONSTANT (rhs)))
+ arg = save_expr (arg), lhs = rhs = 0;
+ }
+
+ if (lhs == 0)
+ lhs = fold (build (lhs_code, lhs_type, *true_lhs, *true_rhs));
+ if (rhs == 0)
+ rhs = fold (build (rhs_code, rhs_type, *false_lhs, *false_rhs));
+
+ test = fold (build (COND_EXPR, type, test, lhs, rhs));
+
+ if (TREE_CODE (arg) == SAVE_EXPR)
+ return build (COMPOUND_EXPR, type,
+ convert (void_type_node, arg),
+ strip_compound_expr (test, arg));
+ else
+ return convert (type, test);
+}
+
\f
/* Perform constant folding and related simplification of EXPR.
The related simplifications include x*1 => x, x*0 => 0, etc.,
tree type = TREE_TYPE (expr);
register tree arg0 = NULL_TREE, arg1 = NULL_TREE;
register enum tree_code code = TREE_CODE (t);
- register int kind;
+ register int kind = TREE_CODE_CLASS (code);
int invert;
/* WINS will be nonzero when the switch is done
if all operands are constant. */
/* Don't try to process an RTL_EXPR since its operands aren't trees.
Likewise for a SAVE_EXPR that's already been evaluated. */
- if (code == RTL_EXPR || (code == SAVE_EXPR && SAVE_EXPR_RTL (t)) != 0)
+ if (code == RTL_EXPR || (code == SAVE_EXPR && SAVE_EXPR_RTL (t) != 0))
return t;
- /* Return right away if already constant. */
- if (TREE_CONSTANT (t))
- {
- if (code == CONST_DECL)
- return DECL_INITIAL (t);
- return t;
- }
+ /* Return right away if a constant. */
+ if (kind == 'c')
+ return t;
#ifdef MAX_INTEGER_COMPUTATION_MODE
check_max_integer_computation_mode (expr);
#endif
- kind = TREE_CODE_CLASS (code);
if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
{
tree subop;
}
else if (IS_EXPR_CODE_CLASS (kind) || kind == 'r')
{
- register int len = TREE_CODE_LENGTH (code);
+ register int len = first_rtl_op (code);
register int i;
for (i = 0; i < len; i++)
{
&& (! TREE_SIDE_EFFECTS (arg0)
|| (global_bindings_p () == 0
&& ! contains_placeholder_p (arg0))))
- {
- tree test, true_value, false_value;
- tree lhs = 0, rhs = 0;
-
- if (TREE_CODE (arg1) == COND_EXPR)
- {
- test = TREE_OPERAND (arg1, 0);
- true_value = TREE_OPERAND (arg1, 1);
- false_value = TREE_OPERAND (arg1, 2);
- }
- else
- {
- tree testtype = TREE_TYPE (arg1);
- test = arg1;
- true_value = convert (testtype, integer_one_node);
- false_value = convert (testtype, integer_zero_node);
- }
-
- /* If ARG0 is complex we want to make sure we only evaluate
- it once. Though this is only required if it is volatile, it
- might be more efficient even if it is not. However, if we
- succeed in folding one part to a constant, we do not need
- to make this SAVE_EXPR. Since we do this optimization
- primarily to see if we do end up with constant and this
- SAVE_EXPR interferes with later optimizations, suppressing
- it when we can is important.
-
- If we are not in a function, we can't make a SAVE_EXPR, so don't
- try to do so. Don't try to see if the result is a constant
- if an arm is a COND_EXPR since we get exponential behavior
- in that case. */
-
- if (TREE_CODE (arg0) != SAVE_EXPR && ! TREE_CONSTANT (arg0)
- && global_bindings_p () == 0
- && ((TREE_CODE (arg0) != VAR_DECL
- && TREE_CODE (arg0) != PARM_DECL)
- || TREE_SIDE_EFFECTS (arg0)))
- {
- if (TREE_CODE (true_value) != COND_EXPR)
- lhs = fold (build (code, type, arg0, true_value));
-
- if (TREE_CODE (false_value) != COND_EXPR)
- rhs = fold (build (code, type, arg0, false_value));
-
- if ((lhs == 0 || ! TREE_CONSTANT (lhs))
- && (rhs == 0 || !TREE_CONSTANT (rhs)))
- arg0 = save_expr (arg0), lhs = rhs = 0;
- }
-
- if (lhs == 0)
- lhs = fold (build (code, type, arg0, true_value));
- if (rhs == 0)
- rhs = fold (build (code, type, arg0, false_value));
-
- test = fold (build (COND_EXPR, type, test, lhs, rhs));
-
- if (TREE_CODE (arg0) == SAVE_EXPR)
- return build (COMPOUND_EXPR, type,
- convert (void_type_node, arg0),
- strip_compound_expr (test, arg0));
- else
- return convert (type, test);
- }
-
+ return
+ fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
+ /*cond_first_p=*/0);
else if (TREE_CODE (arg0) == COMPOUND_EXPR)
return build (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
fold (build (code, type, TREE_OPERAND (arg0, 1), arg1)));
&& (! TREE_SIDE_EFFECTS (arg1)
|| (global_bindings_p () == 0
&& ! contains_placeholder_p (arg1))))
- {
- tree test, true_value, false_value;
- tree lhs = 0, rhs = 0;
-
- if (TREE_CODE (arg0) == COND_EXPR)
- {
- test = TREE_OPERAND (arg0, 0);
- true_value = TREE_OPERAND (arg0, 1);
- false_value = TREE_OPERAND (arg0, 2);
- }
- else
- {
- tree testtype = TREE_TYPE (arg0);
- test = arg0;
- true_value = convert (testtype, integer_one_node);
- false_value = convert (testtype, integer_zero_node);
- }
-
- if (TREE_CODE (arg1) != SAVE_EXPR && ! TREE_CONSTANT (arg0)
- && global_bindings_p () == 0
- && ((TREE_CODE (arg1) != VAR_DECL
- && TREE_CODE (arg1) != PARM_DECL)
- || TREE_SIDE_EFFECTS (arg1)))
- {
- if (TREE_CODE (true_value) != COND_EXPR)
- lhs = fold (build (code, type, true_value, arg1));
-
- if (TREE_CODE (false_value) != COND_EXPR)
- rhs = fold (build (code, type, false_value, arg1));
-
- if ((lhs == 0 || ! TREE_CONSTANT (lhs))
- && (rhs == 0 || !TREE_CONSTANT (rhs)))
- arg1 = save_expr (arg1), lhs = rhs = 0;
- }
-
- if (lhs == 0)
- lhs = fold (build (code, type, true_value, arg1));
-
- if (rhs == 0)
- rhs = fold (build (code, type, false_value, arg1));
-
- test = fold (build (COND_EXPR, type, test, lhs, rhs));
- if (TREE_CODE (arg1) == SAVE_EXPR)
- return build (COMPOUND_EXPR, type,
- convert (void_type_node, arg1),
- strip_compound_expr (test, arg1));
- else
- return convert (type, test);
- }
+ return
+ fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
+ /*cond_first_p=*/1);
}
else if (TREE_CODE_CLASS (code) == '<'
&& TREE_CODE (arg0) == COMPOUND_EXPR)
handled below, if we are converting something to its own
type via an object of identical or wider precision, neither
conversion is needed. */
- if (inside_type == final_type
+ if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (final_type)
&& ((inter_int && final_int) || (inter_float && final_float))
&& inter_prec >= final_prec)
- return TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+ return convert (final_type, TREE_OPERAND (TREE_OPERAND (t, 0), 0));
/* Likewise, if the intermediate and final types are either both
float or both integer, we don't need the middle conversion if
/* Convert - (a - b) to (b - a) for non-floating-point. */
else if (TREE_CODE (arg0) == MINUS_EXPR
- && (! FLOAT_TYPE_P (type) || flag_fast_math))
+ && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
return build (MINUS_EXPR, type, TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg0, 0));
{
if (TREE_CODE (arg0) == INTEGER_CST)
{
- if (! TREE_UNSIGNED (type)
- && TREE_INT_CST_HIGH (arg0) < 0)
+ /* If the value is unsigned, then the absolute value is
+ the same as the ordinary value. */
+ if (TREE_UNSIGNED (type))
+ return arg0;
+ /* Similarly, if the value is non-negative. */
+ else if (INT_CST_LT (integer_minus_one_node, arg0))
+ return arg0;
+ /* If the value is negative, then the absolute value is
+ its negation. */
+ else
{
unsigned HOST_WIDE_INT low;
HOST_WIDE_INT high;
TREE_OPERAND (arg0, 0),
negate_expr (TREE_OPERAND (arg0, 1)));
else if (TREE_CODE (arg0) == COMPLEX_CST)
- return build_complex (type, TREE_OPERAND (arg0, 0),
- negate_expr (TREE_OPERAND (arg0, 1)));
+ return build_complex (type, TREE_REALPART (arg0),
+ negate_expr (TREE_IMAGPART (arg0)));
else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
return fold (build (TREE_CODE (arg0), type,
fold (build1 (CONJ_EXPR, type,
}
/* In IEEE floating point, x+0 may not equal x. */
else if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || flag_fast_math)
+ || flag_unsafe_math_optimizations)
&& real_zerop (arg1))
return non_lvalue (convert (type, arg0));
/* x+(-0) equals x, even for IEEE. */
parentheses. Rather than remember where the parentheses were, we
don't associate floats at all. It shouldn't matter much. However,
associating multiplications is only very slightly inaccurate, so do
- that if -ffast-math is specified. */
+ that if -funsafe-math-optimizations is specified. */
if (! wins
&& (! FLOAT_TYPE_P (type)
- || (flag_fast_math && code != MULT_EXPR)))
+ || (flag_unsafe_math_optimizations && code == MULT_EXPR)))
{
tree var0, con0, lit0, var1, con1, lit1;
if (! FLOAT_TYPE_P (type))
{
if (! wins && integer_zerop (arg0))
- return convert (type, negate_expr (arg1));
+ return negate_expr (convert (type, arg1));
if (integer_zerop (arg1))
return non_lvalue (convert (type, arg0));
}
else if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || flag_fast_math)
+ || flag_unsafe_math_optimizations)
{
/* Except with IEEE floating point, 0-x equals -x. */
if (! wins && real_zerop (arg0))
- return convert (type, negate_expr (arg1));
+ return negate_expr (convert (type, arg1));
/* Except with IEEE floating point, x-0 equals x. */
if (real_zerop (arg1))
return non_lvalue (convert (type, arg0));
Also note that operand_equal_p is always false if an operand
is volatile. */
- if ((! FLOAT_TYPE_P (type) || flag_fast_math)
+ if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
&& operand_equal_p (arg0, arg1, 0))
return convert (type, integer_zero_node);
{
/* x*0 is 0, except for IEEE floating point. */
if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || flag_fast_math)
+ || flag_unsafe_math_optimizations)
&& real_zerop (arg1))
return omit_one_operand (type, arg1, arg0);
/* In IEEE floating point, x*1 is not equivalent to x for snans.
/* If ARG1 is a constant, we can convert this to a multiply by the
reciprocal. This does not have the same rounding properties,
- so only do this if -ffast-math. We can actually always safely
- do it if ARG1 is a power of two, but it's hard to tell if it is
- or not in a portable manner. */
+ so only do this if -funsafe-math-optimizations. We can actually
+ always safely do it if ARG1 is a power of two, but it's hard to
+ tell if it is or not in a portable manner. */
if (TREE_CODE (arg1) == REAL_CST)
{
- if (flag_fast_math
+ if (flag_unsafe_math_optimizations
&& 0 != (tem = const_binop (code, build_real (type, dconst1),
arg1, 0)))
return fold (build (MULT_EXPR, type, arg0, tem));
/* If either arg is constant true, drop it. */
if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
return non_lvalue (convert (type, arg1));
- if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1))
+ if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1)
+ /* Preserve sequence points. */
+ && (code != TRUTH_ANDIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
return non_lvalue (convert (type, arg0));
/* If second arg is constant zero, result is zero, but first arg
must be evaluated. */
/* If either arg is constant zero, drop it. */
if (TREE_CODE (arg0) == INTEGER_CST && integer_zerop (arg0))
return non_lvalue (convert (type, arg1));
- if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1))
+ if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1)
+ /* Preserve sequence points. */
+ && (code != TRUTH_ORIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
return non_lvalue (convert (type, arg0));
/* If second arg is constant true, result is true, but we must
evaluate first arg. */
else if (TREE_INT_CST_HIGH (arg1) == 0
&& (TREE_INT_CST_LOW (arg1)
== ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
- && TREE_UNSIGNED (TREE_TYPE (arg1)))
+ && TREE_UNSIGNED (TREE_TYPE (arg1))
+ /* signed_type does not work on pointer types. */
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
switch (TREE_CODE (t))
{
if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
&& (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|| ! FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0)))
- || flag_fast_math)
+ || flag_unsafe_math_optimizations)
&& operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
arg1, TREE_OPERAND (arg0, 1)))
{
{
case EQ_EXPR:
return
- pedantic_non_lvalue (convert (type, negate_expr (arg1)));
+ pedantic_non_lvalue
+ (convert (type,
+ negate_expr
+ (convert (TREE_TYPE (TREE_OPERAND (t, 1)),
+ arg1))));
+
case NE_EXPR:
return pedantic_non_lvalue (convert (type, arg1));
case GE_EXPR:
return t;
}
+ case CALL_EXPR:
+ /* Check for a built-in function. */
+ if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR
+ && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (expr, 0), 0))
+ == FUNCTION_DECL)
+ && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)))
+ {
+ tree tmp = fold_builtin (expr);
+ if (tmp)
+ return tmp;
+ }
+ return t;
+
default:
return t;
} /* switch (code) */
return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
&& multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
+ case LSHIFT_EXPR:
+ if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
+ {
+ tree op1, t1;
+
+ op1 = TREE_OPERAND (top, 1);
+ /* const_binop may not detect overflow correctly,
+ so check for it explicitly here. */
+ if (TYPE_PRECISION (TREE_TYPE (size_one_node))
+ > TREE_INT_CST_LOW (op1)
+ && TREE_INT_CST_HIGH (op1) == 0
+ && 0 != (t1 = convert (type,
+ const_binop (LSHIFT_EXPR, size_one_node,
+ op1, 0)))
+ && ! TREE_OVERFLOW (t1))
+ return multiple_of_p (type, t1, bottom);
+ }
+ return 0;
+
case NOP_EXPR:
/* Can't handle conversions from non-integral or wider integral type. */
if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (top, 0))) != INTEGER_TYPE)
return multiple_of_p (type, TREE_OPERAND (top, 0), bottom);
case INTEGER_CST:
- if ((TREE_CODE (bottom) != INTEGER_CST)
- || (tree_int_cst_sgn (top) < 0)
- || (tree_int_cst_sgn (bottom) < 0))
+ if (TREE_CODE (bottom) != INTEGER_CST
+ || (TREE_UNSIGNED (type)
+ && (tree_int_cst_sgn (top) < 0
+ || tree_int_cst_sgn (bottom) < 0)))
return 0;
return integer_zerop (const_binop (TRUNC_MOD_EXPR,
top, bottom, 0));
return rtl_expr_nonnegative_p (RTL_EXPR_RTL (t));
default:
- /* We don't know sign of `t', so be safe and return false. */
- return 0;
+ if (truth_value_p (TREE_CODE (t)))
+ /* Truth values evaluate to 0 or 1, which is nonnegative. */
+ return 1;
+ else
+ /* We don't know sign of `t', so be conservative and return false. */
+ return 0;
}
}