/* 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, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
static void encode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
static void decode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);
+static bool negate_mathfn_p (enum built_in_function);
static bool negate_expr_p (tree);
static tree negate_expr (tree);
static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
static tree const_binop (enum tree_code, tree, tree, int);
static hashval_t size_htab_hash (const void *);
static int size_htab_eq (const void *, const void *);
-static tree fold_convert (tree, tree);
+static tree fold_convert_const (enum tree_code, tree, tree);
static enum tree_code invert_tree_comparison (enum tree_code);
static enum tree_code swap_tree_comparison (enum tree_code);
static int comparison_to_compcode (enum tree_code);
static tree fold_mathfn_compare (enum built_in_function, enum tree_code,
tree, tree, tree);
static tree fold_inf_compare (enum tree_code, tree, tree, tree);
+static bool reorder_operands_p (tree, tree);
+static bool tree_swap_operands_p (tree, tree, bool);
/* The following constants represent a bit based encoding of GCC's
comparison operators. This encoding simplifies transformations
abort ();
}
- /* compute true remainder: rem = num - (quo * den) */
+ /* Compute true remainder: rem = num - (quo * den) */
mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
neg_double (*lrem, *hrem, lrem, hrem);
add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
return overflow;
}
\f
+/* Return true if built-in mathematical function specified by CODE
+ preserves the sign of it argument, i.e. -f(x) == f(-x). */
+
+static bool
+negate_mathfn_p (enum built_in_function code)
+{
+ switch (code)
+ {
+ case BUILT_IN_ASIN:
+ case BUILT_IN_ASINF:
+ case BUILT_IN_ASINL:
+ case BUILT_IN_ATAN:
+ case BUILT_IN_ATANF:
+ case BUILT_IN_ATANL:
+ case BUILT_IN_SIN:
+ case BUILT_IN_SINF:
+ case BUILT_IN_SINL:
+ case BUILT_IN_TAN:
+ case BUILT_IN_TANF:
+ case BUILT_IN_TANL:
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+}
+
+
/* Determine whether an expression T can be cheaply negated using
the function negate_expr. */
switch (TREE_CODE (t))
{
case INTEGER_CST:
- if (TREE_UNSIGNED (type))
- return false;
+ if (TREE_UNSIGNED (type) || ! flag_trapv)
+ return true;
/* Check that -CST will not overflow type. */
prec = TYPE_PRECISION (type);
case NEGATE_EXPR:
return true;
+ case COMPLEX_CST:
+ return negate_expr_p (TREE_REALPART (t))
+ && negate_expr_p (TREE_IMAGPART (t));
+
case MINUS_EXPR:
/* We can't turn -(A-B) into B-A when we honor signed zeros. */
- return ! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations;
+ return (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+ && reorder_operands_p (TREE_OPERAND (t, 0),
+ TREE_OPERAND (t, 1));
case MULT_EXPR:
if (TREE_UNSIGNED (TREE_TYPE (t)))
|| negate_expr_p (TREE_OPERAND (t, 0));
break;
+ case NOP_EXPR:
+ /* Negate -((double)float) as (double)(-float). */
+ if (TREE_CODE (type) == REAL_TYPE)
+ {
+ tree tem = strip_float_extensions (t);
+ if (tem != t)
+ return negate_expr_p (tem);
+ }
+ break;
+
+ case CALL_EXPR:
+ /* Negate -f(x) as f(-x). */
+ if (negate_mathfn_p (builtin_mathfn_code (t)))
+ return negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1)));
+ break;
+
default:
break;
}
switch (TREE_CODE (t))
{
case INTEGER_CST:
- if (! TREE_UNSIGNED (type)
- && 0 != (tem = fold (build1 (NEGATE_EXPR, type, t)))
- && ! TREE_OVERFLOW (tem))
+ {
+ unsigned HOST_WIDE_INT low;
+ HOST_WIDE_INT high;
+ int overflow = neg_double (TREE_INT_CST_LOW (t),
+ TREE_INT_CST_HIGH (t),
+ &low, &high);
+ tem = build_int_2 (low, high);
+ TREE_TYPE (tem) = type;
+ TREE_OVERFLOW (tem)
+ = (TREE_OVERFLOW (t)
+ | force_fit_type (tem, overflow && !TREE_UNSIGNED (type)));
+ TREE_CONSTANT_OVERFLOW (tem)
+ = TREE_OVERFLOW (tem) | TREE_CONSTANT_OVERFLOW (t);
+ }
+ if (! TREE_OVERFLOW (tem)
+ || TREE_UNSIGNED (type)
+ || ! flag_trapv)
return tem;
break;
case REAL_CST:
tem = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (t)));
/* Two's complement FP formats, such as c4x, may overflow. */
- if (! TREE_OVERFLOW (tem))
+ if (! TREE_OVERFLOW (tem) || ! flag_trapping_math)
return convert (type, tem);
break;
+ case COMPLEX_CST:
+ {
+ tree rpart = negate_expr (TREE_REALPART (t));
+ tree ipart = negate_expr (TREE_IMAGPART (t));
+
+ if ((TREE_CODE (rpart) == REAL_CST
+ && TREE_CODE (ipart) == REAL_CST)
+ || (TREE_CODE (rpart) == INTEGER_CST
+ && TREE_CODE (ipart) == INTEGER_CST))
+ return build_complex (type, rpart, ipart);
+ }
+ break;
+
case NEGATE_EXPR:
return convert (type, TREE_OPERAND (t, 0));
case MINUS_EXPR:
/* - (A - B) -> B - A */
- if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+ if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+ && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
return convert (type,
fold (build (MINUS_EXPR, TREE_TYPE (t),
TREE_OPERAND (t, 1),
}
break;
+ case NOP_EXPR:
+ /* Convert -((double)float) into (double)(-float). */
+ if (TREE_CODE (type) == REAL_TYPE)
+ {
+ tem = strip_float_extensions (t);
+ if (tem != t && negate_expr_p (tem))
+ return convert (type, negate_expr (tem));
+ }
+ break;
+
+ case CALL_EXPR:
+ /* Negate -f(x) as f(-x). */
+ if (negate_mathfn_p (builtin_mathfn_code (t))
+ && negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1))))
+ {
+ tree fndecl, arg, arglist;
+
+ fndecl = get_callee_fndecl (t);
+ arg = negate_expr (TREE_VALUE (TREE_OPERAND (t, 1)));
+ arglist = build_tree_list (NULL_TREE, arg);
+ return build_function_call_expr (fndecl, arglist);
+ }
+ break;
+
default:
break;
}
}
\f
-/* Given T, a tree representing type conversion of ARG1, a constant,
- return a constant tree representing the result of conversion. */
+/* Attempt to fold type conversion operation CODE of expression ARG1 to
+ type TYPE. If no simplification can be done return NULL_TREE. */
static tree
-fold_convert (tree t, tree arg1)
+fold_convert_const (enum tree_code code, tree type, tree arg1)
{
- tree type = TREE_TYPE (t);
int overflow = 0;
+ tree t;
+
+ if (TREE_TYPE (arg1) == type)
+ return arg1;
if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
{
/* If we would build a constant wider than GCC supports,
leave the conversion unfolded. */
if (TYPE_PRECISION (type) > 2 * HOST_BITS_PER_WIDE_INT)
- return t;
+ return NULL_TREE;
/* If we are trying to make a sizetype for a small integer, use
size_int to pick up cached types to reduce duplicate nodes. */
|| TREE_OVERFLOW (arg1));
TREE_CONSTANT_OVERFLOW (t)
= TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+ return t;
}
else if (TREE_CODE (arg1) == REAL_CST)
{
- /* Don't initialize these, use assignments.
- Initialized local aggregates don't work on old compilers. */
- REAL_VALUE_TYPE x;
- REAL_VALUE_TYPE l;
- REAL_VALUE_TYPE u;
- tree type1 = TREE_TYPE (arg1);
- int no_upper_bound;
-
- x = TREE_REAL_CST (arg1);
- l = real_value_from_int_cst (type1, TYPE_MIN_VALUE (type));
-
- no_upper_bound = (TYPE_MAX_VALUE (type) == NULL);
- if (!no_upper_bound)
- 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. */
- REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);
- if (!no_upper_bound)
- REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
- /* If X is a NaN, use zero instead and show we have an overflow.
- Otherwise, range check. */
- if (REAL_VALUE_ISNAN (x))
- overflow = 1, x = dconst0;
- else if (! (REAL_VALUES_LESS (l, x)
- && !no_upper_bound
- && REAL_VALUES_LESS (x, u)))
- overflow = 1;
+ /* The following code implements the floating point to integer
+ conversion rules required by the Java Language Specification,
+ that IEEE NaNs are mapped to zero and values that overflow
+ the target precision saturate, i.e. values greater than
+ INT_MAX are mapped to INT_MAX, and values less than INT_MIN
+ are mapped to INT_MIN. These semantics are allowed by the
+ C and C++ standards that simply state that the behavior of
+ FP-to-integer conversion is unspecified upon overflow. */
- {
- HOST_WIDE_INT low, high;
- REAL_VALUE_TO_INT (&low, &high, x);
- t = build_int_2 (low, high);
- }
+ HOST_WIDE_INT high, low;
+
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
+
+ switch (code)
+ {
+ case FIX_TRUNC_EXPR:
+ real_trunc (&r, VOIDmode, &x);
+ break;
+
+ case FIX_CEIL_EXPR:
+ real_ceil (&r, VOIDmode, &x);
+ break;
+
+ case FIX_FLOOR_EXPR:
+ real_floor (&r, VOIDmode, &x);
+ break;
+
+ default:
+ abort ();
+ }
+
+ /* If R is NaN, return zero and show we have an overflow. */
+ if (REAL_VALUE_ISNAN (r))
+ {
+ overflow = 1;
+ high = 0;
+ low = 0;
+ }
+
+ /* See if R is less than the lower bound or greater than the
+ upper bound. */
+
+ if (! overflow)
+ {
+ tree lt = TYPE_MIN_VALUE (type);
+ REAL_VALUE_TYPE l = real_value_from_int_cst (NULL_TREE, lt);
+ if (REAL_VALUES_LESS (r, l))
+ {
+ overflow = 1;
+ high = TREE_INT_CST_HIGH (lt);
+ low = TREE_INT_CST_LOW (lt);
+ }
+ }
+
+ if (! overflow)
+ {
+ tree ut = TYPE_MAX_VALUE (type);
+ if (ut)
+ {
+ REAL_VALUE_TYPE u = real_value_from_int_cst (NULL_TREE, ut);
+ if (REAL_VALUES_LESS (u, r))
+ {
+ overflow = 1;
+ high = TREE_INT_CST_HIGH (ut);
+ low = TREE_INT_CST_LOW (ut);
+ }
+ }
+ }
+
+ if (! overflow)
+ REAL_VALUE_TO_INT (&low, &high, r);
+
+ t = build_int_2 (low, high);
TREE_TYPE (t) = type;
TREE_OVERFLOW (t)
= TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
TREE_CONSTANT_OVERFLOW (t)
= TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+ return t;
}
- TREE_TYPE (t) = type;
}
else if (TREE_CODE (type) == REAL_TYPE)
{
return t;
}
}
- TREE_CONSTANT (t) = 1;
- return t;
+ return NULL_TREE;
}
\f
/* Return an expr equal to X but certainly not valid as an lvalue. */
|| code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR);
}
\f
-/* Return nonzero if two operands are necessarily equal.
+/* Return nonzero if two operands (typically of the same tree node)
+ are necessarily equal. If either argument has side-effects this
+ function returns zero.
+
If ONLY_CONST is nonzero, only return nonzero for constants.
This function tests whether the operands are indistinguishable;
it does not test whether they are equal using C's == operation.
The distinction is important for IEEE floating point, because
(1) -0.0 and 0.0 are distinguishable, but -0.0==0.0, and
- (2) two NaNs may be indistinguishable, but NaN!=NaN. */
+ (2) two NaNs may be indistinguishable, but NaN!=NaN.
+
+ If ONLY_CONST is zero, a VAR_DECL is considered equal to itself
+ even though it may hold multiple values during a function.
+ This is because a GCC tree node guarantees that nothing else is
+ executed between the evaluation of its "operands" (which may often
+ be evaluated in arbitrary order). Hence if the operands themselves
+ don't side-effect, the VAR_DECLs, PARM_DECLs etc... must hold the
+ same value in each operand/subexpression. Hence a zero value for
+ ONLY_CONST assumes isochronic (or instantaneous) tree equivalence.
+ If comparing arbitrary expression trees, such as from different
+ statements, ONLY_CONST must usually be nonzero. */
int
operand_equal_p (tree arg0, tree arg1, int only_const)
in_p = n_in_p, low = n_low, high = n_high;
- /* If the high bound is missing, but we
- have a low bound, reverse the range so
- it goes from zero to the low bound minus 1. */
- if (high == 0 && low)
+ /* If the high bound is missing, but we have a nonzero low
+ bound, reverse the range so it goes from zero to the low bound
+ minus 1. */
+ if (high == 0 && low && ! integer_zerop (low))
{
in_p = ! in_p;
high = range_binop (MINUS_EXPR, NULL_TREE, low, 0,
if (code == MULT_EXPR
|| integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
{
- op1 = const_binop (code, convert (ctype, op1), convert (ctype, c), 0);
- if (op1 == 0 || TREE_OVERFLOW (op1))
+ op1 = const_binop (code, convert (ctype, op1),
+ convert (ctype, c), 0);
+ /* We allow the constant to overflow with wrapping semantics. */
+ if (op1 == 0
+ || (TREE_OVERFLOW (op1) && ! flag_wrapv))
break;
}
else
int bitnum = tree_log2 (TREE_OPERAND (arg0, 1));
enum machine_mode operand_mode = TYPE_MODE (type);
int ops_unsigned;
- tree signed_type, unsigned_type;
+ tree signed_type, unsigned_type, intermediate_type;
tree arg00;
/* If we have (A & C) != 0 where C is the sign bit of A, convert
signed_type = (*lang_hooks.types.type_for_mode) (operand_mode, 0);
unsigned_type = (*lang_hooks.types.type_for_mode) (operand_mode, 1);
+ intermediate_type = ops_unsigned ? unsigned_type : signed_type;
+ inner = convert (intermediate_type, inner);
if (bitnum != 0)
- inner = build (RSHIFT_EXPR, ops_unsigned ? unsigned_type : signed_type,
+ inner = build (RSHIFT_EXPR, intermediate_type,
inner, size_int (bitnum));
if (code == EQ_EXPR)
- inner = build (BIT_XOR_EXPR, ops_unsigned ? unsigned_type : signed_type,
+ inner = build (BIT_XOR_EXPR, intermediate_type,
inner, integer_one_node);
/* Put the AND last so it can combine with more things. */
- inner = build (BIT_AND_EXPR, ops_unsigned ? unsigned_type : signed_type,
+ inner = build (BIT_AND_EXPR, intermediate_type,
inner, integer_one_node);
/* Make sure to return the proper type. */
- if (TREE_TYPE (inner) != result_type)
- inner = convert (result_type, inner);
+ inner = convert (result_type, inner);
return inner;
}
return NULL_TREE;
}
+/* Check whether we are allowed to reorder operands arg0 and arg1,
+ such that the evaluation of arg1 occurs before arg0. */
+
+static bool
+reorder_operands_p (tree arg0, tree arg1)
+{
+ if (! flag_evaluation_order)
+ return true;
+ if (TREE_CONSTANT (arg0) || TREE_CONSTANT (arg1))
+ return true;
+ return ! TREE_SIDE_EFFECTS (arg0)
+ && ! TREE_SIDE_EFFECTS (arg1);
+}
+
+/* Test whether it is preferable two swap two operands, ARG0 and
+ ARG1, for example because ARG0 is an integer constant and ARG1
+ isn't. If REORDER is true, only recommend swapping if we can
+ evaluate the operands in reverse order. */
+
+static bool
+tree_swap_operands_p (tree arg0, tree arg1, bool reorder)
+{
+ STRIP_SIGN_NOPS (arg0);
+ STRIP_SIGN_NOPS (arg1);
+
+ if (TREE_CODE (arg1) == INTEGER_CST)
+ return 0;
+ if (TREE_CODE (arg0) == INTEGER_CST)
+ return 1;
+
+ if (TREE_CODE (arg1) == REAL_CST)
+ return 0;
+ if (TREE_CODE (arg0) == REAL_CST)
+ return 1;
+
+ if (TREE_CODE (arg1) == COMPLEX_CST)
+ return 0;
+ if (TREE_CODE (arg0) == COMPLEX_CST)
+ return 1;
+
+ if (TREE_CONSTANT (arg1))
+ return 0;
+ if (TREE_CONSTANT (arg0))
+ return 1;
+
+ if (optimize_size)
+ return 0;
+
+ if (reorder && flag_evaluation_order
+ && (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1)))
+ return 0;
+
+ if (DECL_P (arg1))
+ return 0;
+ if (DECL_P (arg0))
+ return 1;
+
+ return 0;
+}
+
/* Perform constant folding and related simplification of EXPR.
The related simplifications include x*1 => x, x*0 => 0, etc.,
and application of the associative law.
if (kind == 'c')
return t;
-#ifdef MAX_INTEGER_COMPUTATION_MODE
- check_max_integer_computation_mode (expr);
-#endif
orig_t = t;
if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
subop = arg0;
if (subop != 0 && TREE_CODE (subop) != INTEGER_CST
- && TREE_CODE (subop) != REAL_CST
- )
+ && TREE_CODE (subop) != REAL_CST)
/* Note that TREE_CONSTANT isn't enough:
static var addresses are constant but we can't
do arithmetic on them. */
if ((code == PLUS_EXPR || code == MULT_EXPR || code == MIN_EXPR
|| code == MAX_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR
|| code == BIT_AND_EXPR)
- && ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) != INTEGER_CST)
- || (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) != REAL_CST)))
- {
- tem = arg0; arg0 = arg1; arg1 = tem;
-
- if (t == orig_t)
- t = copy_node (t);
- TREE_OPERAND (t, 0) = arg0;
- TREE_OPERAND (t, 1) = arg1;
- }
+ && tree_swap_operands_p (arg0, arg1, true))
+ return fold (build (code, type, arg1, arg0));
/* Now WINS is set as described above,
ARG0 is the first operand of EXPR,
case FLOAT_EXPR:
case CONVERT_EXPR:
case FIX_TRUNC_EXPR:
- /* Other kinds of FIX are not handled properly by fold_convert. */
-
+ case FIX_CEIL_EXPR:
+ case FIX_FLOOR_EXPR:
if (TREE_TYPE (TREE_OPERAND (t, 0)) == TREE_TYPE (t))
return TREE_OPERAND (t, 0);
convert (TREE_TYPE (t), and1)));
}
- if (!wins)
- {
- if (TREE_CONSTANT (t) != TREE_CONSTANT (arg0))
- {
- if (t == orig_t)
- t = copy_node (t);
- TREE_CONSTANT (t) = TREE_CONSTANT (arg0);
- }
- return t;
- }
- return fold_convert (t, arg0);
+ tem = fold_convert_const (code, TREE_TYPE (t), arg0);
+ return tem ? tem : t;
case VIEW_CONVERT_EXPR:
if (TREE_CODE (TREE_OPERAND (t, 0)) == VIEW_CONVERT_EXPR)
return t;
case NEGATE_EXPR:
- if (wins)
- {
- if (TREE_CODE (arg0) == INTEGER_CST)
- {
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT high;
- int overflow = neg_double (TREE_INT_CST_LOW (arg0),
- TREE_INT_CST_HIGH (arg0),
- &low, &high);
- t = build_int_2 (low, high);
- TREE_TYPE (t) = type;
- TREE_OVERFLOW (t)
- = (TREE_OVERFLOW (arg0)
- | force_fit_type (t, overflow && !TREE_UNSIGNED (type)));
- TREE_CONSTANT_OVERFLOW (t)
- = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0);
- }
- else if (TREE_CODE (arg0) == REAL_CST)
- t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
- }
- else if (TREE_CODE (arg0) == NEGATE_EXPR)
- return TREE_OPERAND (arg0, 0);
- /* Convert -((double)float) into (double)(-float). */
- else if (TREE_CODE (arg0) == NOP_EXPR
- && TREE_CODE (type) == REAL_TYPE)
- {
- tree targ0 = strip_float_extensions (arg0);
- if (targ0 != arg0)
- return convert (type, build1 (NEGATE_EXPR, TREE_TYPE (targ0), targ0));
-
- }
-
- /* Convert - (a - b) to (b - a) for non-floating-point. */
- else if (TREE_CODE (arg0) == MINUS_EXPR
- && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
- return build (MINUS_EXPR, type, TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg0, 0));
-
- /* Convert -f(x) into f(-x) where f is sin, tan or atan. */
- switch (builtin_mathfn_code (arg0))
- {
- case BUILT_IN_SIN:
- case BUILT_IN_SINF:
- case BUILT_IN_SINL:
- case BUILT_IN_TAN:
- case BUILT_IN_TANF:
- case BUILT_IN_TANL:
- case BUILT_IN_ATAN:
- case BUILT_IN_ATANF:
- case BUILT_IN_ATANL:
- if (negate_expr_p (TREE_VALUE (TREE_OPERAND (arg0, 1))))
- {
- tree fndecl, arg, arglist;
-
- fndecl = get_callee_fndecl (arg0);
- arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
- arg = fold (build1 (NEGATE_EXPR, type, arg));
- arglist = build_tree_list (NULL_TREE, arg);
- return build_function_call_expr (fndecl, arglist);
- }
- break;
-
- default:
- break;
- }
+ if (negate_expr_p (arg0))
+ return negate_expr (arg0);
return t;
case ABS_EXPR:
&& (FLOAT_TYPE_P (type)
|| (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv))
&& negate_expr_p (arg1)
- && (! TREE_SIDE_EFFECTS (arg0) || TREE_CONSTANT (arg1))
- && (! TREE_SIDE_EFFECTS (arg1) || TREE_CONSTANT (arg0)))
+ && reorder_operands_p (arg0, arg1))
return fold (build (MINUS_EXPR, type, negate_expr (arg1),
TREE_OPERAND (arg0, 0)));
TREE_OPERAND (arg1, 1))),
arg0));
}
+
+ /* Fold (A & ~B) - (A & B) into (A ^ B) - B, where B is
+ any power of 2 minus 1. */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && TREE_CODE (arg1) == BIT_AND_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0), 0))
+ {
+ tree mask0 = TREE_OPERAND (arg0, 1);
+ tree mask1 = TREE_OPERAND (arg1, 1);
+ tree tem = fold (build1 (BIT_NOT_EXPR, type, mask0));
+
+ if (operand_equal_p (tem, mask1, 0))
+ {
+ tem = fold (build (BIT_XOR_EXPR, type,
+ TREE_OPERAND (arg0, 0), mask1));
+ return fold (build (MINUS_EXPR, type, tem, mask1));
+ }
+ }
}
/* See if ARG1 is zero and X - ARG1 reduces to X. */
return build_function_call_expr (sqrtfn, arglist);
}
- /* Optimize exp(x)*exp(y) as exp(x+y). */
- if ((fcode0 == BUILT_IN_EXP && fcode1 == BUILT_IN_EXP)
- || (fcode0 == BUILT_IN_EXPF && fcode1 == BUILT_IN_EXPF)
- || (fcode0 == BUILT_IN_EXPL && fcode1 == BUILT_IN_EXPL))
+ /* Optimize expN(x)*expN(y) as expN(x+y). */
+ if (fcode0 == fcode1
+ && (fcode0 == BUILT_IN_EXP
+ || fcode0 == BUILT_IN_EXPF
+ || fcode0 == BUILT_IN_EXPL
+ || fcode0 == BUILT_IN_EXP2
+ || fcode0 == BUILT_IN_EXP2F
+ || fcode0 == BUILT_IN_EXP2L
+ || fcode0 == BUILT_IN_EXP10
+ || fcode0 == BUILT_IN_EXP10F
+ || fcode0 == BUILT_IN_EXP10L
+ || fcode0 == BUILT_IN_POW10
+ || fcode0 == BUILT_IN_POW10F
+ || fcode0 == BUILT_IN_POW10L))
{
tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
tree arg = build (PLUS_EXPR, type,
if (flag_unsafe_math_optimizations)
{
enum built_in_function fcode = builtin_mathfn_code (arg1);
- /* Optimize x/exp(y) into x*exp(-y). */
+ /* Optimize x/expN(y) into x*expN(-y). */
if (fcode == BUILT_IN_EXP
|| fcode == BUILT_IN_EXPF
- || fcode == BUILT_IN_EXPL)
+ || fcode == BUILT_IN_EXPL
+ || fcode == BUILT_IN_EXP2
+ || fcode == BUILT_IN_EXP2F
+ || fcode == BUILT_IN_EXP2L
+ || fcode == BUILT_IN_EXP10
+ || fcode == BUILT_IN_EXP10F
+ || fcode == BUILT_IN_EXP10L
+ || fcode == BUILT_IN_POW10
+ || fcode == BUILT_IN_POW10F
+ || fcode == BUILT_IN_POW10L)
{
tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
tree arg = build1 (NEGATE_EXPR, type,
RROTATE_EXPR by a new constant. */
if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
{
- if (t == orig_t)
- t = copy_node (t);
- TREE_SET_CODE (t, RROTATE_EXPR);
- code = RROTATE_EXPR;
- TREE_OPERAND (t, 1) = arg1
- = const_binop
- (MINUS_EXPR,
- convert (TREE_TYPE (arg1),
- build_int_2 (GET_MODE_BITSIZE (TYPE_MODE (type)), 0)),
- arg1, 0);
- if (tree_int_cst_sgn (arg1) < 0)
- return t;
+ tree tem = build_int_2 (GET_MODE_BITSIZE (TYPE_MODE (type)), 0);
+ tem = convert (TREE_TYPE (arg1), tem);
+ tem = const_binop (MINUS_EXPR, tem, arg1, 0);
+ return fold (build (RROTATE_EXPR, type, arg0, tem));
}
/* If we have a rotate of a bit operation with the rotate count and
case LE_EXPR:
case GE_EXPR:
/* If one arg is a real or integer constant, put it last. */
- if ((TREE_CODE (arg0) == INTEGER_CST
- && TREE_CODE (arg1) != INTEGER_CST)
- || (TREE_CODE (arg0) == REAL_CST
- && TREE_CODE (arg0) != REAL_CST))
- {
- if (t == orig_t)
- t = copy_node (t);
- TREE_OPERAND (t, 0) = arg1;
- TREE_OPERAND (t, 1) = arg0;
- arg0 = TREE_OPERAND (t, 0);
- arg1 = TREE_OPERAND (t, 1);
- code = swap_tree_comparison (code);
- TREE_SET_CODE (t, code);
- }
+ if (tree_swap_operands_p (arg0, arg1, true))
+ return fold (build (swap_tree_comparison (code), type, arg1, arg0));
if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
{
switch (code)
{
case GE_EXPR:
- code = GT_EXPR;
arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- t = build (code, type, TREE_OPERAND (t, 0), arg1);
- break;
+ return fold (build (GT_EXPR, type, arg0, arg1));
case LT_EXPR:
- code = LE_EXPR;
arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- t = build (code, type, TREE_OPERAND (t, 0), arg1);
- break;
+ return fold (build (LE_EXPR, type, arg0, arg1));
default:
break;
convert (type, integer_zero_node),
arg0);
case GE_EXPR:
- code = EQ_EXPR;
- if (t == orig_t)
- t = copy_node (t);
- TREE_SET_CODE (t, EQ_EXPR);
- break;
+ return fold (build (EQ_EXPR, type, arg0, arg1));
+
case LE_EXPR:
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
case LT_EXPR:
- code = NE_EXPR;
- if (t == orig_t)
- t = copy_node (t);
- TREE_SET_CODE (t, NE_EXPR);
- break;
+ return fold (build (NE_EXPR, type, arg0, arg1));
/* The GE_EXPR and LT_EXPR cases above are not normally
- reached because of previous transformations. */
+ reached because of previous transformations. */
default:
break;
switch (code)
{
case GT_EXPR:
- code = EQ_EXPR;
arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
- t = build (code, type, TREE_OPERAND (t, 0), arg1);
- break;
+ return fold (build (EQ_EXPR, type, arg0, arg1));
case LE_EXPR:
- code = NE_EXPR;
arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
- t = build (code, type, TREE_OPERAND (t, 0), arg1);
- break;
+ return fold (build (NE_EXPR, type, arg0, arg1));
default:
break;
}
convert (type, integer_zero_node),
arg0);
case LE_EXPR:
- code = EQ_EXPR;
- if (t == orig_t)
- t = copy_node (t);
- TREE_SET_CODE (t, EQ_EXPR);
- break;
+ return fold (build (EQ_EXPR, type, arg0, arg1));
case GE_EXPR:
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
case GT_EXPR:
- code = NE_EXPR;
- if (t == orig_t)
- t = copy_node (t);
- TREE_SET_CODE (t, NE_EXPR);
- break;
+ return fold (build (NE_EXPR, type, arg0, arg1));
default:
break;
switch (code)
{
case GE_EXPR:
- code = NE_EXPR;
arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- t = build (code, type, TREE_OPERAND (t, 0), arg1);
- break;
+ return fold (build (NE_EXPR, type, arg0, arg1));
case LT_EXPR:
- code = EQ_EXPR;
arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- t = build (code, type, TREE_OPERAND (t, 0), arg1);
- break;
+ return fold (build (EQ_EXPR, type, arg0, arg1));
default:
break;
}
switch (code)
{
case EQ_EXPR:
+ if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
+ || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ return constant_boolean_node (1, type);
+ break;
+
case GE_EXPR:
case LE_EXPR:
if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
|| ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
return constant_boolean_node (1, type);
- code = EQ_EXPR;
- if (t == orig_t)
- t = copy_node (t);
- TREE_SET_CODE (t, code);
- break;
+ return fold (build (EQ_EXPR, type, arg0, arg1));
case NE_EXPR:
/* For NE, we can only do this simplification if integer
&& (optimize || TREE_CODE (arg1) == INTEGER_CST))
{
t1 = optimize_bit_field_compare (code, type, arg0, arg1);
- return t1 ? t1 : t;
+ if (t1)
+ return t1;
}
/* If this is a comparison of complex values and either or both sides
/* Pedantic ANSI C says that a conditional expression is never an lvalue,
so all simple results must be passed through pedantic_non_lvalue. */
if (TREE_CODE (arg0) == INTEGER_CST)
- return pedantic_non_lvalue
- (TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1)));
- else if (operand_equal_p (arg1, TREE_OPERAND (expr, 2), 0))
- return pedantic_omit_one_operand (type, arg1, arg0);
-
- /* If the second operand is zero, invert the comparison and swap
- the second and third operands. Likewise if the second operand
- is constant and the third is not or if the third operand is
- equivalent to the first operand of the comparison. */
-
- if (integer_zerop (arg1)
- || (TREE_CONSTANT (arg1) && ! TREE_CONSTANT (TREE_OPERAND (t, 2)))
- || (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
- && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (t, 2),
- TREE_OPERAND (arg0, 1))))
{
- /* See if this can be inverted. If it can't, possibly because
- it was a floating-point inequality comparison, don't do
- anything. */
- tem = invert_truthvalue (arg0);
-
- if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
- {
- t = build (code, type, tem,
- TREE_OPERAND (t, 2), TREE_OPERAND (t, 1));
- arg0 = tem;
- /* arg1 should be the first argument of the new T. */
- arg1 = TREE_OPERAND (t, 1);
- STRIP_NOPS (arg1);
- }
+ tem = TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1));
+ /* Only optimize constant conditions when the selected branch
+ has the same type as the COND_EXPR. This avoids optimizing
+ away "c ? x : throw", where the throw has a void type. */
+ if (! VOID_TYPE_P (TREE_TYPE (tem))
+ || VOID_TYPE_P (TREE_TYPE (t)))
+ return pedantic_non_lvalue (tem);
+ return t;
}
+ if (operand_equal_p (arg1, TREE_OPERAND (expr, 2), 0))
+ return pedantic_omit_one_operand (type, arg1, arg0);
/* If we have A op B ? A : C, we may be able to convert this to a
simpler expression, depending on the operation and the values
case EQ_EXPR:
/* We can replace A with C1 in this case. */
arg1 = convert (type, TREE_OPERAND (arg0, 1));
- t = build (code, type, TREE_OPERAND (t, 0), arg1,
- TREE_OPERAND (t, 2));
- break;
+ return fold (build (code, type, TREE_OPERAND (t, 0), arg1,
+ TREE_OPERAND (t, 2)));
case LT_EXPR:
/* If C1 is C2 + 1, this is min(A, C2). */
/* If the second operand is simpler than the third, swap them
since that produces better jump optimization results. */
- if ((TREE_CONSTANT (arg1) || DECL_P (arg1)
- || TREE_CODE (arg1) == SAVE_EXPR)
- && ! (TREE_CONSTANT (TREE_OPERAND (t, 2))
- || DECL_P (TREE_OPERAND (t, 2))
- || TREE_CODE (TREE_OPERAND (t, 2)) == SAVE_EXPR))
+ if (tree_swap_operands_p (TREE_OPERAND (t, 1),
+ TREE_OPERAND (t, 2), false))
{
/* See if this can be inverted. If it can't, possibly because
it was a floating-point inequality comparison, don't do
tem = invert_truthvalue (arg0);
if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
- {
- t = build (code, type, tem,
- TREE_OPERAND (t, 2), TREE_OPERAND (t, 1));
- arg0 = tem;
- /* arg1 should be the first argument of the new T. */
- arg1 = TREE_OPERAND (t, 1);
- STRIP_NOPS (arg1);
- }
+ return fold (build (code, type, tem,
+ TREE_OPERAND (t, 2), TREE_OPERAND (t, 1)));
}
/* Convert A ? 1 : 0 to simply A. */
case COMPOUND_EXPR:
/* When pedantic, a compound expression can be neither an lvalue
nor an integer constant expression. */
- if (TREE_SIDE_EFFECTS (arg0) || pedantic)
+ if (TREE_SIDE_EFFECTS (arg0) || TREE_CONSTANT (arg1))
return t;
/* Don't let (0, 0) be null pointer constant. */
if (integer_zerop (arg1))
- return build1 (NOP_EXPR, type, arg1);
- return convert (type, arg1);
+ return pedantic_non_lvalue (build1 (NOP_EXPR, type, arg1));
+ return pedantic_non_lvalue (convert (type, arg1));
case COMPLEX_EXPR:
if (wins)
case WITH_CLEANUP_EXPR: len = 2; break;
default: break;
}
- /* FALLTHROUGH */
+ /* Fall through. */
case 'r':
case '<':
case '1':
switch (TREE_CODE (t))
{
case ABS_EXPR:
- case FFS_EXPR:
- case POPCOUNT_EXPR:
- case PARITY_EXPR:
return 1;
- case CLZ_EXPR:
- case CTZ_EXPR:
- /* These are undefined at zero. This is true even if
- C[LT]Z_DEFINED_VALUE_AT_ZERO is set, since what we're
- computing here is a user-visible property. */
- return 0;
-
case INTEGER_CST:
return tree_int_cst_sgn (t) >= 0;
case BUILT_IN_EXP:
case BUILT_IN_EXPF:
case BUILT_IN_EXPL:
+ case BUILT_IN_EXP2:
+ case BUILT_IN_EXP2F:
+ case BUILT_IN_EXP2L:
+ case BUILT_IN_EXP10:
+ case BUILT_IN_EXP10F:
+ case BUILT_IN_EXP10L:
case BUILT_IN_FABS:
case BUILT_IN_FABSF:
case BUILT_IN_FABSL:
+ case BUILT_IN_FFS:
+ case BUILT_IN_FFSL:
+ case BUILT_IN_FFSLL:
+ case BUILT_IN_PARITY:
+ case BUILT_IN_PARITYL:
+ case BUILT_IN_PARITYLL:
+ case BUILT_IN_POPCOUNT:
+ case BUILT_IN_POPCOUNTL:
+ case BUILT_IN_POPCOUNTLL:
+ case BUILT_IN_POW10:
+ case BUILT_IN_POW10F:
+ case BUILT_IN_POW10L:
case BUILT_IN_SQRT:
case BUILT_IN_SQRTF:
case BUILT_IN_SQRTL: