diff options
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 170 |
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) |