aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c170
1 files changed, 132 insertions, 38 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index b8da1a74b26..9f13d61fea3 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -178,10 +178,7 @@ decode (words, low, hi)
Return 1 if a signed overflow occurs, 0 otherwise. If OVERFLOW is
nonzero, a signed overflow has already occurred in calculating T, so
- propagate it.
-
- Make the real constant T valid for its type by calling CHECK_FLOAT_VALUE,
- if it exists. */
+ propagate it. */
int
force_fit_type (t, overflow)
@@ -194,10 +191,8 @@ force_fit_type (t, overflow)
if (TREE_CODE (t) == REAL_CST)
{
-#ifdef CHECK_FLOAT_VALUE
- CHECK_FLOAT_VALUE (TYPE_MODE (TREE_TYPE (t)), TREE_REAL_CST (t),
- overflow);
-#endif
+ /* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
+ Consider doing it via real_convert now. */
return overflow;
}
@@ -654,7 +649,7 @@ div_and_round_double (code, uns,
int num_hi_sig, den_hi_sig;
unsigned HOST_WIDE_INT quo_est, scale;
- /* Find the highest non-zero divisor digit. */
+ /* Find the highest nonzero divisor digit. */
for (i = 4 - 1;; i--)
if (den[i] != 0)
{
@@ -1351,11 +1346,11 @@ size_htab_hash (x)
tree t = (tree) x;
return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t)
- ^ (hashval_t) ((long) TREE_TYPE (t) >> 3)
+ ^ htab_hash_pointer (TREE_TYPE (t))
^ (TREE_OVERFLOW (t) << 20));
}
-/* Return non-zero if the value represented by *X (an INTEGER_CST tree node)
+/* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
is the same as that given by *Y, which is the same. */
static int
@@ -1786,7 +1781,7 @@ truth_value_p (code)
}
/* Return nonzero if two operands are necessarily equal.
- If ONLY_CONST is non-zero, only return non-zero for constants.
+ 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
@@ -2020,7 +2015,7 @@ operand_equal_for_comparison_p (arg0, arg1, other)
/* See if ARG is an expression that is either a comparison or is performing
arithmetic on comparisons. The comparisons must only be comparing
two different values, which will be stored in *CVAL1 and *CVAL2; if
- they are non-zero it means that some operands have already been found.
+ they are nonzero it means that some operands have already been found.
No variables may be used anywhere else in the expression except in the
comparisons. If SAVE_P is true it means we removed a SAVE_EXPR around
the expression and save_expr needs to be called with CVAL1 and CVAL2.
@@ -2405,7 +2400,7 @@ distribute_bit_expr (code, type, arg0, arg1)
}
/* Return a BIT_FIELD_REF of type TYPE to refer to BITSIZE bits of INNER
- starting at BITPOS. The field is unsigned if UNSIGNEDP is non-zero. */
+ starting at BITPOS. The field is unsigned if UNSIGNEDP is nonzero. */
static tree
make_bit_field_ref (inner, type, bitsize, bitpos, unsignedp)
@@ -2678,7 +2673,7 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
return inner;
}
-/* Return non-zero if MASK represents a mask of SIZE ones in the low-order
+/* Return nonzero if MASK represents a mask of SIZE ones in the low-order
bit positions. */
static int
@@ -3089,9 +3084,10 @@ make_range (exp, pin_p, plow, phigh)
= TYPE_MAX_VALUE (equiv_type) ? TYPE_MAX_VALUE (equiv_type)
: TYPE_MAX_VALUE (type);
- high_positive = fold (build (RSHIFT_EXPR, type,
- convert (type, high_positive),
- convert (type, integer_one_node)));
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (exp)))
+ high_positive = fold (build (RSHIFT_EXPR, type,
+ convert (type, high_positive),
+ convert (type, integer_one_node)));
/* If the low bound is specified, "and" the range with the
range for which the original unsigned value will be
@@ -4399,7 +4395,7 @@ count_cond (expr, lim)
/* Transform `a + (b ? x : y)' into `b ? (a + x) : (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
+ expression, and ARG to `a'. If COND_FIRST_P is nonzero, 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. */
@@ -4434,6 +4430,7 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
/* And these are the types of the expressions. */
tree lhs_type = type;
tree rhs_type = type;
+ int save = 0;
if (cond_first_p)
{
@@ -4459,15 +4456,23 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
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 (! cond_first_p)
+ {
+ lhs_code = COMPOUND_EXPR;
+ lhs_type = void_type_node;
+ }
+ else
+ lhs = true_value;
}
if (VOID_TYPE_P (TREE_TYPE (false_value)))
{
- rhs_code = COMPOUND_EXPR;
- if (!cond_first_p)
- rhs_type = void_type_node;
+ if (! cond_first_p)
+ {
+ rhs_code = COMPOUND_EXPR;
+ rhs_type = void_type_node;
+ }
+ else
+ rhs = false_value;
}
}
else
@@ -4492,11 +4497,13 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
if an arm is a COND_EXPR since we get exponential behavior
in that case. */
- if (TREE_CODE (arg) != SAVE_EXPR && ! TREE_CONSTANT (arg)
- && (*lang_hooks.decls.global_bindings_p) () == 0
- && ((TREE_CODE (arg) != VAR_DECL
- && TREE_CODE (arg) != PARM_DECL)
- || TREE_SIDE_EFFECTS (arg)))
+ if (TREE_CODE (arg) == SAVE_EXPR)
+ save = 1;
+ else if (lhs == 0 && rhs == 0
+ && !TREE_CONSTANT (arg)
+ && (*lang_hooks.decls.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));
@@ -4506,7 +4513,11 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
if ((lhs == 0 || ! TREE_CONSTANT (lhs))
&& (rhs == 0 || !TREE_CONSTANT (rhs)))
- arg = save_expr (arg), lhs = rhs = 0;
+ {
+ arg = save_expr (arg);
+ lhs = rhs = 0;
+ save = 1;
+ }
}
if (lhs == 0)
@@ -4516,7 +4527,7 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
test = fold (build (COND_EXPR, type, test, lhs, rhs));
- if (TREE_CODE (arg) == SAVE_EXPR)
+ if (save)
return build (COMPOUND_EXPR, type,
convert (void_type_node, arg),
strip_compound_expr (test, arg));
@@ -4531,7 +4542,7 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
TYPE, X + ADDEND is the same as X. If NEGATE, return true if X -
ADDEND is the same as X.
- X + 0 and X - 0 both give X when X is NaN, infinite, or non-zero
+ X + 0 and X - 0 both give X when X is NaN, infinite, or nonzero
and finite. The problematic cases are when X is zero, and its mode
has signed zeros. In the case of rounding towards -infinity,
X - 0 is not the same as X because 0 - 0 is -0. In other rounding
@@ -4724,9 +4735,14 @@ fold (expr)
fold (build1 (code, type, TREE_OPERAND (arg0, 1))));
else if (TREE_CODE (arg0) == COND_EXPR)
{
+ tree arg01 = TREE_OPERAND (arg0, 1);
+ tree arg02 = TREE_OPERAND (arg0, 2);
+ if (! VOID_TYPE_P (TREE_TYPE (arg01)))
+ arg01 = fold (build1 (code, type, arg01));
+ if (! VOID_TYPE_P (TREE_TYPE (arg02)))
+ arg02 = fold (build1 (code, type, arg02));
t = fold (build (COND_EXPR, type, TREE_OPERAND (arg0, 0),
- fold (build1 (code, type, TREE_OPERAND (arg0, 1))),
- fold (build1 (code, type, TREE_OPERAND (arg0, 2)))));
+ arg01, arg02));
/* If this was a conversion, and all we did was to move into
inside the COND_EXPR, bring it back out. But leave it if
@@ -4742,6 +4758,8 @@ fold (expr)
&& TREE_CODE (t) == COND_EXPR
&& TREE_CODE (TREE_OPERAND (t, 1)) == code
&& TREE_CODE (TREE_OPERAND (t, 2)) == code
+ && ! VOID_TYPE_P (TREE_OPERAND (t, 1))
+ && ! VOID_TYPE_P (TREE_OPERAND (t, 2))
&& (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0))
== TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 2), 0)))
&& ! (INTEGRAL_TYPE_P (TREE_TYPE (t))
@@ -4765,7 +4783,9 @@ fold (expr)
else if (TREE_CODE_CLASS (code) == '2'
|| TREE_CODE_CLASS (code) == '<')
{
- if (TREE_CODE (arg1) == COMPOUND_EXPR)
+ if (TREE_CODE (arg1) == COMPOUND_EXPR
+ && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg1, 0))
+ && ! TREE_SIDE_EFFECTS (arg0))
return build (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
fold (build (code, type,
arg0, TREE_OPERAND (arg1, 1))));
@@ -5061,6 +5081,18 @@ fold (expr)
}
else if (TREE_CODE (arg0) == ABS_EXPR || TREE_CODE (arg0) == NEGATE_EXPR)
return build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0));
+ else
+ {
+ /* fabs(sqrt(x)) = sqrt(x) and fabs(exp(x)) = exp(x). */
+ enum built_in_function fcode = builtin_mathfn_code (arg0);
+ if (fcode == BUILT_IN_SQRT
+ || fcode == BUILT_IN_SQRTF
+ || fcode == BUILT_IN_SQRTL
+ || fcode == BUILT_IN_EXP
+ || fcode == BUILT_IN_EXPF
+ || fcode == BUILT_IN_EXPL)
+ t = arg0;
+ }
return t;
case CONJ_EXPR:
@@ -5501,6 +5533,38 @@ fold (expr)
tree arg = save_expr (arg0);
return build (PLUS_EXPR, type, arg, arg);
}
+
+ if (flag_unsafe_math_optimizations)
+ {
+ enum built_in_function fcode0 = builtin_mathfn_code (arg0);
+ enum built_in_function fcode1 = builtin_mathfn_code (arg1);
+
+ /* Optimize sqrt(x)*sqrt(y) as sqrt(x*y). */
+ if ((fcode0 == BUILT_IN_SQRT && fcode1 == BUILT_IN_SQRT)
+ || (fcode0 == BUILT_IN_SQRTF && fcode1 == BUILT_IN_SQRTF)
+ || (fcode0 == BUILT_IN_SQRTL && fcode1 == BUILT_IN_SQRTL))
+ {
+ tree sqrtfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ tree arg = build (MULT_EXPR, type,
+ TREE_VALUE (TREE_OPERAND (arg0, 1)),
+ TREE_VALUE (TREE_OPERAND (arg1, 1)));
+ tree arglist = build_tree_list (NULL_TREE, arg);
+ return fold (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))
+ {
+ tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ tree arg = build (PLUS_EXPR, type,
+ TREE_VALUE (TREE_OPERAND (arg0, 1)),
+ TREE_VALUE (TREE_OPERAND (arg1, 1)));
+ tree arglist = build_tree_list (NULL_TREE, arg);
+ return fold (build_function_call_expr (expfn, arglist));
+ }
+ }
}
goto associate;
@@ -5669,6 +5733,23 @@ fold (expr)
TREE_OPERAND (arg1, 0)),
TREE_OPERAND (arg1, 1)));
}
+
+ /* Optimize x/exp(y) into x*exp(-y). */
+ if (flag_unsafe_math_optimizations)
+ {
+ enum built_in_function fcode = builtin_mathfn_code (arg1);
+ if (fcode == BUILT_IN_EXP
+ || fcode == BUILT_IN_EXPF
+ || fcode == BUILT_IN_EXPL)
+ {
+ tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
+ tree arg = build1 (NEGATE_EXPR, type,
+ TREE_VALUE (TREE_OPERAND (arg1, 1)));
+ tree arglist = build_tree_list (NULL_TREE, arg);
+ arg1 = build_function_call_expr (expfn, arglist);
+ return fold (build (MULT_EXPR, type, arg0, arg1));
+ }
+ }
goto binary;
case TRUNC_DIV_EXPR:
@@ -5714,12 +5795,25 @@ fold (expr)
goto binary;
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
case LROTATE_EXPR:
case RROTATE_EXPR:
+ if (integer_all_onesp (arg0))
+ return omit_one_operand (type, arg0, arg1);
+ goto shift;
+
+ case RSHIFT_EXPR:
+ /* Optimize -1 >> x for arithmetic right shifts. */
+ if (integer_all_onesp (arg0) && ! TREE_UNSIGNED (type))
+ return omit_one_operand (type, arg0, arg1);
+ /* ... fall through ... */
+
+ case LSHIFT_EXPR:
+ shift:
if (integer_zerop (arg1))
return non_lvalue (convert (type, arg0));
+ if (integer_zerop (arg0))
+ return omit_one_operand (type, arg0, arg1);
+
/* Since negative shift count is not well-defined,
don't try to compute it in the compiler. */
if (TREE_CODE (arg1) == INTEGER_CST && tree_int_cst_sgn (arg1) < 0)