X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ffold-const.c;h=2c89c5b3d8d5b1a44e38cb6533b617395295ea04;hb=c7fe03c012a11c8b641a4e140914034e11538ca3;hp=71f1e9bce0957973f31b1ea524a0ab390628898e;hpb=3bcc1a800100c83e84eaa18ef50c68510a8d8cd1;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 71f1e9bce09..2c89c5b3d8d 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -65,12 +65,10 @@ 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 associate_trees (tree, tree, enum tree_code, tree); -static tree int_const_binop (enum tree_code, 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_const (enum tree_code, tree, tree); -static tree fold_convert (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); @@ -100,19 +98,23 @@ static tree fold_truthop (enum tree_code, tree, tree, tree); static tree optimize_minmax_comparison (tree); static tree extract_muldiv (tree, tree, enum tree_code, tree); static tree extract_muldiv_1 (tree, tree, enum tree_code, tree); -static tree strip_compound_expr (tree, tree); static int multiple_of_p (tree, tree, tree); static tree constant_boolean_node (int, tree); -static int count_cond (tree, int); static tree fold_binary_op_with_conditional_arg (enum tree_code, tree, tree, tree, int); static bool fold_real_zero_addition_p (tree, tree, int); 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 tree fold_div_compare (enum tree_code, tree, tree, tree); static bool reorder_operands_p (tree, tree); static bool tree_swap_operands_p (tree, tree, bool); +static tree fold_negate_const (tree, tree); +static tree fold_abs_const (tree, tree); +static tree fold_relational_const (enum tree_code, tree, tree, tree); +static tree fold_relational_hi_lo (enum tree_code *, const tree, tree *, tree *); + /* The following constants represent a bit based encoding of GCC's comparison operators. This encoding simplifies transformations on relational comparison operators, such as AND and OR. */ @@ -220,7 +222,7 @@ force_fit_type (tree t, int overflow) /* Unsigned types do not suffer sign extension or overflow unless they are a sizetype. */ - if (TREE_UNSIGNED (TREE_TYPE (t)) + if (TYPE_UNSIGNED (TREE_TYPE (t)) && ! (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE && TYPE_IS_SIZETYPE (TREE_TYPE (t)))) return overflow; @@ -374,10 +376,8 @@ lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, return; } -#ifdef SHIFT_COUNT_TRUNCATED if (SHIFT_COUNT_TRUNCATED) count %= prec; -#endif if (count >= 2 * HOST_BITS_PER_WIDE_INT) { @@ -437,10 +437,8 @@ rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, ? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1)) : 0); -#ifdef SHIFT_COUNT_TRUNCATED if (SHIFT_COUNT_TRUNCATED) count %= prec; -#endif if (count >= 2 * HOST_BITS_PER_WIDE_INT) { @@ -722,7 +720,7 @@ div_and_round_double (enum tree_code code, int uns, if (quo_neg) neg_double (*lquo, *hquo, lquo, hquo); - /* compute trial remainder: rem = num - (quo * den) */ + /* Compute trial 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); @@ -853,7 +851,7 @@ negate_expr_p (tree t) switch (TREE_CODE (t)) { case INTEGER_CST: - if (TREE_UNSIGNED (type) || ! flag_trapv) + if (TYPE_UNSIGNED (type) || ! flag_trapv) return true; /* Check that -CST will not overflow type. */ @@ -897,7 +895,7 @@ negate_expr_p (tree t) TREE_OPERAND (t, 1)); case MULT_EXPR: - if (TREE_UNSIGNED (TREE_TYPE (t))) + if (TYPE_UNSIGNED (TREE_TYPE (t))) break; /* Fall through. */ @@ -924,6 +922,18 @@ negate_expr_p (tree t) return negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1))); break; + case RSHIFT_EXPR: + /* Optimize -((int)x >> 31) into (unsigned)x >> 31. */ + if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST) + { + tree op1 = TREE_OPERAND (t, 1); + if (TREE_INT_CST_HIGH (op1) == 0 + && (unsigned HOST_WIDE_INT) (TYPE_PRECISION (type) - 1) + == TREE_INT_CST_LOW (op1)) + return true; + } + break; + default: break; } @@ -948,28 +958,15 @@ negate_expr (tree t) switch (TREE_CODE (t)) { case INTEGER_CST: - { - 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); - } + tem = fold_negate_const (t, type); if (! TREE_OVERFLOW (tem) - || TREE_UNSIGNED (type) + || TYPE_UNSIGNED (type) || ! flag_trapv) return tem; break; case REAL_CST: - tem = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (t))); + tem = fold_negate_const (t, type); /* Two's complement FP formats, such as c4x, may overflow. */ if (! TREE_OVERFLOW (tem) || ! flag_trapping_math) return fold_convert (type, tem); @@ -998,16 +995,21 @@ negate_expr (tree t) if (negate_expr_p (TREE_OPERAND (t, 1)) && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1))) - return fold_convert (type, - fold (build (MINUS_EXPR, TREE_TYPE (t), - negate_expr (TREE_OPERAND (t, 1)), - TREE_OPERAND (t, 0)))); + { + tem = negate_expr (TREE_OPERAND (t, 1)); + tem = fold (build2 (MINUS_EXPR, TREE_TYPE (t), + tem, TREE_OPERAND (t, 0))); + return fold_convert (type, tem); + } + /* -(A + B) -> (-A) - B. */ if (negate_expr_p (TREE_OPERAND (t, 0))) - return fold_convert (type, - fold (build (MINUS_EXPR, TREE_TYPE (t), - negate_expr (TREE_OPERAND (t, 0)), - TREE_OPERAND (t, 1)))); + { + tem = negate_expr (TREE_OPERAND (t, 0)); + tem = fold (build2 (MINUS_EXPR, TREE_TYPE (t), + tem, TREE_OPERAND (t, 1))); + return fold_convert (type, tem); + } } break; @@ -1016,13 +1018,13 @@ negate_expr (tree t) if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations) && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1))) return fold_convert (type, - fold (build (MINUS_EXPR, TREE_TYPE (t), - TREE_OPERAND (t, 1), - TREE_OPERAND (t, 0)))); + fold (build2 (MINUS_EXPR, TREE_TYPE (t), + TREE_OPERAND (t, 1), + TREE_OPERAND (t, 0)))); break; case MULT_EXPR: - if (TREE_UNSIGNED (TREE_TYPE (t))) + if (TYPE_UNSIGNED (TREE_TYPE (t))) break; /* Fall through. */ @@ -1033,15 +1035,15 @@ negate_expr (tree t) tem = TREE_OPERAND (t, 1); if (negate_expr_p (tem)) return fold_convert (type, - fold (build (TREE_CODE (t), TREE_TYPE (t), - TREE_OPERAND (t, 0), - negate_expr (tem)))); + fold (build2 (TREE_CODE (t), TREE_TYPE (t), + TREE_OPERAND (t, 0), + negate_expr (tem)))); tem = TREE_OPERAND (t, 0); if (negate_expr_p (tem)) return fold_convert (type, - fold (build (TREE_CODE (t), TREE_TYPE (t), - negate_expr (tem), - TREE_OPERAND (t, 1)))); + fold (build2 (TREE_CODE (t), TREE_TYPE (t), + negate_expr (tem), + TREE_OPERAND (t, 1)))); } break; @@ -1069,6 +1071,25 @@ negate_expr (tree t) } break; + case RSHIFT_EXPR: + /* Optimize -((int)x >> 31) into (unsigned)x >> 31. */ + if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST) + { + tree op1 = TREE_OPERAND (t, 1); + if (TREE_INT_CST_HIGH (op1) == 0 + && (unsigned HOST_WIDE_INT) (TYPE_PRECISION (type) - 1) + == TREE_INT_CST_LOW (op1)) + { + tree ntype = TYPE_UNSIGNED (type) + ? lang_hooks.types.signed_type (type) + : lang_hooks.types.unsigned_type (type); + tree temp = fold_convert (ntype, TREE_OPERAND (t, 0)); + temp = fold (build2 (RSHIFT_EXPR, ntype, temp, op1)); + return fold_convert (type, temp); + } + } + break; + default: break; } @@ -1193,18 +1214,18 @@ associate_trees (tree t1, tree t2, enum tree_code code, tree type) if (code == PLUS_EXPR) { if (TREE_CODE (t1) == NEGATE_EXPR) - return build (MINUS_EXPR, type, fold_convert (type, t2), - fold_convert (type, TREE_OPERAND (t1, 0))); + return build2 (MINUS_EXPR, type, fold_convert (type, t2), + fold_convert (type, TREE_OPERAND (t1, 0))); else if (TREE_CODE (t2) == NEGATE_EXPR) - return build (MINUS_EXPR, type, fold_convert (type, t1), - fold_convert (type, TREE_OPERAND (t2, 0))); + return build2 (MINUS_EXPR, type, fold_convert (type, t1), + fold_convert (type, TREE_OPERAND (t2, 0))); } - return build (code, type, fold_convert (type, t1), - fold_convert (type, t2)); + return build2 (code, type, fold_convert (type, t1), + fold_convert (type, t2)); } - return fold (build (code, type, fold_convert (type, t1), - fold_convert (type, t2))); + return fold (build2 (code, type, fold_convert (type, t1), + fold_convert (type, t2))); } /* Combine two integer constants ARG1 and ARG2 under operation CODE @@ -1212,7 +1233,7 @@ associate_trees (tree t1, tree t2, enum tree_code code, tree type) If NOTRUNC is nonzero, do not truncate the result to fit the data type. */ -static tree +tree int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) { unsigned HOST_WIDE_INT int1l, int2l; @@ -1223,7 +1244,7 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) HOST_WIDE_INT garbageh; tree t; tree type = TREE_TYPE (arg1); - int uns = TREE_UNSIGNED (type); + int uns = TYPE_UNSIGNED (type); int is_sizetype = (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)); int overflow = 0; @@ -1646,7 +1667,7 @@ size_binop (enum tree_code code, tree arg0, tree arg1) if (arg0 == error_mark_node || arg1 == error_mark_node) return error_mark_node; - return fold (build (code, type, arg0, arg1)); + return fold (build2 (code, type, arg0, arg1)); } /* Given two values, either both of sizetype or both of bitsizetype, @@ -1664,7 +1685,7 @@ size_diffop (tree arg0, tree arg1) abort (); /* If the type is already signed, just do the simple thing. */ - if (! TREE_UNSIGNED (type)) + if (!TYPE_UNSIGNED (type)) return size_binop (MINUS_EXPR, arg0, arg1); ctype = (type == bitsizetype || type == ubitsizetype @@ -1733,8 +1754,8 @@ fold_convert_const (enum tree_code code, tree type, tree arg1) TREE_OVERFLOW (t) = ((force_fit_type (t, (TREE_INT_CST_HIGH (arg1) < 0 - && (TREE_UNSIGNED (type) - < TREE_UNSIGNED (TREE_TYPE (arg1))))) + && (TYPE_UNSIGNED (type) + < TYPE_UNSIGNED (TREE_TYPE (arg1))))) && ! POINTER_TYPE_P (TREE_TYPE (arg1))) || TREE_OVERFLOW (arg1)); TREE_CONSTANT_OVERFLOW (t) @@ -1771,6 +1792,10 @@ fold_convert_const (enum tree_code code, tree type, tree arg1) real_floor (&r, VOIDmode, &x); break; + case FIX_ROUND_EXPR: + real_round (&r, VOIDmode, &x); + break; + default: abort (); } @@ -1857,7 +1882,7 @@ fold_convert_const (enum tree_code code, tree type, tree arg1) /* Convert expression ARG to type TYPE. Used by the middle-end for simple conversions in preference to calling the front-end's convert. */ -static tree +tree fold_convert (tree type, tree arg) { tree orig = TREE_TYPE (arg); @@ -1925,9 +1950,9 @@ fold_convert (tree type, tree arg) if (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig) || TREE_CODE (orig) == REAL_TYPE) - return build (COMPLEX_EXPR, type, - fold_convert (TREE_TYPE (type), arg), - fold_convert (TREE_TYPE (type), integer_zero_node)); + return build2 (COMPLEX_EXPR, type, + fold_convert (TREE_TYPE (type), arg), + fold_convert (TREE_TYPE (type), integer_zero_node)); if (TREE_CODE (orig) == COMPLEX_TYPE) { tree rpart, ipart; @@ -1936,7 +1961,7 @@ fold_convert (tree type, tree arg) { rpart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 0)); ipart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 1)); - return fold (build (COMPLEX_EXPR, type, rpart, ipart)); + return fold (build2 (COMPLEX_EXPR, type, rpart, ipart)); } arg = save_expr (arg); @@ -1944,7 +1969,7 @@ fold_convert (tree type, tree arg) ipart = fold (build1 (IMAGPART_EXPR, TREE_TYPE (orig), arg)); rpart = fold_convert (TREE_TYPE (type), rpart); ipart = fold_convert (TREE_TYPE (type), ipart); - return fold (build (COMPLEX_EXPR, type, rpart, ipart)); + return fold (build2 (COMPLEX_EXPR, type, rpart, ipart)); } } else if (TREE_CODE (type) == VECTOR_TYPE) @@ -1968,8 +1993,6 @@ fold_convert (tree type, tree arg) tree non_lvalue (tree x) { - tree result; - /* These things are certainly not lvalues. */ if (TREE_CODE (x) == NON_LVALUE_EXPR || TREE_CODE (x) == INTEGER_CST @@ -1978,9 +2001,7 @@ non_lvalue (tree x) || TREE_CODE (x) == ADDR_EXPR) return x; - result = build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x); - TREE_CONSTANT (result) = TREE_CONSTANT (x); - return result; + return build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x); } /* Nonzero means lvalues are limited to those valid in pedantic ANSI C. @@ -2116,16 +2137,16 @@ truth_value_p (enum tree_code code) /* Return nonzero if two operands (typically of the same tree node) are necessarily equal. If either argument has side-effects this - function returns zero. + function returns zero. FLAGS modifies behaviour as follows: - If ONLY_CONST is nonzero, only return nonzero for constants. + If OEP_ONLY_CONST is set, 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. - If ONLY_CONST is zero, a VAR_DECL is considered equal to itself + If OEP_ONLY_CONST is unset, 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 @@ -2134,17 +2155,23 @@ truth_value_p (enum tree_code code) 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. */ + statements, ONLY_CONST must usually be nonzero. + + If OEP_PURE_SAME is set, then pure functions with identical arguments + are considered the same. It is used when the caller has other ways + to ensure that global memory is unchanged in between. */ int -operand_equal_p (tree arg0, tree arg1, int only_const) +operand_equal_p (tree arg0, tree arg1, unsigned int flags) { - tree fndecl; + /* If either is ERROR_MARK, they aren't equal. */ + if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK) + return 0; /* If both types don't have the same signedness, then we can't consider them equal. We must check this before the STRIP_NOPS calls because they may change the signedness of the arguments. */ - if (TREE_UNSIGNED (TREE_TYPE (arg0)) != TREE_UNSIGNED (TREE_TYPE (arg1))) + if (TYPE_UNSIGNED (TREE_TYPE (arg0)) != TYPE_UNSIGNED (TREE_TYPE (arg1))) return 0; STRIP_NOPS (arg0); @@ -2165,7 +2192,7 @@ operand_equal_p (tree arg0, tree arg1, int only_const) expressions with side effects that should be treated the same due to the only side effects being identical SAVE_EXPR's, that will be detected in the recursive calls below. */ - if (arg0 == arg1 && ! only_const + if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST) && (TREE_CODE (arg0) == SAVE_EXPR || (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1)))) return 1; @@ -2198,7 +2225,8 @@ operand_equal_p (tree arg0, tree arg1, int only_const) v2 = TREE_VECTOR_CST_ELTS (arg1); while (v1 && v2) { - if (!operand_equal_p (v1, v2, only_const)) + if (!operand_equal_p (TREE_VALUE (v1), TREE_VALUE (v2), + flags)) return 0; v1 = TREE_CHAIN (v1); v2 = TREE_CHAIN (v2); @@ -2209,9 +2237,9 @@ operand_equal_p (tree arg0, tree arg1, int only_const) case COMPLEX_CST: return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1), - only_const) + flags) && operand_equal_p (TREE_IMAGPART (arg0), TREE_IMAGPART (arg1), - only_const)); + flags)); case STRING_CST: return (TREE_STRING_LENGTH (arg0) == TREE_STRING_LENGTH (arg1) @@ -2226,7 +2254,7 @@ operand_equal_p (tree arg0, tree arg1, int only_const) break; } - if (only_const) + if (flags & OEP_ONLY_CONST) return 0; switch (TREE_CODE_CLASS (TREE_CODE (arg0))) @@ -2234,12 +2262,12 @@ operand_equal_p (tree arg0, tree arg1, int only_const) case '1': /* Two conversions are equal only if signedness and modes match. */ if ((TREE_CODE (arg0) == NOP_EXPR || TREE_CODE (arg0) == CONVERT_EXPR) - && (TREE_UNSIGNED (TREE_TYPE (arg0)) - != TREE_UNSIGNED (TREE_TYPE (arg1)))) + && (TYPE_UNSIGNED (TREE_TYPE (arg0)) + != TYPE_UNSIGNED (TREE_TYPE (arg1)))) return 0; return operand_equal_p (TREE_OPERAND (arg0, 0), - TREE_OPERAND (arg1, 0), 0); + TREE_OPERAND (arg1, 0), flags); case '<': case '2': @@ -2251,9 +2279,9 @@ operand_equal_p (tree arg0, tree arg1, int only_const) /* For commutative ops, allow the other order. */ return (commutative_tree_code (TREE_CODE (arg0)) && operand_equal_p (TREE_OPERAND (arg0, 0), - TREE_OPERAND (arg1, 1), 0) + TREE_OPERAND (arg1, 1), flags) && operand_equal_p (TREE_OPERAND (arg0, 1), - TREE_OPERAND (arg1, 0), 0)); + TREE_OPERAND (arg1, 0), flags)); case 'r': /* If either of the pointer (or reference) expressions we are @@ -2266,23 +2294,23 @@ operand_equal_p (tree arg0, tree arg1, int only_const) { case INDIRECT_REF: return operand_equal_p (TREE_OPERAND (arg0, 0), - TREE_OPERAND (arg1, 0), 0); + TREE_OPERAND (arg1, 0), flags); case COMPONENT_REF: case ARRAY_REF: case ARRAY_RANGE_REF: return (operand_equal_p (TREE_OPERAND (arg0, 0), - TREE_OPERAND (arg1, 0), 0) + TREE_OPERAND (arg1, 0), flags) && operand_equal_p (TREE_OPERAND (arg0, 1), - TREE_OPERAND (arg1, 1), 0)); + TREE_OPERAND (arg1, 1), flags)); case BIT_FIELD_REF: return (operand_equal_p (TREE_OPERAND (arg0, 0), - TREE_OPERAND (arg1, 0), 0) + TREE_OPERAND (arg1, 0), flags) && operand_equal_p (TREE_OPERAND (arg0, 1), - TREE_OPERAND (arg1, 1), 0) + TREE_OPERAND (arg1, 1), flags) && operand_equal_p (TREE_OPERAND (arg0, 2), - TREE_OPERAND (arg1, 2), 0)); + TREE_OPERAND (arg1, 2), flags)); default: return 0; } @@ -2293,7 +2321,7 @@ operand_equal_p (tree arg0, tree arg1, int only_const) case ADDR_EXPR: case TRUTH_NOT_EXPR: return operand_equal_p (TREE_OPERAND (arg0, 0), - TREE_OPERAND (arg1, 0), 0); + TREE_OPERAND (arg1, 0), flags); case RTL_EXPR: return rtx_equal_p (RTL_EXPR_RTL (arg0), RTL_EXPR_RTL (arg1)); @@ -2302,14 +2330,18 @@ operand_equal_p (tree arg0, tree arg1, int only_const) /* If the CALL_EXPRs call different functions, then they clearly can not be equal. */ if (! operand_equal_p (TREE_OPERAND (arg0, 0), - TREE_OPERAND (arg1, 0), 0)) + TREE_OPERAND (arg1, 0), flags)) return 0; - /* Only consider const functions equivalent. */ - fndecl = get_callee_fndecl (arg0); - if (fndecl == NULL_TREE - || ! (flags_from_decl_or_type (fndecl) & ECF_CONST)) - return 0; + { + unsigned int cef = call_expr_flags (arg0); + if (flags & OEP_PURE_SAME) + cef &= ECF_CONST | ECF_PURE; + else + cef &= ECF_CONST; + if (!cef) + return 0; + } /* Now see if all the arguments are the same. operand_equal_p does not handle TREE_LIST, so we walk the operands here @@ -2318,7 +2350,8 @@ operand_equal_p (tree arg0, tree arg1, int only_const) arg1 = TREE_OPERAND (arg1, 1); while (arg0 && arg1) { - if (! operand_equal_p (TREE_VALUE (arg0), TREE_VALUE (arg1), 0)) + if (! operand_equal_p (TREE_VALUE (arg0), TREE_VALUE (arg1), + flags)) return 0; arg0 = TREE_CHAIN (arg0); @@ -2334,11 +2367,11 @@ operand_equal_p (tree arg0, tree arg1, int only_const) } case 'd': - /* Consider __builtin_sqrt equal to sqrt. */ - return TREE_CODE (arg0) == FUNCTION_DECL - && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1) - && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1) - && DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1); + /* Consider __builtin_sqrt equal to sqrt. */ + return (TREE_CODE (arg0) == FUNCTION_DECL + && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1) + && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1) + && DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1)); default: return 0; @@ -2391,7 +2424,7 @@ operand_equal_for_comparison_p (tree arg0, tree arg1, tree other) /* Make sure shorter operand is extended the right way to match the longer operand. */ - primarg1 = fold_convert ((*lang_hooks.types.signed_or_unsigned_type) + primarg1 = fold_convert (lang_hooks.types.signed_or_unsigned_type (unsignedp1, TREE_TYPE (primarg1)), primarg1); if (operand_equal_p (arg0, fold_convert (type, primarg1), 0)) @@ -2525,11 +2558,11 @@ eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1) old0, new0, old1, new1))); case '2': - return fold (build (code, type, - eval_subst (TREE_OPERAND (arg, 0), - old0, new0, old1, new1), - eval_subst (TREE_OPERAND (arg, 1), - old0, new0, old1, new1))); + return fold (build2 (code, type, + eval_subst (TREE_OPERAND (arg, 0), + old0, new0, old1, new1), + eval_subst (TREE_OPERAND (arg, 1), + old0, new0, old1, new1))); case 'e': switch (code) @@ -2541,13 +2574,13 @@ eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1) return eval_subst (TREE_OPERAND (arg, 1), old0, new0, old1, new1); case COND_EXPR: - return fold (build (code, type, - eval_subst (TREE_OPERAND (arg, 0), - old0, new0, old1, new1), - eval_subst (TREE_OPERAND (arg, 1), - old0, new0, old1, new1), - eval_subst (TREE_OPERAND (arg, 2), - old0, new0, old1, new1))); + return fold (build3 (code, type, + eval_subst (TREE_OPERAND (arg, 0), + old0, new0, old1, new1), + eval_subst (TREE_OPERAND (arg, 1), + old0, new0, old1, new1), + eval_subst (TREE_OPERAND (arg, 2), + old0, new0, old1, new1))); default: break; } @@ -2572,7 +2605,7 @@ eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1) else if (arg1 == old1 || operand_equal_p (arg1, old1, 0)) arg1 = new1; - return fold (build (code, type, arg0, arg1)); + return fold (build2 (code, type, arg0, arg1)); } default: @@ -2593,7 +2626,7 @@ omit_one_operand (tree type, tree result, tree omitted) tree t = fold_convert (type, result); if (TREE_SIDE_EFFECTS (omitted)) - return build (COMPOUND_EXPR, type, omitted, t); + return build2 (COMPOUND_EXPR, type, omitted, t); return non_lvalue (t); } @@ -2606,7 +2639,7 @@ pedantic_omit_one_operand (tree type, tree result, tree omitted) tree t = fold_convert (type, result); if (TREE_SIDE_EFFECTS (omitted)) - return build (COMPOUND_EXPR, type, omitted, t); + return build2 (COMPOUND_EXPR, type, omitted, t); return pedantic_non_lvalue (t); } @@ -2635,9 +2668,17 @@ invert_truthvalue (tree arg) && code != NE_EXPR && code != EQ_EXPR) return build1 (TRUTH_NOT_EXPR, type, arg); + else if (code == UNORDERED_EXPR + || code == ORDERED_EXPR + || code == UNEQ_EXPR + || code == UNLT_EXPR + || code == UNLE_EXPR + || code == UNGT_EXPR + || code == UNGE_EXPR) + return build1 (TRUTH_NOT_EXPR, type, arg); else - return build (invert_tree_comparison (code), type, - TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1)); + return build2 (invert_tree_comparison (code), type, + TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1)); } switch (code) @@ -2646,14 +2687,14 @@ invert_truthvalue (tree arg) return fold_convert (type, build_int_2 (integer_zerop (arg), 0)); case TRUTH_AND_EXPR: - return build (TRUTH_OR_EXPR, type, - invert_truthvalue (TREE_OPERAND (arg, 0)), - invert_truthvalue (TREE_OPERAND (arg, 1))); + return build2 (TRUTH_OR_EXPR, type, + invert_truthvalue (TREE_OPERAND (arg, 0)), + invert_truthvalue (TREE_OPERAND (arg, 1))); case TRUTH_OR_EXPR: - return build (TRUTH_AND_EXPR, type, - invert_truthvalue (TREE_OPERAND (arg, 0)), - invert_truthvalue (TREE_OPERAND (arg, 1))); + return build2 (TRUTH_AND_EXPR, type, + invert_truthvalue (TREE_OPERAND (arg, 0)), + invert_truthvalue (TREE_OPERAND (arg, 1))); case TRUTH_XOR_EXPR: /* Here we can invert either operand. We invert the first operand @@ -2662,44 +2703,42 @@ invert_truthvalue (tree arg) negation of the second operand. */ if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR) - return build (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0), - TREE_OPERAND (TREE_OPERAND (arg, 1), 0)); + return build2 (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0), + TREE_OPERAND (TREE_OPERAND (arg, 1), 0)); else - return build (TRUTH_XOR_EXPR, type, - invert_truthvalue (TREE_OPERAND (arg, 0)), - TREE_OPERAND (arg, 1)); + return build2 (TRUTH_XOR_EXPR, type, + invert_truthvalue (TREE_OPERAND (arg, 0)), + TREE_OPERAND (arg, 1)); case TRUTH_ANDIF_EXPR: - return build (TRUTH_ORIF_EXPR, type, - invert_truthvalue (TREE_OPERAND (arg, 0)), - invert_truthvalue (TREE_OPERAND (arg, 1))); + return build2 (TRUTH_ORIF_EXPR, type, + invert_truthvalue (TREE_OPERAND (arg, 0)), + invert_truthvalue (TREE_OPERAND (arg, 1))); case TRUTH_ORIF_EXPR: - return build (TRUTH_ANDIF_EXPR, type, - invert_truthvalue (TREE_OPERAND (arg, 0)), - invert_truthvalue (TREE_OPERAND (arg, 1))); + return build2 (TRUTH_ANDIF_EXPR, type, + invert_truthvalue (TREE_OPERAND (arg, 0)), + invert_truthvalue (TREE_OPERAND (arg, 1))); case TRUTH_NOT_EXPR: return TREE_OPERAND (arg, 0); case COND_EXPR: - return build (COND_EXPR, type, TREE_OPERAND (arg, 0), - invert_truthvalue (TREE_OPERAND (arg, 1)), - invert_truthvalue (TREE_OPERAND (arg, 2))); + return build3 (COND_EXPR, type, TREE_OPERAND (arg, 0), + invert_truthvalue (TREE_OPERAND (arg, 1)), + invert_truthvalue (TREE_OPERAND (arg, 2))); case COMPOUND_EXPR: - return build (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0), - invert_truthvalue (TREE_OPERAND (arg, 1))); - - case WITH_RECORD_EXPR: - return build (WITH_RECORD_EXPR, type, - invert_truthvalue (TREE_OPERAND (arg, 0)), - TREE_OPERAND (arg, 1)); + return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0), + invert_truthvalue (TREE_OPERAND (arg, 1))); case NON_LVALUE_EXPR: return invert_truthvalue (TREE_OPERAND (arg, 0)); case NOP_EXPR: + if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) + break; + case CONVERT_EXPR: case FLOAT_EXPR: return build1 (TREE_CODE (arg), type, @@ -2708,8 +2747,8 @@ invert_truthvalue (tree arg) case BIT_AND_EXPR: if (!integer_onep (TREE_OPERAND (arg, 1))) break; - return build (EQ_EXPR, type, arg, - fold_convert (type, integer_zero_node)); + return build2 (EQ_EXPR, type, arg, + fold_convert (type, integer_zero_node)); case SAVE_EXPR: return build1 (TRUTH_NOT_EXPR, type, arg); @@ -2774,8 +2813,8 @@ distribute_bit_expr (enum tree_code code, tree type, tree arg0, tree arg1) else return 0; - return fold (build (TREE_CODE (arg0), type, common, - fold (build (code, type, left, right)))); + return fold (build2 (TREE_CODE (arg0), type, common, + fold (build2 (code, type, left, right)))); } /* Return a BIT_FIELD_REF of type TYPE to refer to BITSIZE bits of INNER @@ -2785,10 +2824,10 @@ static tree make_bit_field_ref (tree inner, tree type, int bitsize, int bitpos, int unsignedp) { - tree result = build (BIT_FIELD_REF, type, inner, - size_int (bitsize), bitsize_int (bitpos)); + tree result = build3 (BIT_FIELD_REF, type, inner, + size_int (bitsize), bitsize_int (bitpos)); - TREE_UNSIGNED (result) = unsignedp; + BIT_FIELD_REF_UNSIGNED (result) = unsignedp; return result; } @@ -2864,8 +2903,8 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type, /* Set signed and unsigned types of the precision of this mode for the shifts below. */ - signed_type = (*lang_hooks.types.type_for_mode) (nmode, 0); - unsigned_type = (*lang_hooks.types.type_for_mode) (nmode, 1); + signed_type = lang_hooks.types.type_for_mode (nmode, 0); + unsigned_type = lang_hooks.types.type_for_mode (nmode, 1); /* Compute the bit position and size for the new reference and our offset within it. If the new reference is the same size as the original, we @@ -2891,15 +2930,15 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type, if (! const_p) /* If not comparing with constant, just rework the comparison and return. */ - return build (code, compare_type, - build (BIT_AND_EXPR, unsigned_type, - make_bit_field_ref (linner, unsigned_type, - nbitsize, nbitpos, 1), - mask), - build (BIT_AND_EXPR, unsigned_type, - make_bit_field_ref (rinner, unsigned_type, - nbitsize, nbitpos, 1), - mask)); + return build2 (code, compare_type, + build2 (BIT_AND_EXPR, unsigned_type, + make_bit_field_ref (linner, unsigned_type, + nbitsize, nbitpos, 1), + mask), + build2 (BIT_AND_EXPR, unsigned_type, + make_bit_field_ref (rinner, unsigned_type, + nbitsize, nbitpos, 1), + mask)); /* Otherwise, we are handling the constant case. See if the constant is too big for the field. Warn and return a tree of for 0 (false) if so. We do @@ -2960,9 +2999,9 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type, size_int (lbitpos), 0), mask, 0)); - return build (code, compare_type, - build (BIT_AND_EXPR, unsigned_type, lhs, mask), - rhs); + return build2 (code, compare_type, + build2 (BIT_AND_EXPR, unsigned_type, lhs, mask), + rhs); } /* Subroutine for fold_truthop: decode a field reference. @@ -3035,10 +3074,10 @@ decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize, the outer type, then the outer type gives the signedness. Otherwise (in case of a small bitfield) the signedness is unchanged. */ if (outer_type && *pbitsize == tree_low_cst (TYPE_SIZE (outer_type), 1)) - *punsignedp = TREE_UNSIGNED (outer_type); + *punsignedp = TYPE_UNSIGNED (outer_type); /* Compute the mask to access the bitfield. */ - unsigned_type = (*lang_hooks.types.type_for_size) (*pbitsize, 1); + unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1); precision = TYPE_PRECISION (unsigned_type); mask = build_int_2 (~0, ~0); @@ -3049,8 +3088,8 @@ decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize, /* Merge it with the mask we found in the BIT_AND_EXPR, if any. */ if (and_mask != 0) - mask = fold (build (BIT_AND_EXPR, unsigned_type, - fold_convert (unsigned_type, and_mask), mask)); + mask = fold (build2 (BIT_AND_EXPR, unsigned_type, + fold_convert (unsigned_type, and_mask), mask)); *pmask = mask; *pand_mask = and_mask; @@ -3068,7 +3107,7 @@ all_ones_mask_p (tree mask, int size) tree tmask; tmask = build_int_2 (~0, ~0); - TREE_TYPE (tmask) = (*lang_hooks.types.signed_type) (type); + TREE_TYPE (tmask) = lang_hooks.types.signed_type (type); force_fit_type (tmask, 0); return tree_int_cst_equal (mask, @@ -3215,8 +3254,8 @@ range_binop (enum tree_code code, tree type, tree arg0, int upper0_p, if (arg0 != 0 && arg1 != 0) { - tem = fold (build (code, type != 0 ? type : TREE_TYPE (arg0), - arg0, fold_convert (TREE_TYPE (arg0), arg1))); + tem = fold (build2 (code, type != 0 ? type : TREE_TYPE (arg0), + arg0, fold_convert (TREE_TYPE (arg0), arg1))); STRIP_NOPS (tem); return TREE_CODE (tem) == INTEGER_CST ? tem : 0; } @@ -3355,7 +3394,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh) greater than or equal to zero. We base the range tests we make on that fact, so we record it here so we can parse existing range tests. */ - if (TREE_UNSIGNED (type) && (low == 0 || high == 0)) + if (TYPE_UNSIGNED (type) && (low == 0 || high == 0)) { if (! merge_ranges (&n_in_p, &n_low, &n_high, in_p, low, high, 1, fold_convert (type, integer_zero_node), @@ -3391,8 +3430,8 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh) case BIT_NOT_EXPR: /* ~ X -> -X - 1 */ - exp = build (MINUS_EXPR, type, negate_expr (arg0), - fold_convert (type, integer_one_node)); + exp = build2 (MINUS_EXPR, type, negate_expr (arg0), + fold_convert (type, integer_one_node)); continue; case PLUS_EXPR: case MINUS_EXPR: @@ -3459,9 +3498,9 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh) So we have to make sure that the original unsigned value will be interpreted as positive. */ - if (TREE_UNSIGNED (type) && ! TREE_UNSIGNED (TREE_TYPE (exp))) + if (TYPE_UNSIGNED (type) && ! TYPE_UNSIGNED (TREE_TYPE (exp))) { - tree equiv_type = (*lang_hooks.types.type_for_mode) + tree equiv_type = lang_hooks.types.type_for_mode (TYPE_MODE (type), 1); tree high_positive; @@ -3473,11 +3512,11 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh) : TYPE_MAX_VALUE (type); if (TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (exp))) - high_positive = fold (build (RSHIFT_EXPR, type, - fold_convert (type, - high_positive), - fold_convert (type, - integer_one_node))); + high_positive = fold (build2 (RSHIFT_EXPR, type, + fold_convert (type, + high_positive), + fold_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 @@ -3550,19 +3589,19 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high) return fold_convert (type, integer_one_node); if (low == 0) - return fold (build (LE_EXPR, type, exp, high)); + return fold (build2 (LE_EXPR, type, exp, high)); if (high == 0) - return fold (build (GE_EXPR, type, exp, low)); + return fold (build2 (GE_EXPR, type, exp, low)); if (operand_equal_p (low, high, 0)) - return fold (build (EQ_EXPR, type, exp, low)); + return fold (build2 (EQ_EXPR, type, exp, low)); if (integer_zerop (low)) { - if (! TREE_UNSIGNED (etype)) + if (! TYPE_UNSIGNED (etype)) { - etype = (*lang_hooks.types.unsigned_type) (etype); + etype = lang_hooks.types.unsigned_type (etype); high = fold_convert (etype, high); exp = fold_convert (etype, exp); } @@ -3590,20 +3629,20 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high) if (TREE_INT_CST_HIGH (high) == hi && TREE_INT_CST_LOW (high) == lo) { - if (TREE_UNSIGNED (etype)) + if (TYPE_UNSIGNED (etype)) { - etype = (*lang_hooks.types.signed_type) (etype); + etype = lang_hooks.types.signed_type (etype); exp = fold_convert (etype, exp); } - return fold (build (GT_EXPR, type, exp, - fold_convert (etype, integer_zero_node))); + return fold (build2 (GT_EXPR, type, exp, + fold_convert (etype, integer_zero_node))); } } if (0 != (value = const_binop (MINUS_EXPR, high, low, 0)) && ! TREE_OVERFLOW (value)) return build_range_check (type, - fold (build (MINUS_EXPR, etype, exp, low)), + fold (build2 (MINUS_EXPR, etype, exp, low)), 1, fold_convert (etype, integer_zero_node), value); @@ -3792,12 +3831,12 @@ fold_range_test (tree exp) unless we are at top level or LHS contains a PLACEHOLDER_EXPR, in which cases we can't do this. */ if (simple_operand_p (lhs)) - return build (TREE_CODE (exp) == TRUTH_ANDIF_EXPR - ? TRUTH_AND_EXPR : TRUTH_OR_EXPR, - TREE_TYPE (exp), TREE_OPERAND (exp, 0), - TREE_OPERAND (exp, 1)); + return build2 (TREE_CODE (exp) == TRUTH_ANDIF_EXPR + ? TRUTH_AND_EXPR : TRUTH_OR_EXPR, + TREE_TYPE (exp), TREE_OPERAND (exp, 0), + TREE_OPERAND (exp, 1)); - else if ((*lang_hooks.decls.global_bindings_p) () == 0 + else if (lang_hooks.decls.global_bindings_p () == 0 && ! CONTAINS_PLACEHOLDER_P (lhs)) { tree common = save_expr (lhs); @@ -3808,9 +3847,9 @@ fold_range_test (tree exp) && (0 != (rhs = build_range_check (TREE_TYPE (exp), common, or_op ? ! in1_p : in1_p, low1, high1)))) - return build (TREE_CODE (exp) == TRUTH_ANDIF_EXPR - ? TRUTH_AND_EXPR : TRUTH_OR_EXPR, - TREE_TYPE (exp), lhs, rhs); + return build2 (TREE_CODE (exp) == TRUTH_ANDIF_EXPR + ? TRUTH_AND_EXPR : TRUTH_OR_EXPR, + TREE_TYPE (exp), lhs, rhs); } } @@ -3844,8 +3883,8 @@ unextend (tree c, int p, int unsignedp, tree mask) do the type conversion here. At this point, the constant is either zero or one, and the conversion to a signed type can never overflow. We could get an overflow if this conversion is done anywhere else. */ - if (TREE_UNSIGNED (type)) - temp = fold_convert ((*lang_hooks.types.signed_type) (type), temp); + if (TYPE_UNSIGNED (type)) + temp = fold_convert (lang_hooks.types.signed_type (type), temp); temp = const_binop (LSHIFT_EXPR, temp, size_int (modesize - 1), 0); temp = const_binop (RSHIFT_EXPR, temp, size_int (modesize - p - 1), 0); @@ -3853,7 +3892,7 @@ unextend (tree c, int p, int unsignedp, tree mask) temp = const_binop (BIT_AND_EXPR, temp, fold_convert (TREE_TYPE (c), mask), 0); /* If necessary, convert the type back to match the type of C. */ - if (TREE_UNSIGNED (type)) + if (TYPE_UNSIGNED (type)) temp = fold_convert (type, temp); return fold_convert (type, const_binop (BIT_XOR_EXPR, c, temp, 0)); @@ -3924,10 +3963,16 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs) rcode = TREE_CODE (rhs); if (lcode == BIT_AND_EXPR && integer_onep (TREE_OPERAND (lhs, 1))) - lcode = NE_EXPR, lhs = build (NE_EXPR, truth_type, lhs, integer_zero_node); + { + lhs = build2 (NE_EXPR, truth_type, lhs, integer_zero_node); + lcode = NE_EXPR; + } if (rcode == BIT_AND_EXPR && integer_onep (TREE_OPERAND (rhs, 1))) - rcode = NE_EXPR, rhs = build (NE_EXPR, truth_type, rhs, integer_zero_node); + { + rhs = build2 (NE_EXPR, truth_type, rhs, integer_zero_node); + rcode = NE_EXPR; + } if (TREE_CODE_CLASS (lcode) != '<' || TREE_CODE_CLASS (rcode) != '<') return 0; @@ -3978,8 +4023,8 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs) else if (compcode == COMPCODE_FALSE) return fold_convert (truth_type, integer_zero_node); else if (compcode != -1) - return build (compcode_to_comparison (compcode), - truth_type, ll_arg, lr_arg); + return build2 (compcode_to_comparison (compcode), + truth_type, ll_arg, lr_arg); } /* If the RHS can be evaluated unconditionally and its operands are @@ -3998,22 +4043,22 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs) && lcode == NE_EXPR && integer_zerop (lr_arg) && rcode == NE_EXPR && integer_zerop (rr_arg) && TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)) - return build (NE_EXPR, truth_type, - build (BIT_IOR_EXPR, TREE_TYPE (ll_arg), - ll_arg, rl_arg), - integer_zero_node); + return build2 (NE_EXPR, truth_type, + build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg), + ll_arg, rl_arg), + integer_zero_node); /* Convert (a == 0) && (b == 0) into (a | b) == 0. */ if (code == TRUTH_AND_EXPR && lcode == EQ_EXPR && integer_zerop (lr_arg) && rcode == EQ_EXPR && integer_zerop (rr_arg) && TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)) - return build (EQ_EXPR, truth_type, - build (BIT_IOR_EXPR, TREE_TYPE (ll_arg), - ll_arg, rl_arg), - integer_zero_node); + return build2 (EQ_EXPR, truth_type, + build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg), + ll_arg, rl_arg), + integer_zero_node); - return build (code, truth_type, lhs, rhs); + return build2 (code, truth_type, lhs, rhs); } /* See if the comparisons can be merged. Then get all the parameters for @@ -4091,7 +4136,7 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs) /* After this point all optimizations will generate bit-field references, which we might not want. */ - if (! (*lang_hooks.can_use_bit_fields_p) ()) + if (! lang_hooks.can_use_bit_fields_p ()) return 0; /* See if we can find a mode that contains both fields being compared on @@ -4107,7 +4152,7 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs) lnbitsize = GET_MODE_BITSIZE (lnmode); lnbitpos = first_bit & ~ (lnbitsize - 1); - lntype = (*lang_hooks.types.type_for_size) (lnbitsize, 1); + lntype = lang_hooks.types.type_for_size (lnbitsize, 1); xll_bitpos = ll_bitpos - lnbitpos, xrl_bitpos = rl_bitpos - lnbitpos; if (BYTES_BIG_ENDIAN) @@ -4178,7 +4223,7 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs) rnbitsize = GET_MODE_BITSIZE (rnmode); rnbitpos = first_bit & ~ (rnbitsize - 1); - rntype = (*lang_hooks.types.type_for_size) (rnbitsize, 1); + rntype = lang_hooks.types.type_for_size (rnbitsize, 1); xlr_bitpos = lr_bitpos - rnbitpos, xrr_bitpos = rr_bitpos - rnbitpos; if (BYTES_BIG_ENDIAN) @@ -4204,14 +4249,14 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs) lhs = make_bit_field_ref (ll_inner, lntype, lnbitsize, lnbitpos, ll_unsignedp || rl_unsignedp); if (! all_ones_mask_p (ll_mask, lnbitsize)) - lhs = build (BIT_AND_EXPR, lntype, lhs, ll_mask); + lhs = build2 (BIT_AND_EXPR, lntype, lhs, ll_mask); rhs = make_bit_field_ref (lr_inner, rntype, rnbitsize, rnbitpos, lr_unsignedp || rr_unsignedp); if (! all_ones_mask_p (lr_mask, rnbitsize)) - rhs = build (BIT_AND_EXPR, rntype, rhs, lr_mask); + rhs = build2 (BIT_AND_EXPR, rntype, rhs, lr_mask); - return build (wanted_code, truth_type, lhs, rhs); + return build2 (wanted_code, truth_type, lhs, rhs); } /* There is still another way we can do something: If both pairs of @@ -4257,12 +4302,12 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs) } if (! all_ones_mask_p (ll_mask, ll_bitsize + rl_bitsize)) - lhs = build (BIT_AND_EXPR, type, lhs, ll_mask); + lhs = build2 (BIT_AND_EXPR, type, lhs, ll_mask); if (! all_ones_mask_p (lr_mask, lr_bitsize + rr_bitsize)) - rhs = build (BIT_AND_EXPR, type, rhs, lr_mask); + rhs = build2 (BIT_AND_EXPR, type, rhs, lr_mask); - return build (wanted_code, truth_type, lhs, rhs); + return build2 (wanted_code, truth_type, lhs, rhs); } return 0; @@ -4298,10 +4343,10 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs) ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask, 0); if (! all_ones_mask_p (ll_mask, lnbitsize)) - result = build (BIT_AND_EXPR, lntype, result, ll_mask); + result = build2 (BIT_AND_EXPR, lntype, result, ll_mask); - return build (wanted_code, truth_type, result, - const_binop (BIT_IOR_EXPR, l_const, r_const, 0)); + return build2 (wanted_code, truth_type, result, + const_binop (BIT_IOR_EXPR, l_const, r_const, 0)); } /* Optimize T, which is a comparison of a MIN_EXPR or MAX_EXPR with a @@ -4345,20 +4390,20 @@ optimize_minmax_comparison (tree t) case GE_EXPR: return - fold (build (TRUTH_ORIF_EXPR, type, - optimize_minmax_comparison - (build (EQ_EXPR, type, arg0, comp_const)), - optimize_minmax_comparison - (build (GT_EXPR, type, arg0, comp_const)))); + fold (build2 (TRUTH_ORIF_EXPR, type, + optimize_minmax_comparison + (build2 (EQ_EXPR, type, arg0, comp_const)), + optimize_minmax_comparison + (build2 (GT_EXPR, type, arg0, comp_const)))); case EQ_EXPR: if (op_code == MAX_EXPR && consts_equal) /* MAX (X, 0) == 0 -> X <= 0 */ - return fold (build (LE_EXPR, type, inner, comp_const)); + return fold (build2 (LE_EXPR, type, inner, comp_const)); else if (op_code == MAX_EXPR && consts_lt) /* MAX (X, 0) == 5 -> X == 5 */ - return fold (build (EQ_EXPR, type, inner, comp_const)); + return fold (build2 (EQ_EXPR, type, inner, comp_const)); else if (op_code == MAX_EXPR) /* MAX (X, 0) == -1 -> false */ @@ -4366,7 +4411,7 @@ optimize_minmax_comparison (tree t) else if (consts_equal) /* MIN (X, 0) == 0 -> X >= 0 */ - return fold (build (GE_EXPR, type, inner, comp_const)); + return fold (build2 (GE_EXPR, type, inner, comp_const)); else if (consts_lt) /* MIN (X, 0) == 5 -> false */ @@ -4374,13 +4419,13 @@ optimize_minmax_comparison (tree t) else /* MIN (X, 0) == -1 -> X == -1 */ - return fold (build (EQ_EXPR, type, inner, comp_const)); + return fold (build2 (EQ_EXPR, type, inner, comp_const)); case GT_EXPR: if (op_code == MAX_EXPR && (consts_equal || consts_lt)) /* MAX (X, 0) > 0 -> X > 0 MAX (X, 0) > 5 -> X > 5 */ - return fold (build (GT_EXPR, type, inner, comp_const)); + return fold (build2 (GT_EXPR, type, inner, comp_const)); else if (op_code == MAX_EXPR) /* MAX (X, 0) > -1 -> true */ @@ -4393,7 +4438,7 @@ optimize_minmax_comparison (tree t) else /* MIN (X, 0) > -1 -> X > -1 */ - return fold (build (GT_EXPR, type, inner, comp_const)); + return fold (build2 (GT_EXPR, type, inner, comp_const)); default: return t; @@ -4482,7 +4527,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) || TREE_CODE_CLASS (TREE_CODE (op0)) == 'e') /* ... and is unsigned, and its type is smaller than ctype, then we cannot pass through as widening. */ - && ((TREE_UNSIGNED (TREE_TYPE (op0)) + && ((TYPE_UNSIGNED (TREE_TYPE (op0)) && ! (TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE && TYPE_IS_SIZETYPE (TREE_TYPE (op0))) && (GET_MODE_SIZE (TYPE_MODE (ctype)) @@ -4494,8 +4539,8 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) /* ... or signedness changes for division or modulus, then we cannot pass through this conversion. */ || (code != MULT_EXPR - && (TREE_UNSIGNED (ctype) - != TREE_UNSIGNED (TREE_TYPE (op0)))))) + && (TYPE_UNSIGNED (ctype) + != TYPE_UNSIGNED (TREE_TYPE (op0)))))) break; /* Pass the constant down and see if we can make a simplification. If @@ -4518,7 +4563,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) case MIN_EXPR: case MAX_EXPR: /* If widening the type changes the signedness, then we can't perform this optimization as that changes the result. */ - if (TREE_UNSIGNED (ctype) != TREE_UNSIGNED (type)) + if (TYPE_UNSIGNED (ctype) != TYPE_UNSIGNED (type)) break; /* MIN (a, b) / 5 -> MIN (a / 5, b / 5) */ @@ -4528,17 +4573,11 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) if (tree_int_cst_sgn (c) < 0) tcode = (tcode == MIN_EXPR ? MAX_EXPR : MIN_EXPR); - return fold (build (tcode, ctype, fold_convert (ctype, t1), - fold_convert (ctype, t2))); + return fold (build2 (tcode, ctype, fold_convert (ctype, t1), + fold_convert (ctype, t2))); } break; - case WITH_RECORD_EXPR: - if ((t1 = extract_muldiv (TREE_OPERAND (t, 0), c, code, wide_type)) != 0) - return build (WITH_RECORD_EXPR, TREE_TYPE (t1), t1, - TREE_OPERAND (t, 1)); - break; - case LSHIFT_EXPR: case RSHIFT_EXPR: /* If the second operand is constant, this is a multiplication or floor division, by a power of two, so we can treat it that @@ -4553,9 +4592,9 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) size_one_node, op1, 0))) && ! TREE_OVERFLOW (t1)) - return extract_muldiv (build (tcode == LSHIFT_EXPR - ? MULT_EXPR : FLOOR_DIV_EXPR, - ctype, fold_convert (ctype, op0), t1), + return extract_muldiv (build2 (tcode == LSHIFT_EXPR + ? MULT_EXPR : FLOOR_DIV_EXPR, + ctype, fold_convert (ctype, op0), t1), c, code, wide_type); break; @@ -4572,8 +4611,8 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) are divisible by c. */ || (multiple_of_p (ctype, op0, c) && multiple_of_p (ctype, op1, c)))) - return fold (build (tcode, ctype, fold_convert (ctype, t1), - fold_convert (ctype, t2))); + return fold (build2 (tcode, ctype, fold_convert (ctype, t1), + fold_convert (ctype, t2))); /* If this was a subtraction, negate OP1 and set it to be an addition. This simplifies the logic below. */ @@ -4615,7 +4654,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) /* If we have an unsigned type is not a sizetype, we cannot widen the operation since it will change the result if the original computation overflowed. */ - if (TREE_UNSIGNED (ctype) + if (TYPE_UNSIGNED (ctype) && ! (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype)) && ctype != type) break; @@ -4623,17 +4662,17 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) /* If we were able to eliminate our operation from the first side, apply our operation to the second side and reform the PLUS. */ if (t1 != 0 && (TREE_CODE (t1) != code || code == MULT_EXPR)) - return fold (build (tcode, ctype, fold_convert (ctype, t1), op1)); + return fold (build2 (tcode, ctype, fold_convert (ctype, t1), op1)); /* The last case is if we are a multiply. In that case, we can apply the distributive law to commute the multiply and addition if the multiplication of the constants doesn't overflow. */ if (code == MULT_EXPR) - return fold (build (tcode, ctype, - fold (build (code, ctype, - fold_convert (ctype, op0), - fold_convert (ctype, c))), - op1)); + return fold (build2 (tcode, ctype, + fold (build2 (code, ctype, + fold_convert (ctype, op0), + fold_convert (ctype, c))), + op1)); break; @@ -4655,12 +4694,12 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) do something only if the second operand is a constant. */ if (same_p && (t1 = extract_muldiv (op0, c, code, wide_type)) != 0) - return fold (build (tcode, ctype, fold_convert (ctype, t1), - fold_convert (ctype, op1))); + return fold (build2 (tcode, ctype, fold_convert (ctype, t1), + fold_convert (ctype, op1))); else if (tcode == MULT_EXPR && code == MULT_EXPR && (t1 = extract_muldiv (op1, c, code, wide_type)) != 0) - return fold (build (tcode, ctype, fold_convert (ctype, op0), - fold_convert (ctype, t1))); + return fold (build2 (tcode, ctype, fold_convert (ctype, op0), + fold_convert (ctype, t1))); else if (TREE_CODE (op1) != INTEGER_CST) return 0; @@ -4670,7 +4709,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) && 0 != (t1 = const_binop (MULT_EXPR, fold_convert (ctype, op1), fold_convert (ctype, c), 0)) && ! TREE_OVERFLOW (t1)) - return fold (build (tcode, ctype, fold_convert (ctype, op0), t1)); + return fold (build2 (tcode, ctype, fold_convert (ctype, op0), t1)); /* If these operations "cancel" each other, we have the main optimizations of this pass, which occur when either constant is a @@ -4680,7 +4719,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) If we have an unsigned type that is not a sizetype, we cannot do this since it will change the result if the original computation overflowed. */ - if ((! TREE_UNSIGNED (ctype) + if ((! TYPE_UNSIGNED (ctype) || (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype))) && ! flag_wrapv && ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR) @@ -4689,15 +4728,15 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) && code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR))) { if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0))) - return fold (build (tcode, ctype, fold_convert (ctype, op0), - fold_convert (ctype, - const_binop (TRUNC_DIV_EXPR, - op1, c, 0)))); + return fold (build2 (tcode, ctype, fold_convert (ctype, op0), + fold_convert (ctype, + const_binop (TRUNC_DIV_EXPR, + op1, c, 0)))); else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1, 0))) - return fold (build (code, ctype, fold_convert (ctype, op0), - fold_convert (ctype, - const_binop (TRUNC_DIV_EXPR, - c, op1, 0)))); + return fold (build2 (code, ctype, fold_convert (ctype, op0), + fold_convert (ctype, + const_binop (TRUNC_DIV_EXPR, + c, op1, 0)))); } break; @@ -4708,40 +4747,6 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type) return 0; } -/* If T contains a COMPOUND_EXPR which was inserted merely to evaluate - S, a SAVE_EXPR, return the expression actually being evaluated. Note - that we may sometimes modify the tree. */ - -static tree -strip_compound_expr (tree t, tree s) -{ - enum tree_code code = TREE_CODE (t); - - /* See if this is the COMPOUND_EXPR we want to eliminate. */ - if (code == COMPOUND_EXPR && TREE_CODE (TREE_OPERAND (t, 0)) == CONVERT_EXPR - && TREE_OPERAND (TREE_OPERAND (t, 0), 0) == s) - return TREE_OPERAND (t, 1); - - /* See if this is a COND_EXPR or a simple arithmetic operator. We - don't bother handling any other types. */ - else if (code == COND_EXPR) - { - TREE_OPERAND (t, 0) = strip_compound_expr (TREE_OPERAND (t, 0), s); - TREE_OPERAND (t, 1) = strip_compound_expr (TREE_OPERAND (t, 1), s); - TREE_OPERAND (t, 2) = strip_compound_expr (TREE_OPERAND (t, 2), s); - } - else if (TREE_CODE_CLASS (code) == '1') - TREE_OPERAND (t, 0) = strip_compound_expr (TREE_OPERAND (t, 0), s); - else if (TREE_CODE_CLASS (code) == '<' - || TREE_CODE_CLASS (code) == '2') - { - TREE_OPERAND (t, 0) = strip_compound_expr (TREE_OPERAND (t, 0), s); - TREE_OPERAND (t, 1) = strip_compound_expr (TREE_OPERAND (t, 1), s); - } - - return t; -} - /* Return a node which has the indicated constant VALUE (either 0 or 1), and is of the indicated TYPE. */ @@ -4751,8 +4756,8 @@ constant_boolean_node (int value, tree type) if (type == integer_type_node) return value ? integer_one_node : integer_zero_node; else if (TREE_CODE (type) == BOOLEAN_TYPE) - return (*lang_hooks.truthvalue_conversion) (value ? integer_one_node : - integer_zero_node); + return lang_hooks.truthvalue_conversion (value ? integer_one_node + : integer_zero_node); else { tree t = build_int_2 (value, 0); @@ -4762,32 +4767,14 @@ constant_boolean_node (int value, tree type) } } -/* Utility function for the following routine, to see how complex a nesting of - COND_EXPRs can be. EXPR is the expression and LIMIT is a count beyond which - we don't care (to avoid spending too much time on complex expressions.). */ - -static int -count_cond (tree expr, int lim) -{ - int ctrue, cfalse; - - if (TREE_CODE (expr) != COND_EXPR) - return 0; - else if (lim <= 0) - return 0; - - 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 `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 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. */ + original expression. Return NULL_TREE if no simplification is + possible. */ static tree fold_binary_op_with_conditional_arg (enum tree_code code, tree type, @@ -4796,39 +4783,12 @@ fold_binary_op_with_conditional_arg (enum tree_code code, tree type, 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 analogous -- - 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; - int save = 0; - - 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; - } + + /* This transformation is only worthwhile if we don't have to wrap + arg in a SAVE_EXPR, and the operation can be simplified on atleast + one of the branches once its pushed inside the COND_EXPR. */ + if (!TREE_CONSTANT (arg)) + return NULL_TREE; if (TREE_CODE (cond) == COND_EXPR) { @@ -4837,28 +4797,11 @@ fold_binary_op_with_conditional_arg (enum tree_code code, tree type, 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'. */ + involving it. */ if (VOID_TYPE_P (TREE_TYPE (true_value))) - { - if (! cond_first_p) - { - lhs_code = COMPOUND_EXPR; - lhs_type = void_type_node; - } - else - lhs = true_value; - } + lhs = true_value; if (VOID_TYPE_P (TREE_TYPE (false_value))) - { - if (! cond_first_p) - { - rhs_code = COMPOUND_EXPR; - rhs_type = void_type_node; - } - else - rhs = false_value; - } + rhs = false_value; } else { @@ -4868,60 +4811,15 @@ fold_binary_op_with_conditional_arg (enum tree_code code, tree type, false_value = fold_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 (saved_expr_p (arg)) - 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)); - - 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; - save = saved_expr_p (arg); - } - } - if (lhs == 0) - lhs = fold (build (lhs_code, lhs_type, *true_lhs, *true_rhs)); + lhs = fold (cond_first_p ? build2 (code, type, true_value, arg) + : build2 (code, type, arg, true_value)); if (rhs == 0) - rhs = fold (build (rhs_code, rhs_type, *false_lhs, *false_rhs)); - - test = fold (build (COND_EXPR, type, test, lhs, rhs)); - - /* If ARG involves a SAVE_EXPR, we need to ensure it is evaluated - ahead of the COND_EXPR we made. Otherwise we would have it only - evaluated in one branch, with the other branch using the result - but missing the evaluation code. Beware that the save_expr call - above might not return a SAVE_EXPR, so testing the TREE_CODE - of ARG is not enough to decide here.  */ - if (save) - return build (COMPOUND_EXPR, type, - fold_convert (void_type_node, arg), - strip_compound_expr (test, arg)); - else - return fold_convert (type, test); + rhs = fold (cond_first_p ? build2 (code, type, false_value, arg) + : build2 (code, type, arg, false_value)); + + test = fold (build3 (COND_EXPR, type, test, lhs, rhs)); + return fold_convert (type, test); } @@ -4980,9 +4878,7 @@ fold_mathfn_compare (enum built_in_function fcode, enum tree_code code, { REAL_VALUE_TYPE c; - if (fcode == BUILT_IN_SQRT - || fcode == BUILT_IN_SQRTF - || fcode == BUILT_IN_SQRTL) + if (BUILTIN_SQRT_P (fcode)) { tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1)); enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg0)); @@ -5004,8 +4900,8 @@ fold_mathfn_compare (enum built_in_function fcode, enum tree_code code, arg); /* sqrt(x) > y is the same as x >= 0, if y is negative. */ - return fold (build (GE_EXPR, type, arg, - build_real (TREE_TYPE (arg), dconst0))); + return fold (build2 (GE_EXPR, type, arg, + build_real (TREE_TYPE (arg), dconst0))); } else if (code == GT_EXPR || code == GE_EXPR) { @@ -5018,8 +4914,8 @@ fold_mathfn_compare (enum built_in_function fcode, enum tree_code code, { /* sqrt(x) > y is x == +Inf, when y is very large. */ if (HONOR_INFINITIES (mode)) - return fold (build (EQ_EXPR, type, arg, - build_real (TREE_TYPE (arg), c2))); + return fold (build2 (EQ_EXPR, type, arg, + build_real (TREE_TYPE (arg), c2))); /* sqrt(x) > y is always false, when y is very large and we don't care about infinities. */ @@ -5029,8 +4925,8 @@ fold_mathfn_compare (enum built_in_function fcode, enum tree_code code, } /* sqrt(x) > c is the same as x > c*c. */ - return fold (build (code, type, arg, - build_real (TREE_TYPE (arg), c2))); + return fold (build2 (code, type, arg, + build_real (TREE_TYPE (arg), c2))); } else if (code == LT_EXPR || code == LE_EXPR) { @@ -5051,47 +4947,47 @@ fold_mathfn_compare (enum built_in_function fcode, enum tree_code code, /* sqrt(x) < y is x != +Inf when y is very large and we don't care about NaNs. */ if (! HONOR_NANS (mode)) - return fold (build (NE_EXPR, type, arg, - build_real (TREE_TYPE (arg), c2))); + return fold (build2 (NE_EXPR, type, arg, + build_real (TREE_TYPE (arg), c2))); /* sqrt(x) < y is x >= 0 when y is very large and we don't care about Infinities. */ if (! HONOR_INFINITIES (mode)) - return fold (build (GE_EXPR, type, arg, - build_real (TREE_TYPE (arg), dconst0))); + return fold (build2 (GE_EXPR, type, arg, + build_real (TREE_TYPE (arg), dconst0))); /* sqrt(x) < y is x >= 0 && x != +Inf, when y is large. */ - if ((*lang_hooks.decls.global_bindings_p) () != 0 + if (lang_hooks.decls.global_bindings_p () != 0 || CONTAINS_PLACEHOLDER_P (arg)) return NULL_TREE; arg = save_expr (arg); - return fold (build (TRUTH_ANDIF_EXPR, type, - fold (build (GE_EXPR, type, arg, - build_real (TREE_TYPE (arg), - dconst0))), - fold (build (NE_EXPR, type, arg, - build_real (TREE_TYPE (arg), - c2))))); + return fold (build2 (TRUTH_ANDIF_EXPR, type, + fold (build2 (GE_EXPR, type, arg, + build_real (TREE_TYPE (arg), + dconst0))), + fold (build2 (NE_EXPR, type, arg, + build_real (TREE_TYPE (arg), + c2))))); } /* sqrt(x) < c is the same as x < c*c, if we ignore NaNs. */ if (! HONOR_NANS (mode)) - return fold (build (code, type, arg, - build_real (TREE_TYPE (arg), c2))); + return fold (build2 (code, type, arg, + build_real (TREE_TYPE (arg), c2))); /* sqrt(x) < c is the same as x >= 0 && x < c*c. */ - if ((*lang_hooks.decls.global_bindings_p) () == 0 + if (lang_hooks.decls.global_bindings_p () == 0 && ! CONTAINS_PLACEHOLDER_P (arg)) { arg = save_expr (arg); - return fold (build (TRUTH_ANDIF_EXPR, type, - fold (build (GE_EXPR, type, arg, - build_real (TREE_TYPE (arg), - dconst0))), - fold (build (code, type, arg, - build_real (TREE_TYPE (arg), - c2))))); + return fold (build2 (TRUTH_ANDIF_EXPR, type, + fold (build2 (GE_EXPR, type, arg, + build_real (TREE_TYPE (arg), + dconst0))), + fold (build2 (code, type, arg, + build_real (TREE_TYPE (arg), + c2))))); } } } @@ -5142,11 +5038,11 @@ fold_inf_compare (enum tree_code code, tree type, tree arg0, tree arg1) arg0); /* x <= +Inf is the same as x == x, i.e. isfinite(x). */ - if ((*lang_hooks.decls.global_bindings_p) () == 0 + if (lang_hooks.decls.global_bindings_p () == 0 && ! CONTAINS_PLACEHOLDER_P (arg0)) { arg0 = save_expr (arg0); - return fold (build (EQ_EXPR, type, arg0, arg0)); + return fold (build2 (EQ_EXPR, type, arg0, arg0)); } break; @@ -5154,23 +5050,23 @@ fold_inf_compare (enum tree_code code, tree type, tree arg0, tree arg1) case GE_EXPR: /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX. */ real_maxval (&max, neg, mode); - return fold (build (neg ? LT_EXPR : GT_EXPR, type, - arg0, build_real (TREE_TYPE (arg0), max))); + return fold (build2 (neg ? LT_EXPR : GT_EXPR, type, + arg0, build_real (TREE_TYPE (arg0), max))); case LT_EXPR: /* x < +Inf is always equal to x <= DBL_MAX. */ real_maxval (&max, neg, mode); - return fold (build (neg ? GE_EXPR : LE_EXPR, type, - arg0, build_real (TREE_TYPE (arg0), max))); + return fold (build2 (neg ? GE_EXPR : LE_EXPR, type, + arg0, build_real (TREE_TYPE (arg0), max))); case NE_EXPR: /* x != +Inf is always equal to !(x > DBL_MAX). */ real_maxval (&max, neg, mode); if (! HONOR_NANS (mode)) - return fold (build (neg ? GE_EXPR : LE_EXPR, type, - arg0, build_real (TREE_TYPE (arg0), max))); - temp = fold (build (neg ? LT_EXPR : GT_EXPR, type, - arg0, build_real (TREE_TYPE (arg0), max))); + return fold (build2 (neg ? GE_EXPR : LE_EXPR, type, + arg0, build_real (TREE_TYPE (arg0), max))); + temp = fold (build2 (neg ? LT_EXPR : GT_EXPR, type, + arg0, build_real (TREE_TYPE (arg0), max))); return fold (build1 (TRUTH_NOT_EXPR, type, temp)); default: @@ -5180,6 +5076,156 @@ fold_inf_compare (enum tree_code code, tree type, tree arg0, tree arg1) return NULL_TREE; } +/* Subroutine of fold() that optimizes comparisons of a division by + a non-zero integer constant against an integer constant, i.e. + X/C1 op C2. + + CODE is the comparison operator: EQ_EXPR, NE_EXPR, GT_EXPR, LT_EXPR, + GE_EXPR or LE_EXPR. TYPE is the type of the result and ARG0 and ARG1 + are the operands of the comparison. ARG1 must be a TREE_REAL_CST. + + The function returns the constant folded tree if a simplification + can be made, and NULL_TREE otherwise. */ + +static tree +fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1) +{ + tree prod, tmp, hi, lo; + tree arg00 = TREE_OPERAND (arg0, 0); + tree arg01 = TREE_OPERAND (arg0, 1); + unsigned HOST_WIDE_INT lpart; + HOST_WIDE_INT hpart; + int overflow; + + /* We have to do this the hard way to detect unsigned overflow. + prod = int_const_binop (MULT_EXPR, arg01, arg1, 0); */ + overflow = mul_double (TREE_INT_CST_LOW (arg01), + TREE_INT_CST_HIGH (arg01), + TREE_INT_CST_LOW (arg1), + TREE_INT_CST_HIGH (arg1), &lpart, &hpart); + prod = build_int_2 (lpart, hpart); + TREE_TYPE (prod) = TREE_TYPE (arg00); + TREE_OVERFLOW (prod) = force_fit_type (prod, overflow) + || TREE_INT_CST_HIGH (prod) != hpart + || TREE_INT_CST_LOW (prod) != lpart; + TREE_CONSTANT_OVERFLOW (prod) = TREE_OVERFLOW (prod); + + if (TYPE_UNSIGNED (TREE_TYPE (arg0))) + { + tmp = int_const_binop (MINUS_EXPR, arg01, integer_one_node, 0); + lo = prod; + + /* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp, 0). */ + overflow = add_double (TREE_INT_CST_LOW (prod), + TREE_INT_CST_HIGH (prod), + TREE_INT_CST_LOW (tmp), + TREE_INT_CST_HIGH (tmp), + &lpart, &hpart); + hi = build_int_2 (lpart, hpart); + TREE_TYPE (hi) = TREE_TYPE (arg00); + TREE_OVERFLOW (hi) = force_fit_type (hi, overflow) + || TREE_INT_CST_HIGH (hi) != hpart + || TREE_INT_CST_LOW (hi) != lpart + || TREE_OVERFLOW (prod); + TREE_CONSTANT_OVERFLOW (hi) = TREE_OVERFLOW (hi); + } + else if (tree_int_cst_sgn (arg01) >= 0) + { + tmp = int_const_binop (MINUS_EXPR, arg01, integer_one_node, 0); + switch (tree_int_cst_sgn (arg1)) + { + case -1: + lo = int_const_binop (MINUS_EXPR, prod, tmp, 0); + hi = prod; + break; + + case 0: + lo = fold_negate_const (tmp, TREE_TYPE (arg0)); + hi = tmp; + break; + + case 1: + hi = int_const_binop (PLUS_EXPR, prod, tmp, 0); + lo = prod; + break; + + default: + abort (); + } + } + else + { + tmp = int_const_binop (PLUS_EXPR, arg01, integer_one_node, 0); + switch (tree_int_cst_sgn (arg1)) + { + case -1: + hi = int_const_binop (MINUS_EXPR, prod, tmp, 0); + lo = prod; + break; + + case 0: + hi = fold_negate_const (tmp, TREE_TYPE (arg0)); + lo = tmp; + break; + + case 1: + lo = int_const_binop (PLUS_EXPR, prod, tmp, 0); + hi = prod; + break; + + default: + abort (); + } + } + + switch (code) + { + case EQ_EXPR: + if (TREE_OVERFLOW (lo) && TREE_OVERFLOW (hi)) + return omit_one_operand (type, integer_zero_node, arg00); + if (TREE_OVERFLOW (hi)) + return fold (build2 (GE_EXPR, type, arg00, lo)); + if (TREE_OVERFLOW (lo)) + return fold (build2 (LE_EXPR, type, arg00, hi)); + return build_range_check (type, arg00, 1, lo, hi); + + case NE_EXPR: + if (TREE_OVERFLOW (lo) && TREE_OVERFLOW (hi)) + return omit_one_operand (type, integer_one_node, arg00); + if (TREE_OVERFLOW (hi)) + return fold (build2 (LT_EXPR, type, arg00, lo)); + if (TREE_OVERFLOW (lo)) + return fold (build2 (GT_EXPR, type, arg00, hi)); + return build_range_check (type, arg00, 0, lo, hi); + + case LT_EXPR: + if (TREE_OVERFLOW (lo)) + return omit_one_operand (type, integer_zero_node, arg00); + return fold (build2 (LT_EXPR, type, arg00, lo)); + + case LE_EXPR: + if (TREE_OVERFLOW (hi)) + return omit_one_operand (type, integer_one_node, arg00); + return fold (build2 (LE_EXPR, type, arg00, hi)); + + case GT_EXPR: + if (TREE_OVERFLOW (hi)) + return omit_one_operand (type, integer_zero_node, arg00); + return fold (build2 (GT_EXPR, type, arg00, hi)); + + case GE_EXPR: + if (TREE_OVERFLOW (lo)) + return omit_one_operand (type, integer_one_node, arg00); + return fold (build2 (GE_EXPR, type, arg00, lo)); + + default: + break; + } + + return NULL_TREE; +} + + /* If CODE with arguments ARG0 and ARG1 represents a single bit equality/inequality test, then return a simplified form of the test using shifts and logical operations. Otherwise return @@ -5223,10 +5269,10 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1, arg00 = sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1)); if (arg00 != NULL_TREE) { - tree stype = (*lang_hooks.types.signed_type) (TREE_TYPE (arg00)); - return fold (build (code == EQ_EXPR ? GE_EXPR : LT_EXPR, result_type, - fold_convert (stype, arg00), - fold_convert (stype, integer_zero_node))); + tree stype = lang_hooks.types.signed_type (TREE_TYPE (arg00)); + return fold (build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR, + result_type, fold_convert (stype, arg00), + fold_convert (stype, integer_zero_node))); } /* At this point, we know that arg0 is not testing the sign bit. */ @@ -5259,22 +5305,22 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1, ops_unsigned = 1; #endif - signed_type = (*lang_hooks.types.type_for_mode) (operand_mode, 0); - unsigned_type = (*lang_hooks.types.type_for_mode) (operand_mode, 1); + 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 = fold_convert (intermediate_type, inner); if (bitnum != 0) - inner = build (RSHIFT_EXPR, intermediate_type, - inner, size_int (bitnum)); + inner = build2 (RSHIFT_EXPR, intermediate_type, + inner, size_int (bitnum)); if (code == EQ_EXPR) - inner = build (BIT_XOR_EXPR, intermediate_type, - inner, integer_one_node); + inner = build2 (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, intermediate_type, - inner, integer_one_node); + inner = build2 (BIT_AND_EXPR, intermediate_type, + inner, integer_one_node); /* Make sure to return the proper type. */ inner = fold_convert (result_type, inner); @@ -5341,6 +5387,15 @@ tree_swap_operands_p (tree arg0, tree arg1, bool reorder) if (DECL_P (arg0)) return 1; + 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; } @@ -5348,7 +5403,7 @@ tree_swap_operands_p (tree arg0, tree arg1, bool reorder) The related simplifications include x*1 => x, x*0 => 0, etc., and application of the associative law. NOP_EXPR conversions may be removed freely (as long as we - are careful not to change the C type of the overall expression) + are careful not to change the type of the overall expression). We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR, but we can constant-fold them if they have constant operands. */ @@ -5360,14 +5415,14 @@ static tree fold (tree expr) { - tree t = expr, orig_t; + const tree t = expr; + const tree type = TREE_TYPE (expr); tree t1 = NULL_TREE; tree tem; - tree type = TREE_TYPE (expr); tree arg0 = NULL_TREE, arg1 = NULL_TREE; enum tree_code code = TREE_CODE (t); int kind = TREE_CODE_CLASS (code); - int invert; + /* WINS will be nonzero when the switch is done if all operands are constant. */ int wins = 1; @@ -5381,8 +5436,6 @@ fold (tree expr) if (kind == 'c') return t; - orig_t = t; - if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR) { tree subop; @@ -5418,14 +5471,20 @@ fold (tree expr) if (op == 0) continue; /* Valid for CALL_EXPR, at least. */ - if (kind == '<' || code == RSHIFT_EXPR) - { - /* Signedness matters here. Perhaps we can refine this - later. */ - STRIP_SIGN_NOPS (op); - } + /* Strip any conversions that don't change the mode. This is + safe for every expression, except for a comparison expression + because its signedness is derived from its operands. So, in + the latter case, only strip conversions that don't change the + signedness. + + Note that this is done as an internal manipulation within the + constant folder, in order to find the simplest representation + of the arguments so that their form can be studied. In any + cases, the appropriate type conversions should be put back in + the tree that will get out of the constant folder. */ + if (kind == '<') + STRIP_SIGN_NOPS (op); else - /* Strip any conversions that don't change the mode. */ STRIP_NOPS (op); if (TREE_CODE (op) == COMPLEX_CST) @@ -5451,7 +5510,8 @@ fold (tree expr) to ARG1 to reduce the number of tests below. */ if (commutative_tree_code (code) && tree_swap_operands_p (arg0, arg1, true)) - return fold (build (code, type, arg1, arg0)); + return fold (build2 (code, type, TREE_OPERAND (t, 1), + TREE_OPERAND (t, 0))); /* Now WINS is set as described above, ARG0 is the first operand of EXPR, @@ -5482,22 +5542,23 @@ fold (tree expr) || (TREE_CODE (arg0) == BIT_AND_EXPR && integer_onep (TREE_OPERAND (arg0, 1))))))) { - t = fold (build (code == BIT_AND_EXPR ? TRUTH_AND_EXPR - : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR - : TRUTH_XOR_EXPR, - type, arg0, arg1)); + tem = fold (build2 (code == BIT_AND_EXPR ? TRUTH_AND_EXPR + : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR + : TRUTH_XOR_EXPR, + type, fold_convert (boolean_type_node, arg0), + fold_convert (boolean_type_node, arg1))); if (code == EQ_EXPR) - t = invert_truthvalue (t); + tem = invert_truthvalue (tem); - return t; + return tem; } if (TREE_CODE_CLASS (code) == '1') { if (TREE_CODE (arg0) == COMPOUND_EXPR) - return build (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), - fold (build1 (code, type, TREE_OPERAND (arg0, 1)))); + return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), + fold (build1 (code, type, TREE_OPERAND (arg0, 1)))); else if (TREE_CODE (arg0) == COND_EXPR) { tree arg01 = TREE_OPERAND (arg0, 1); @@ -5506,8 +5567,8 @@ fold (tree expr) 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), - arg01, arg02)); + tem = fold (build3 (COND_EXPR, type, TREE_OPERAND (arg0, 0), + 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 @@ -5520,85 +5581,84 @@ fold (tree expr) if ((code == NOP_EXPR || code == CONVERT_EXPR || code == NON_LVALUE_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)) + && TREE_CODE (tem) == COND_EXPR + && TREE_CODE (TREE_OPERAND (tem, 1)) == code + && TREE_CODE (TREE_OPERAND (tem, 2)) == code + && ! VOID_TYPE_P (TREE_OPERAND (tem, 1)) + && ! VOID_TYPE_P (TREE_OPERAND (tem, 2)) + && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0)) + == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 2), 0))) + && ! (INTEGRAL_TYPE_P (TREE_TYPE (tem)) && (INTEGRAL_TYPE_P - (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0)))) - && TYPE_PRECISION (TREE_TYPE (t)) <= BITS_PER_WORD)) - t = build1 (code, type, - build (COND_EXPR, - TREE_TYPE (TREE_OPERAND - (TREE_OPERAND (t, 1), 0)), - TREE_OPERAND (t, 0), - TREE_OPERAND (TREE_OPERAND (t, 1), 0), - TREE_OPERAND (TREE_OPERAND (t, 2), 0))); - return t; + (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0)))) + && TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD)) + tem = build1 (code, type, + build3 (COND_EXPR, + TREE_TYPE (TREE_OPERAND + (TREE_OPERAND (tem, 1), 0)), + TREE_OPERAND (tem, 0), + TREE_OPERAND (TREE_OPERAND (tem, 1), 0), + TREE_OPERAND (TREE_OPERAND (tem, 2), 0))); + return tem; } else if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<') - return fold (build (COND_EXPR, type, arg0, - fold (build1 (code, type, integer_one_node)), - fold (build1 (code, type, integer_zero_node)))); + { + if (TREE_CODE (type) == BOOLEAN_TYPE) + { + arg0 = copy_node (arg0); + TREE_TYPE (arg0) = type; + return arg0; + } + else if (TREE_CODE (type) != INTEGER_TYPE) + return fold (build3 (COND_EXPR, type, arg0, + fold (build1 (code, type, + integer_one_node)), + fold (build1 (code, type, + integer_zero_node)))); + } } else if (TREE_CODE_CLASS (code) == '<' && TREE_CODE (arg0) == COMPOUND_EXPR) - return build (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), - fold (build (code, type, TREE_OPERAND (arg0, 1), arg1))); + return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), + fold (build2 (code, type, TREE_OPERAND (arg0, 1), arg1))); else if (TREE_CODE_CLASS (code) == '<' && TREE_CODE (arg1) == COMPOUND_EXPR) - return build (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0), - fold (build (code, type, arg0, TREE_OPERAND (arg1, 1)))); + return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0), + fold (build2 (code, type, arg0, TREE_OPERAND (arg1, 1)))); else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<') { + if (TREE_CODE (arg0) == COMPOUND_EXPR) + return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), + fold (build2 (code, type, TREE_OPERAND (arg0, 1), + arg1))); 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)))); - else if ((TREE_CODE (arg1) == COND_EXPR - || (TREE_CODE_CLASS (TREE_CODE (arg1)) == '<' - && TREE_CODE_CLASS (code) != '<')) - && (TREE_CODE (arg0) != COND_EXPR - || count_cond (arg0, 25) + count_cond (arg1, 25) <= 25) - && (! TREE_SIDE_EFFECTS (arg0) - || ((*lang_hooks.decls.global_bindings_p) () == 0 - && ! CONTAINS_PLACEHOLDER_P (arg0)))) - 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))); - else if ((TREE_CODE (arg0) == COND_EXPR - || (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<' - && TREE_CODE_CLASS (code) != '<')) - && (TREE_CODE (arg1) != COND_EXPR - || count_cond (arg0, 25) + count_cond (arg1, 25) <= 25) - && (! TREE_SIDE_EFFECTS (arg1) - || ((*lang_hooks.decls.global_bindings_p) () == 0 - && ! CONTAINS_PLACEHOLDER_P (arg1)))) - return - fold_binary_op_with_conditional_arg (code, type, arg0, arg1, - /*cond_first_p=*/1); + && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0))) + return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0), + fold (build2 (code, type, + arg0, TREE_OPERAND (arg1, 1)))); + + if (TREE_CODE (arg0) == COND_EXPR + || TREE_CODE_CLASS (TREE_CODE (arg0)) == '<') + { + tem = fold_binary_op_with_conditional_arg (code, type, arg0, arg1, + /*cond_first_p=*/1); + if (tem != NULL_TREE) + return tem; + } + + if (TREE_CODE (arg1) == COND_EXPR + || TREE_CODE_CLASS (TREE_CODE (arg1)) == '<') + { + tem = fold_binary_op_with_conditional_arg (code, type, arg1, arg0, + /*cond_first_p=*/0); + if (tem != NULL_TREE) + return tem; + } } switch (code) { - case INTEGER_CST: - case REAL_CST: - case VECTOR_CST: - case STRING_CST: - case COMPLEX_CST: - case CONSTRUCTOR: - return t; - case CONST_DECL: return fold (DECL_INITIAL (t)); @@ -5608,7 +5668,8 @@ fold (tree expr) case FIX_TRUNC_EXPR: case FIX_CEIL_EXPR: case FIX_FLOOR_EXPR: - if (TREE_TYPE (TREE_OPERAND (t, 0)) == TREE_TYPE (t)) + case FIX_ROUND_EXPR: + if (TREE_TYPE (TREE_OPERAND (t, 0)) == type) return TREE_OPERAND (t, 0); /* Handle cases of two conversions in a row. */ @@ -5617,31 +5678,30 @@ fold (tree expr) { tree inside_type = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0)); tree inter_type = TREE_TYPE (TREE_OPERAND (t, 0)); - tree final_type = TREE_TYPE (t); int inside_int = INTEGRAL_TYPE_P (inside_type); int inside_ptr = POINTER_TYPE_P (inside_type); int inside_float = FLOAT_TYPE_P (inside_type); unsigned int inside_prec = TYPE_PRECISION (inside_type); - int inside_unsignedp = TREE_UNSIGNED (inside_type); + int inside_unsignedp = TYPE_UNSIGNED (inside_type); int inter_int = INTEGRAL_TYPE_P (inter_type); int inter_ptr = POINTER_TYPE_P (inter_type); int inter_float = FLOAT_TYPE_P (inter_type); unsigned int inter_prec = TYPE_PRECISION (inter_type); - int inter_unsignedp = TREE_UNSIGNED (inter_type); - int final_int = INTEGRAL_TYPE_P (final_type); - int final_ptr = POINTER_TYPE_P (final_type); - int final_float = FLOAT_TYPE_P (final_type); - unsigned int final_prec = TYPE_PRECISION (final_type); - int final_unsignedp = TREE_UNSIGNED (final_type); + int inter_unsignedp = TYPE_UNSIGNED (inter_type); + int final_int = INTEGRAL_TYPE_P (type); + int final_ptr = POINTER_TYPE_P (type); + int final_float = FLOAT_TYPE_P (type); + unsigned int final_prec = TYPE_PRECISION (type); + int final_unsignedp = TYPE_UNSIGNED (type); /* In addition to the cases of two conversions in a row handled below, if we are converting something to its own type via an object of identical or wider precision, neither conversion is needed. */ - if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (final_type) + if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (type) && ((inter_int && final_int) || (inter_float && final_float)) && inter_prec >= final_prec) - return fold (build1 (code, final_type, + return fold (build1 (code, type, TREE_OPERAND (TREE_OPERAND (t, 0), 0))); /* Likewise, if the intermediate and final types are either both @@ -5654,10 +5714,10 @@ fold (tree expr) || (inter_float && inside_float)) && inter_prec >= inside_prec && (inter_float || inter_unsignedp == inside_unsignedp) - && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (final_type)) - && TYPE_MODE (final_type) == TYPE_MODE (inter_type)) + && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type)) + && TYPE_MODE (type) == TYPE_MODE (inter_type)) && ! final_ptr) - return fold (build1 (code, final_type, + return fold (build1 (code, type, TREE_OPERAND (TREE_OPERAND (t, 0), 0))); /* If we have a sign-extension of a zero-extended value, we can @@ -5665,7 +5725,7 @@ fold (tree expr) if (inside_int && inter_int && final_int && inside_prec < inter_prec && inter_prec < final_prec && inside_unsignedp && !inter_unsignedp) - return fold (build1 (code, final_type, + return fold (build1 (code, type, TREE_OPERAND (TREE_OPERAND (t, 0), 0))); /* Two conversions in a row are not needed unless: @@ -5687,10 +5747,10 @@ fold (tree expr) == (final_unsignedp && final_prec > inter_prec)) && ! (inside_ptr && inter_prec != final_prec) && ! (final_ptr && inside_prec != inter_prec) - && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (final_type)) - && TYPE_MODE (final_type) == TYPE_MODE (inter_type)) + && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type)) + && TYPE_MODE (type) == TYPE_MODE (inter_type)) && ! final_ptr) - return fold (build1 (code, final_type, + return fold (build1 (code, type, TREE_OPERAND (TREE_OPERAND (t, 0), 0))); } @@ -5703,20 +5763,20 @@ fold (tree expr) /* Don't leave an assignment inside a conversion unless assigning a bitfield. */ tree prev = TREE_OPERAND (t, 0); - if (t == orig_t) - t = copy_node (t); - TREE_OPERAND (t, 0) = TREE_OPERAND (prev, 1); + tem = copy_node (t); + TREE_OPERAND (tem, 0) = TREE_OPERAND (prev, 1); /* First do the assignment, then return converted constant. */ - t = build (COMPOUND_EXPR, TREE_TYPE (t), prev, fold (t)); - TREE_USED (t) = 1; - return t; + tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), prev, fold (tem)); + TREE_NO_WARNING (tem) = 1; + TREE_USED (tem) = 1; + return tem; } /* Convert (T)(x & c) into (T)x & (T)c, if c is an integer constants (if x has signed type, the sign bit cannot be set in c). This folds extension into the BIT_AND_EXPR. */ - if (INTEGRAL_TYPE_P (TREE_TYPE (t)) - && TREE_CODE (TREE_TYPE (t)) != BOOLEAN_TYPE + if (INTEGRAL_TYPE_P (type) + && TREE_CODE (type) != BOOLEAN_TYPE && TREE_CODE (TREE_OPERAND (t, 0)) == BIT_AND_EXPR && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == INTEGER_CST) { @@ -5724,8 +5784,8 @@ fold (tree expr) tree and0 = TREE_OPERAND (and, 0), and1 = TREE_OPERAND (and, 1); int change = 0; - if (TREE_UNSIGNED (TREE_TYPE (and)) - || (TYPE_PRECISION (TREE_TYPE (t)) + if (TYPE_UNSIGNED (TREE_TYPE (and)) + || (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (and)))) change = 1; else if (TYPE_PRECISION (TREE_TYPE (and1)) @@ -5743,19 +5803,39 @@ fold (tree expr) && (LOAD_EXTEND_OP (TYPE_MODE (TREE_TYPE (and0))) == ZERO_EXTEND)) { - tree uns = (*lang_hooks.types.unsigned_type) (TREE_TYPE (and0)); + tree uns = lang_hooks.types.unsigned_type (TREE_TYPE (and0)); and0 = fold_convert (uns, and0); and1 = fold_convert (uns, and1); } #endif } if (change) - return fold (build (BIT_AND_EXPR, TREE_TYPE (t), - fold_convert (TREE_TYPE (t), and0), - fold_convert (TREE_TYPE (t), and1))); + return fold (build2 (BIT_AND_EXPR, type, + fold_convert (type, and0), + fold_convert (type, and1))); + } + + /* Convert (T1)((T2)X op Y) into (T1)X op Y, for pointer types T1 and + T2 being pointers to types of the same size. */ + if (POINTER_TYPE_P (TREE_TYPE (t)) + && TREE_CODE_CLASS (TREE_CODE (arg0)) == '2' + && TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR + && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0)))) + { + tree arg00 = TREE_OPERAND (arg0, 0); + tree t0 = TREE_TYPE (t); + tree t1 = TREE_TYPE (arg00); + tree tt0 = TREE_TYPE (t0); + tree tt1 = TREE_TYPE (t1); + tree s0 = TYPE_SIZE (tt0); + tree s1 = TYPE_SIZE (tt1); + + if (s0 && s1 && operand_equal_p (s0, s1, OEP_ONLY_CONST)) + return build2 (TREE_CODE (arg0), t0, fold_convert (t0, arg00), + TREE_OPERAND (arg0, 1)); } - tem = fold_convert_const (code, TREE_TYPE (t), arg0); + tem = fold_convert_const (code, type, arg0); return tem ? tem : t; case VIEW_CONVERT_EXPR: @@ -5770,16 +5850,17 @@ fold (tree expr) { tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0)); if (m) - t = TREE_VALUE (m); + return TREE_VALUE (m); } return t; case RANGE_EXPR: if (TREE_CONSTANT (t) != wins) { - if (t == orig_t) - t = copy_node (t); - TREE_CONSTANT (t) = wins; + tem = copy_node (t); + TREE_CONSTANT (tem) = wins; + TREE_INVARIANT (tem) = wins; + return tem; } return t; @@ -5789,42 +5870,9 @@ fold (tree expr) return t; case ABS_EXPR: - if (wins) - { - if (TREE_CODE (arg0) == INTEGER_CST) - { - /* 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; - 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_CONSTANT_OVERFLOW (t) - = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0); - } - } - else if (TREE_CODE (arg0) == REAL_CST) - { - if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg0))) - t = build_real (type, - REAL_VALUE_NEGATE (TREE_REAL_CST (arg0))); - } - } + if (wins + && (TREE_CODE (arg0) == INTEGER_CST || TREE_CODE (arg0) == REAL_CST)) + return fold_abs_const (arg0, type); else if (TREE_CODE (arg0) == NEGATE_EXPR) return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg0, 0))); /* Convert fabs((double)float) into (double)fabsf(float). */ @@ -5845,18 +5893,18 @@ fold (tree expr) if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE) return fold_convert (type, arg0); else if (TREE_CODE (arg0) == COMPLEX_EXPR) - return build (COMPLEX_EXPR, type, - TREE_OPERAND (arg0, 0), - negate_expr (TREE_OPERAND (arg0, 1))); + return build2 (COMPLEX_EXPR, type, + TREE_OPERAND (arg0, 0), + negate_expr (TREE_OPERAND (arg0, 1))); else if (TREE_CODE (arg0) == COMPLEX_CST) 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, - TREE_OPERAND (arg0, 0))), - fold (build1 (CONJ_EXPR, - type, TREE_OPERAND (arg0, 1))))); + return fold (build2 (TREE_CODE (arg0), type, + fold (build1 (CONJ_EXPR, type, + TREE_OPERAND (arg0, 0))), + fold (build1 (CONJ_EXPR, type, + TREE_OPERAND (arg0, 1))))); else if (TREE_CODE (arg0) == CONJ_EXPR) return TREE_OPERAND (arg0, 0); return t; @@ -5864,12 +5912,13 @@ fold (tree expr) case BIT_NOT_EXPR: if (wins) { - t = build_int_2 (~ TREE_INT_CST_LOW (arg0), - ~ TREE_INT_CST_HIGH (arg0)); - TREE_TYPE (t) = type; - force_fit_type (t, 0); - TREE_OVERFLOW (t) = TREE_OVERFLOW (arg0); - TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg0); + tem = build_int_2 (~ TREE_INT_CST_LOW (arg0), + ~ TREE_INT_CST_HIGH (arg0)); + TREE_TYPE (tem) = type; + force_fit_type (tem, 0); + TREE_OVERFLOW (tem) = TREE_OVERFLOW (arg0); + TREE_CONSTANT_OVERFLOW (tem) = TREE_CONSTANT_OVERFLOW (arg0); + return tem; } else if (TREE_CODE (arg0) == BIT_NOT_EXPR) return TREE_OPERAND (arg0, 0); @@ -5878,11 +5927,12 @@ fold (tree expr) case PLUS_EXPR: /* A + (-B) -> A - B */ if (TREE_CODE (arg1) == NEGATE_EXPR) - return fold (build (MINUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0))); + return fold (build2 (MINUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0))); /* (-A) + B -> B - A */ - if (TREE_CODE (arg0) == NEGATE_EXPR) - return fold (build (MINUS_EXPR, type, arg1, TREE_OPERAND (arg0, 0))); - else if (! FLOAT_TYPE_P (type)) + if (TREE_CODE (arg0) == NEGATE_EXPR + && reorder_operands_p (TREE_OPERAND (arg0, 0), arg1)) + return fold (build2 (MINUS_EXPR, type, arg1, TREE_OPERAND (arg0, 0))); + if (! FLOAT_TYPE_P (type)) { if (integer_zerop (arg1)) return non_lvalue (fold_convert (type, arg0)); @@ -5924,18 +5974,18 @@ fold (tree expr) if (TREE_CODE (parg0) == MULT_EXPR && TREE_CODE (parg1) != MULT_EXPR) - return fold (build (PLUS_EXPR, type, - fold (build (PLUS_EXPR, type, - fold_convert (type, parg0), - fold_convert (type, marg))), - fold_convert (type, parg1))); + return fold (build2 (PLUS_EXPR, type, + fold (build2 (PLUS_EXPR, type, + fold_convert (type, parg0), + fold_convert (type, marg))), + fold_convert (type, parg1))); if (TREE_CODE (parg0) != MULT_EXPR && TREE_CODE (parg1) == MULT_EXPR) - return fold (build (PLUS_EXPR, type, - fold (build (PLUS_EXPR, type, - fold_convert (type, parg1), - fold_convert (type, marg))), - fold_convert (type, parg0))); + return fold (build2 (PLUS_EXPR, type, + fold (build2 (PLUS_EXPR, type, + fold_convert (type, parg1), + fold_convert (type, marg))), + fold_convert (type, parg0))); } if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR) @@ -5986,17 +6036,18 @@ fold (tree expr) if (exact_log2 (int11) > 0 && int01 % int11 == 0) { - alt0 = fold (build (MULT_EXPR, type, arg00, - build_int_2 (int01 / int11, 0))); + alt0 = fold (build2 (MULT_EXPR, type, arg00, + build_int_2 (int01 / int11, 0))); alt1 = arg10; same = arg11; } } if (same) - return fold (build (MULT_EXPR, type, - fold (build (PLUS_EXPR, type, alt0, alt1)), - same)); + return fold (build2 (MULT_EXPR, type, + fold (build2 (PLUS_EXPR, type, + alt0, alt1)), + same)); } } else @@ -6012,8 +6063,8 @@ fold (tree expr) /* Convert x+x into x*2.0. */ if (operand_equal_p (arg0, arg1, 0) && SCALAR_FLOAT_TYPE_P (type)) - return fold (build (MULT_EXPR, type, arg0, - build_real (type, dconst2))); + return fold (build2 (MULT_EXPR, type, arg0, + build_real (type, dconst2))); /* Convert x*c+x into x*(c+1). */ if (flag_unsafe_math_optimizations @@ -6026,8 +6077,8 @@ fold (tree expr) c = TREE_REAL_CST (TREE_OPERAND (arg0, 1)); real_arithmetic (&c, PLUS_EXPR, &c, &dconst1); - return fold (build (MULT_EXPR, type, arg1, - build_real (type, c))); + return fold (build2 (MULT_EXPR, type, arg1, + build_real (type, c))); } /* Convert x+x*c into x*(c+1). */ @@ -6041,8 +6092,8 @@ fold (tree expr) c = TREE_REAL_CST (TREE_OPERAND (arg1, 1)); real_arithmetic (&c, PLUS_EXPR, &c, &dconst1); - return fold (build (MULT_EXPR, type, arg0, - build_real (type, c))); + return fold (build2 (MULT_EXPR, type, arg0, + build_real (type, c))); } /* Convert x*c1+x*c2 into x*(c1+c2). */ @@ -6061,10 +6112,40 @@ fold (tree expr) c1 = TREE_REAL_CST (TREE_OPERAND (arg0, 1)); c2 = TREE_REAL_CST (TREE_OPERAND (arg1, 1)); real_arithmetic (&c1, PLUS_EXPR, &c1, &c2); - return fold (build (MULT_EXPR, type, - TREE_OPERAND (arg0, 0), - build_real (type, c1))); + return fold (build2 (MULT_EXPR, type, + TREE_OPERAND (arg0, 0), + build_real (type, c1))); } + /* Convert a + (b*c + d*e) into (a + b*c) + d*e */ + if (flag_unsafe_math_optimizations + && TREE_CODE (arg1) == PLUS_EXPR + && TREE_CODE (arg0) != MULT_EXPR) + { + tree tree10 = TREE_OPERAND (arg1, 0); + tree tree11 = TREE_OPERAND (arg1, 1); + if (TREE_CODE (tree11) == MULT_EXPR + && TREE_CODE (tree10) == MULT_EXPR) + { + tree tree0; + tree0 = fold (build2 (PLUS_EXPR, type, arg0, tree10)); + return fold (build2 (PLUS_EXPR, type, tree0, tree11)); + } + } + /* Convert (b*c + d*e) + a into b*c + (d*e +a) */ + if (flag_unsafe_math_optimizations + && TREE_CODE (arg0) == PLUS_EXPR + && TREE_CODE (arg1) != MULT_EXPR) + { + tree tree00 = TREE_OPERAND (arg0, 0); + tree tree01 = TREE_OPERAND (arg0, 1); + if (TREE_CODE (tree01) == MULT_EXPR + && TREE_CODE (tree00) == MULT_EXPR) + { + tree tree0; + tree0 = fold (build2 (PLUS_EXPR, type, tree01, arg1)); + return fold (build2 (PLUS_EXPR, type, tree00, tree0)); + } + } } bit_rotate: @@ -6080,7 +6161,7 @@ fold (tree 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)))) + && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0)))) { tree tree01, tree11; enum tree_code code01, code11; @@ -6097,8 +6178,8 @@ fold (tree expr) && 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), - code0 == LSHIFT_EXPR ? tree01 : tree11); + return build2 (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0), + code0 == LSHIFT_EXPR ? tree01 : tree11); else if (code11 == MINUS_EXPR) { tree tree110, tree111; @@ -6112,10 +6193,10 @@ fold (tree expr) (TREE_TYPE (TREE_OPERAND (arg0, 0)))) && operand_equal_p (tree01, tree111, 0)) - return build ((code0 == LSHIFT_EXPR - ? LROTATE_EXPR - : RROTATE_EXPR), - type, TREE_OPERAND (arg0, 0), tree01); + return build2 ((code0 == LSHIFT_EXPR + ? LROTATE_EXPR + : RROTATE_EXPR), + type, TREE_OPERAND (arg0, 0), tree01); } else if (code01 == MINUS_EXPR) { @@ -6130,10 +6211,10 @@ fold (tree expr) (TREE_TYPE (TREE_OPERAND (arg0, 0)))) && operand_equal_p (tree11, tree011, 0)) - return build ((code0 != LSHIFT_EXPR - ? LROTATE_EXPR - : RROTATE_EXPR), - type, TREE_OPERAND (arg0, 0), tree11); + return build2 ((code0 != LSHIFT_EXPR + ? LROTATE_EXPR + : RROTATE_EXPR), + type, TREE_OPERAND (arg0, 0), tree11); } } } @@ -6226,8 +6307,8 @@ fold (tree expr) { /* The return value should always have the same type as the original expression. */ - if (TREE_TYPE (t1) != TREE_TYPE (t)) - t1 = fold_convert (TREE_TYPE (t), t1); + if (TREE_TYPE (t1) != type) + t1 = fold_convert (type, t1); return t1; } @@ -6236,15 +6317,15 @@ fold (tree expr) case MINUS_EXPR: /* A - (-B) -> A + B */ if (TREE_CODE (arg1) == NEGATE_EXPR) - return fold (build (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0))); + return fold (build2 (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0))); /* (-A) - B -> (-B) - A where B is easily negated and we can swap. */ if (TREE_CODE (arg0) == NEGATE_EXPR && (FLOAT_TYPE_P (type) || (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv)) && negate_expr_p (arg1) && reorder_operands_p (arg0, arg1)) - return fold (build (MINUS_EXPR, type, negate_expr (arg1), - TREE_OPERAND (arg0, 0))); + return fold (build2 (MINUS_EXPR, type, negate_expr (arg1), + TREE_OPERAND (arg0, 0))); if (! FLOAT_TYPE_P (type)) { @@ -6258,15 +6339,15 @@ fold (tree expr) && TREE_CODE (arg1) == BIT_AND_EXPR) { if (operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)) - return fold (build (BIT_AND_EXPR, type, - fold (build1 (BIT_NOT_EXPR, type, - TREE_OPERAND (arg1, 0))), - arg0)); + return fold (build2 (BIT_AND_EXPR, type, + fold (build1 (BIT_NOT_EXPR, type, + TREE_OPERAND (arg1, 0))), + arg0)); if (operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)) - return fold (build (BIT_AND_EXPR, type, - fold (build1 (BIT_NOT_EXPR, type, - TREE_OPERAND (arg1, 1))), - arg0)); + return fold (build2 (BIT_AND_EXPR, type, + fold (build1 (BIT_NOT_EXPR, type, + TREE_OPERAND (arg1, 1))), + arg0)); } /* Fold (A & ~B) - (A & B) into (A ^ B) - B, where B is @@ -6282,9 +6363,9 @@ fold (tree expr) 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)); + tem = fold (build2 (BIT_XOR_EXPR, type, + TREE_OPERAND (arg0, 0), mask1)); + return fold (build2 (MINUS_EXPR, type, tem, mask1)); } } } @@ -6313,7 +6394,7 @@ fold (tree expr) if (!wins && negate_expr_p (arg1) && (FLOAT_TYPE_P (type) || (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv))) - return fold (build (PLUS_EXPR, type, arg0, negate_expr (arg1))); + return fold (build2 (PLUS_EXPR, type, arg0, negate_expr (arg1))); if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR @@ -6322,19 +6403,19 @@ fold (tree expr) /* (A * C) - (B * C) -> (A-B) * C. */ if (operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1), 0)) - return fold (build (MULT_EXPR, type, - fold (build (MINUS_EXPR, type, - TREE_OPERAND (arg0, 0), - TREE_OPERAND (arg1, 0))), - TREE_OPERAND (arg0, 1))); + return fold (build2 (MULT_EXPR, type, + fold (build2 (MINUS_EXPR, type, + TREE_OPERAND (arg0, 0), + TREE_OPERAND (arg1, 0))), + TREE_OPERAND (arg0, 1))); /* (A * C1) - (A * C2) -> A * (C1-C2). */ if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0)) - return fold (build (MULT_EXPR, type, - TREE_OPERAND (arg0, 0), - fold (build (MINUS_EXPR, type, - TREE_OPERAND (arg0, 1), - TREE_OPERAND (arg1, 1))))); + return fold (build2 (MULT_EXPR, type, + TREE_OPERAND (arg0, 0), + fold (build2 (MINUS_EXPR, type, + TREE_OPERAND (arg0, 1), + TREE_OPERAND (arg1, 1))))); } goto associate; @@ -6342,13 +6423,13 @@ fold (tree expr) case MULT_EXPR: /* (-A) * (-B) -> A * B */ if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1)) - return fold (build (MULT_EXPR, type, - TREE_OPERAND (arg0, 0), - negate_expr (arg1))); + return fold (build2 (MULT_EXPR, type, + TREE_OPERAND (arg0, 0), + negate_expr (arg1))); if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0)) - return fold (build (MULT_EXPR, type, - negate_expr (arg0), - TREE_OPERAND (arg1, 0))); + return fold (build2 (MULT_EXPR, type, + negate_expr (arg0), + TREE_OPERAND (arg1, 0))); if (! FLOAT_TYPE_P (type)) { @@ -6360,12 +6441,12 @@ fold (tree expr) /* (a * (1 << b)) is (a << b) */ if (TREE_CODE (arg1) == LSHIFT_EXPR && integer_onep (TREE_OPERAND (arg1, 0))) - return fold (build (LSHIFT_EXPR, type, arg0, - TREE_OPERAND (arg1, 1))); + return fold (build2 (LSHIFT_EXPR, type, arg0, + TREE_OPERAND (arg1, 1))); if (TREE_CODE (arg0) == LSHIFT_EXPR && integer_onep (TREE_OPERAND (arg0, 0))) - return fold (build (LSHIFT_EXPR, type, arg1, - TREE_OPERAND (arg0, 1))); + return fold (build2 (LSHIFT_EXPR, type, arg1, + TREE_OPERAND (arg0, 1))); if (TREE_CODE (arg1) == INTEGER_CST && 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), @@ -6392,7 +6473,7 @@ fold (tree expr) /* Transform x * -1.0 into -x. */ if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))) && real_minus_onep (arg1)) - return fold (build1 (NEGATE_EXPR, type, arg0)); + return fold_convert (type, negate_expr (arg0)); /* Convert (C1/X)*C2 into (C1*C2)/X. */ if (flag_unsafe_math_optimizations @@ -6403,8 +6484,8 @@ fold (tree expr) tree tem = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 0), arg1, 0); if (tem) - return fold (build (RDIV_EXPR, type, tem, - TREE_OPERAND (arg0, 1))); + return fold (build2 (RDIV_EXPR, type, tem, + TREE_OPERAND (arg0, 1))); } if (flag_unsafe_math_optimizations) @@ -6412,46 +6493,33 @@ fold (tree expr) enum built_in_function fcode0 = builtin_mathfn_code (arg0); enum built_in_function fcode1 = builtin_mathfn_code (arg1); - /* Optimizations of sqrt(...)*sqrt(...). */ - 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)) + /* Optimizations of root(...)*root(...). */ + if (fcode0 == fcode1 && BUILTIN_ROOT_P (fcode0)) { - tree sqrtfn, arg, arglist; + tree rootfn, arg, arglist; tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1)); tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1)); /* Optimize sqrt(x)*sqrt(x) as x. */ - if (operand_equal_p (arg00, arg10, 0) + if (BUILTIN_SQRT_P (fcode0) + && operand_equal_p (arg00, arg10, 0) && ! HONOR_SNANS (TYPE_MODE (type))) return arg00; - /* Optimize sqrt(x)*sqrt(y) as sqrt(x*y). */ - sqrtfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); - arg = fold (build (MULT_EXPR, type, arg00, arg10)); + /* Optimize root(x)*root(y) as root(x*y). */ + rootfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); + arg = fold (build2 (MULT_EXPR, type, arg00, arg10)); arglist = build_tree_list (NULL_TREE, arg); - return build_function_call_expr (sqrtfn, arglist); + return build_function_call_expr (rootfn, arglist); } /* 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)) + if (fcode0 == fcode1 && BUILTIN_EXPONENT_P (fcode0)) { 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 arg = build2 (PLUS_EXPR, type, + TREE_VALUE (TREE_OPERAND (arg0, 1)), + TREE_VALUE (TREE_OPERAND (arg1, 1))); tree arglist = build_tree_list (NULL_TREE, fold (arg)); return build_function_call_expr (expfn, arglist); } @@ -6472,7 +6540,7 @@ fold (tree expr) if (operand_equal_p (arg01, arg11, 0)) { tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); - tree arg = build (MULT_EXPR, type, arg00, arg10); + tree arg = build2 (MULT_EXPR, type, arg00, arg10); tree arglist = tree_cons (NULL_TREE, fold (arg), build_tree_list (NULL_TREE, arg01)); @@ -6483,7 +6551,7 @@ fold (tree expr) if (operand_equal_p (arg00, arg10, 0)) { tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); - tree arg = fold (build (PLUS_EXPR, type, arg01, arg11)); + tree arg = fold (build2 (PLUS_EXPR, type, arg01, arg11)); tree arglist = tree_cons (NULL_TREE, arg00, build_tree_list (NULL_TREE, arg)); @@ -6501,25 +6569,7 @@ fold (tree expr) && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)), TREE_VALUE (TREE_OPERAND (arg1, 1)), 0)) { - tree sinfn; - - switch (fcode0) - { - case BUILT_IN_TAN: - case BUILT_IN_COS: - sinfn = implicit_built_in_decls[BUILT_IN_SIN]; - break; - case BUILT_IN_TANF: - case BUILT_IN_COSF: - sinfn = implicit_built_in_decls[BUILT_IN_SINF]; - break; - case BUILT_IN_TANL: - case BUILT_IN_COSL: - sinfn = implicit_built_in_decls[BUILT_IN_SINL]; - break; - default: - sinfn = NULL_TREE; - } + tree sinfn = mathfn_built_in (type, BUILT_IN_SIN); if (sinfn != NULL_TREE) return build_function_call_expr (sinfn, @@ -6580,16 +6630,7 @@ fold (tree expr) if (! optimize_size && operand_equal_p (arg0, arg1, 0)) { - tree powfn; - - if (type == double_type_node) - powfn = implicit_built_in_decls[BUILT_IN_POW]; - else if (type == float_type_node) - powfn = implicit_built_in_decls[BUILT_IN_POWF]; - else if (type == long_double_type_node) - powfn = implicit_built_in_decls[BUILT_IN_POWL]; - else - powfn = NULL_TREE; + tree powfn = mathfn_built_in (type, BUILT_IN_POW); if (powfn) { @@ -6609,6 +6650,8 @@ fold (tree expr) return omit_one_operand (type, arg1, arg0); if (integer_zerop (arg1)) return non_lvalue (fold_convert (type, arg0)); + if (operand_equal_p (arg0, arg1, 0)) + return non_lvalue (fold_convert (type, arg0)); t1 = distribute_bit_expr (code, type, arg0, arg1); if (t1 != NULL_TREE) return t1; @@ -6623,9 +6666,9 @@ fold (tree expr) && TREE_CODE (arg1) == BIT_NOT_EXPR) { return fold (build1 (BIT_NOT_EXPR, type, - build (BIT_AND_EXPR, type, - TREE_OPERAND (arg0, 0), - TREE_OPERAND (arg1, 0)))); + build2 (BIT_AND_EXPR, type, + TREE_OPERAND (arg0, 0), + TREE_OPERAND (arg1, 0)))); } /* See if this can be simplified into a rotate first. If that @@ -6637,6 +6680,8 @@ fold (tree expr) return non_lvalue (fold_convert (type, arg0)); if (integer_all_onesp (arg1)) return fold (build1 (BIT_NOT_EXPR, type, arg0)); + if (operand_equal_p (arg0, arg1, 0)) + return omit_one_operand (type, integer_zero_node, arg0); /* If we are XORing two BIT_AND_EXPR's, both of which are and'ing with a constant, and the two constants have no bits in common, @@ -6663,12 +6708,14 @@ fold (tree expr) return non_lvalue (fold_convert (type, arg0)); if (integer_zerop (arg1)) return omit_one_operand (type, arg1, arg0); + if (operand_equal_p (arg0, arg1, 0)) + return non_lvalue (fold_convert (type, arg0)); t1 = distribute_bit_expr (code, type, arg0, arg1); if (t1 != NULL_TREE) return t1; /* Simplify ((int)c & 0377) into (int)c, if c is unsigned char. */ if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR - && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0)))) + && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0)))) { unsigned int prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))); @@ -6689,9 +6736,9 @@ fold (tree expr) && TREE_CODE (arg1) == BIT_NOT_EXPR) { return fold (build1 (BIT_NOT_EXPR, type, - build (BIT_IOR_EXPR, type, - TREE_OPERAND (arg0, 0), - TREE_OPERAND (arg1, 0)))); + build2 (BIT_IOR_EXPR, type, + TREE_OPERAND (arg0, 0), + TREE_OPERAND (arg1, 0)))); } goto associate; @@ -6706,13 +6753,13 @@ fold (tree expr) /* (-A) / (-B) -> A / B */ if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1)) - return fold (build (RDIV_EXPR, type, - TREE_OPERAND (arg0, 0), - negate_expr (arg1))); + return fold (build2 (RDIV_EXPR, type, + TREE_OPERAND (arg0, 0), + negate_expr (arg1))); if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0)) - return fold (build (RDIV_EXPR, type, - negate_expr (arg0), - TREE_OPERAND (arg1, 0))); + return fold (build2 (RDIV_EXPR, type, + negate_expr (arg0), + TREE_OPERAND (arg1, 0))); /* In IEEE floating point, x/1 is not equivalent to x for snans. */ if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))) @@ -6734,7 +6781,7 @@ fold (tree expr) if (flag_unsafe_math_optimizations && 0 != (tem = const_binop (code, build_real (type, dconst1), arg1, 0))) - return fold (build (MULT_EXPR, type, arg0, tem)); + return fold (build2 (MULT_EXPR, type, arg0, tem)); /* Find the reciprocal if optimizing and the result is exact. */ if (optimize) { @@ -6743,24 +6790,24 @@ fold (tree expr) if (exact_real_inverse (TYPE_MODE(TREE_TYPE(arg0)), &r)) { tem = build_real (type, r); - return fold (build (MULT_EXPR, type, arg0, tem)); + return fold (build2 (MULT_EXPR, type, arg0, tem)); } } } /* Convert A/B/C to A/(B*C). */ if (flag_unsafe_math_optimizations && TREE_CODE (arg0) == RDIV_EXPR) - return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0), - fold (build (MULT_EXPR, type, - TREE_OPERAND (arg0, 1), arg1)))); + return fold (build2 (RDIV_EXPR, type, TREE_OPERAND (arg0, 0), + fold (build2 (MULT_EXPR, type, + TREE_OPERAND (arg0, 1), arg1)))); /* Convert A/(B/C) to (A/B)*C. */ if (flag_unsafe_math_optimizations && TREE_CODE (arg1) == RDIV_EXPR) - return fold (build (MULT_EXPR, type, - fold (build (RDIV_EXPR, type, arg0, - TREE_OPERAND (arg1, 0))), - TREE_OPERAND (arg1, 1))); + return fold (build2 (MULT_EXPR, type, + fold (build2 (RDIV_EXPR, type, arg0, + TREE_OPERAND (arg1, 0))), + TREE_OPERAND (arg1, 1))); /* Convert C1/(X*C2) into (C1/C2)/X. */ if (flag_unsafe_math_optimizations @@ -6771,33 +6818,22 @@ fold (tree expr) tree tem = const_binop (RDIV_EXPR, arg0, TREE_OPERAND (arg1, 1), 0); if (tem) - return fold (build (RDIV_EXPR, type, tem, - TREE_OPERAND (arg1, 0))); + return fold (build2 (RDIV_EXPR, type, tem, + TREE_OPERAND (arg1, 0))); } if (flag_unsafe_math_optimizations) { enum built_in_function fcode = builtin_mathfn_code (arg1); /* Optimize x/expN(y) into x*expN(-y). */ - if (fcode == BUILT_IN_EXP - || fcode == BUILT_IN_EXPF - || 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) + if (BUILTIN_EXPONENT_P (fcode)) { 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, fold (arg)); + tree arg = negate_expr (TREE_VALUE (TREE_OPERAND (arg1, 1))); + tree arglist = build_tree_list (NULL_TREE, + fold_convert (type, arg)); arg1 = build_function_call_expr (expfn, arglist); - return fold (build (MULT_EXPR, type, arg0, arg1)); + return fold (build2 (MULT_EXPR, type, arg0, arg1)); } /* Optimize x/pow(y,z) into x*pow(y,-z). */ @@ -6808,11 +6844,11 @@ fold (tree expr) tree powfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0); tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1)); tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1, 1))); - tree neg11 = fold (build1 (NEGATE_EXPR, type, arg11)); + tree neg11 = fold_convert (type, negate_expr (arg11)); tree arglist = tree_cons(NULL_TREE, arg10, build_tree_list (NULL_TREE, neg11)); arg1 = build_function_call_expr (powfn, arglist); - return fold (build (MULT_EXPR, type, arg0, arg1)); + return fold (build2 (MULT_EXPR, type, arg0, arg1)); } } @@ -6828,16 +6864,7 @@ fold (tree expr) && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)), TREE_VALUE (TREE_OPERAND (arg1, 1)), 0)) { - tree tanfn; - - if (fcode0 == BUILT_IN_SIN) - tanfn = implicit_built_in_decls[BUILT_IN_TAN]; - else if (fcode0 == BUILT_IN_SINF) - tanfn = implicit_built_in_decls[BUILT_IN_TANF]; - else if (fcode0 == BUILT_IN_SINL) - tanfn = implicit_built_in_decls[BUILT_IN_TANL]; - else - tanfn = NULL_TREE; + tree tanfn = mathfn_built_in (type, BUILT_IN_TAN); if (tanfn != NULL_TREE) return build_function_call_expr (tanfn, @@ -6851,24 +6878,14 @@ fold (tree expr) && operand_equal_p (TREE_VALUE (TREE_OPERAND (arg0, 1)), TREE_VALUE (TREE_OPERAND (arg1, 1)), 0)) { - tree tanfn; - - if (fcode0 == BUILT_IN_COS) - tanfn = implicit_built_in_decls[BUILT_IN_TAN]; - else if (fcode0 == BUILT_IN_COSF) - tanfn = implicit_built_in_decls[BUILT_IN_TANF]; - else if (fcode0 == BUILT_IN_COSL) - tanfn = implicit_built_in_decls[BUILT_IN_TANL]; - else - tanfn = NULL_TREE; + tree tanfn = mathfn_built_in (type, BUILT_IN_TAN); if (tanfn != NULL_TREE) { tree tmp = TREE_OPERAND (arg0, 1); tmp = build_function_call_expr (tanfn, tmp); - return fold (build (RDIV_EXPR, type, - build_real (type, dconst1), - tmp)); + return fold (build2 (RDIV_EXPR, type, + build_real (type, dconst1), tmp)); } } @@ -6907,6 +6924,12 @@ fold (tree expr) return non_lvalue (fold_convert (type, arg0)); if (integer_zerop (arg1)) return t; + /* X / -1 is -X. */ + if (!TYPE_UNSIGNED (type) + && TREE_CODE (arg1) == INTEGER_CST + && TREE_INT_CST_LOW (arg1) == (unsigned HOST_WIDE_INT) -1 + && TREE_INT_CST_HIGH (arg1) == -1) + return fold_convert (type, negate_expr (arg0)); /* If arg0 is a multiple of arg1, then rewrite to the fastest div operation, EXACT_DIV_EXPR. @@ -6916,7 +6939,7 @@ fold (tree expr) after the last round to changes to the DIV code in expmed.c. */ if ((code == CEIL_DIV_EXPR || code == FLOOR_DIV_EXPR) && multiple_of_p (type, arg0, arg1)) - return fold (build (EXACT_DIV_EXPR, type, arg0, arg1)); + return fold (build2 (EXACT_DIV_EXPR, type, arg0, arg1)); if (TREE_CODE (arg1) == INTEGER_CST && 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1, @@ -6933,6 +6956,12 @@ fold (tree expr) return omit_one_operand (type, integer_zero_node, arg0); if (integer_zerop (arg1)) return t; + /* X % -1 is zero. */ + if (!TYPE_UNSIGNED (type) + && TREE_CODE (arg1) == INTEGER_CST + && TREE_INT_CST_LOW (arg1) == (unsigned HOST_WIDE_INT) -1 + && TREE_INT_CST_HIGH (arg1) == -1) + return omit_one_operand (type, integer_zero_node, arg0); if (TREE_CODE (arg1) == INTEGER_CST && 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1, @@ -6949,7 +6978,7 @@ fold (tree expr) case RSHIFT_EXPR: /* Optimize -1 >> x for arithmetic right shifts. */ - if (integer_all_onesp (arg0) && ! TREE_UNSIGNED (type)) + if (integer_all_onesp (arg0) && !TYPE_UNSIGNED (type)) return omit_one_operand (type, arg0, arg1); /* ... fall through ... */ @@ -6971,7 +7000,7 @@ fold (tree expr) tree tem = build_int_2 (GET_MODE_BITSIZE (TYPE_MODE (type)), 0); tem = fold_convert (TREE_TYPE (arg1), tem); tem = const_binop (MINUS_EXPR, tem, arg1, 0); - return fold (build (RROTATE_EXPR, type, arg0, tem)); + return fold (build2 (RROTATE_EXPR, type, arg0, tem)); } /* If we have a rotate of a bit operation with the rotate count and @@ -6982,11 +7011,11 @@ fold (tree expr) || TREE_CODE (arg0) == BIT_IOR_EXPR || TREE_CODE (arg0) == BIT_XOR_EXPR) && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST) - return fold (build (TREE_CODE (arg0), type, - fold (build (code, type, - TREE_OPERAND (arg0, 0), arg1)), - fold (build (code, type, - TREE_OPERAND (arg0, 1), arg1)))); + return fold (build2 (TREE_CODE (arg0), type, + fold (build2 (code, type, + TREE_OPERAND (arg0, 0), arg1)), + fold (build2 (code, type, + TREE_OPERAND (arg0, 1), arg1)))); /* Two consecutive rotates adding up to the width of the mode can be ignored. */ @@ -7006,7 +7035,7 @@ fold (tree expr) if (operand_equal_p (arg0, arg1, 0)) return omit_one_operand (type, arg0, arg1); if (INTEGRAL_TYPE_P (type) - && operand_equal_p (arg1, TYPE_MIN_VALUE (type), 1)) + && operand_equal_p (arg1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST)) return omit_one_operand (type, arg1, arg0); goto associate; @@ -7015,7 +7044,7 @@ fold (tree expr) return omit_one_operand (type, arg0, arg1); if (INTEGRAL_TYPE_P (type) && TYPE_MAX_VALUE (type) - && operand_equal_p (arg1, TYPE_MAX_VALUE (type), 1)) + && operand_equal_p (arg1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST)) return omit_one_operand (type, arg1, arg0); goto associate; @@ -7087,23 +7116,23 @@ fold (tree expr) || code == TRUTH_OR_EXPR)); if (operand_equal_p (a00, a10, 0)) - return fold (build (TREE_CODE (arg0), type, a00, - fold (build (code, type, a01, a11)))); + return fold (build2 (TREE_CODE (arg0), type, a00, + fold (build2 (code, type, a01, a11)))); else if (commutative && operand_equal_p (a00, a11, 0)) - return fold (build (TREE_CODE (arg0), type, a00, - fold (build (code, type, a01, a10)))); + return fold (build2 (TREE_CODE (arg0), type, a00, + fold (build2 (code, type, a01, a10)))); else if (commutative && operand_equal_p (a01, a10, 0)) - return fold (build (TREE_CODE (arg0), type, a01, - fold (build (code, type, a00, a11)))); + return fold (build2 (TREE_CODE (arg0), type, a01, + fold (build2 (code, type, a00, a11)))); /* This case if tricky because we must either have commutative operators or else A10 must not have side-effects. */ else if ((commutative || ! TREE_SIDE_EFFECTS (a10)) && operand_equal_p (a01, a11, 0)) - return fold (build (TREE_CODE (arg0), type, - fold (build (code, type, a00, a10)), - a01)); + return fold (build2 (TREE_CODE (arg0), type, + fold (build2 (code, type, a00, a10)), + a01)); } /* See if we can build a range comparison. */ @@ -7116,7 +7145,7 @@ fold (tree expr) if (TREE_CODE (arg0) == code && 0 != (tem = fold_truthop (code, type, TREE_OPERAND (arg0, 1), arg1))) - return fold (build (code, type, TREE_OPERAND (arg0, 0), tem)); + return fold (build2 (code, type, TREE_OPERAND (arg0, 0), tem)); if ((tem = fold_truthop (code, type, arg0, arg1)) != 0) return tem; @@ -7159,6 +7188,9 @@ fold (tree expr) return non_lvalue (fold_convert (type, invert_truthvalue (arg1))); if (integer_onep (arg1)) return non_lvalue (fold_convert (type, invert_truthvalue (arg0))); + /* Identical arguments cancel to zero. */ + if (operand_equal_p (arg0, arg1, 0)) + return omit_one_operand (type, integer_zero_node, arg0); return t; case EQ_EXPR: @@ -7169,27 +7201,66 @@ fold (tree expr) case GE_EXPR: /* If one arg is a real or integer constant, put it last. */ if (tree_swap_operands_p (arg0, arg1, true)) - return fold (build (swap_tree_comparison (code), type, arg1, arg0)); + return fold (build2 (swap_tree_comparison (code), type, arg1, arg0)); - if (FLOAT_TYPE_P (TREE_TYPE (arg0))) + /* If this is an equality comparison of the address of a non-weak + object against zero, then we know the result. */ + if ((code == EQ_EXPR || code == NE_EXPR) + && TREE_CODE (arg0) == ADDR_EXPR + && DECL_P (TREE_OPERAND (arg0, 0)) + && ! DECL_WEAK (TREE_OPERAND (arg0, 0)) + && integer_zerop (arg1)) { - tree targ0 = strip_float_extensions (arg0); - tree targ1 = strip_float_extensions (arg1); - tree newtype = TREE_TYPE (targ0); + if (code == EQ_EXPR) + return fold_convert (type, integer_zero_node); + else + return fold_convert (type, integer_one_node); + } - if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype)) - newtype = TREE_TYPE (targ1); + /* If this is an equality comparison of the address of two non-weak, + unaliased symbols neither of which are extern (since we do not + have access to attributes for externs), then we know the result. */ + if ((code == EQ_EXPR || code == NE_EXPR) + && TREE_CODE (arg0) == ADDR_EXPR + && DECL_P (TREE_OPERAND (arg0, 0)) + && ! DECL_WEAK (TREE_OPERAND (arg0, 0)) + && ! lookup_attribute ("alias", + DECL_ATTRIBUTES (TREE_OPERAND (arg0, 0))) + && ! DECL_EXTERNAL (TREE_OPERAND (arg0, 0)) + && TREE_CODE (arg1) == ADDR_EXPR + && DECL_P (TREE_OPERAND (arg1, 0)) + && ! DECL_WEAK (TREE_OPERAND (arg1, 0)) + && ! lookup_attribute ("alias", + DECL_ATTRIBUTES (TREE_OPERAND (arg1, 0))) + && ! DECL_EXTERNAL (TREE_OPERAND (arg1, 0))) + { + if (code == EQ_EXPR) + return fold_convert (type, (operand_equal_p (arg0, arg1, 0) + ? integer_one_node : integer_zero_node)); + else + return fold_convert (type, (operand_equal_p (arg0, arg1, 0) + ? integer_zero_node : integer_one_node)); + } + + if (FLOAT_TYPE_P (TREE_TYPE (arg0))) + { + tree targ0 = strip_float_extensions (arg0); + tree targ1 = strip_float_extensions (arg1); + tree newtype = TREE_TYPE (targ0); + + if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype)) + newtype = TREE_TYPE (targ1); /* Fold (double)float1 CMP (double)float2 into float1 CMP float2. */ if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0))) - return fold (build (code, type, fold_convert (newtype, targ0), - fold_convert (newtype, targ1))); + return fold (build2 (code, type, fold_convert (newtype, targ0), + fold_convert (newtype, targ1))); /* (-a) CMP (-b) -> b CMP a */ if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR) - return fold (build (code, type, TREE_OPERAND (arg1, 0), - TREE_OPERAND (arg0, 0))); + return fold (build2 (code, type, TREE_OPERAND (arg1, 0), + TREE_OPERAND (arg0, 0))); if (TREE_CODE (arg1) == REAL_CST) { @@ -7199,23 +7270,23 @@ fold (tree expr) /* (-a) CMP CST -> a swap(CMP) (-CST) */ if (TREE_CODE (arg0) == NEGATE_EXPR) return - fold (build (swap_tree_comparison (code), type, - TREE_OPERAND (arg0, 0), - build_real (TREE_TYPE (arg1), - REAL_VALUE_NEGATE (cst)))); + fold (build2 (swap_tree_comparison (code), type, + TREE_OPERAND (arg0, 0), + build_real (TREE_TYPE (arg1), + REAL_VALUE_NEGATE (cst)))); /* IEEE doesn't distinguish +0 and -0 in comparisons. */ /* a CMP (-0) -> a CMP 0 */ if (REAL_VALUE_MINUS_ZERO (cst)) - return fold (build (code, type, arg0, - build_real (TREE_TYPE (arg1), dconst0))); + return fold (build2 (code, type, arg0, + build_real (TREE_TYPE (arg1), dconst0))); /* x != NaN is always true, other ops are always false. */ if (REAL_VALUE_ISNAN (cst) && ! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))) { - t = (code == NE_EXPR) ? integer_one_node : integer_zero_node; - return omit_one_operand (type, fold_convert (type, t), arg0); + tem = (code == NE_EXPR) ? integer_one_node : integer_zero_node; + return omit_one_operand (type, fold_convert (type, tem), arg0); } /* Fold comparisons against infinity. */ @@ -7240,7 +7311,7 @@ fold (tree expr) ? MINUS_EXPR : PLUS_EXPR, arg1, TREE_OPERAND (arg0, 1), 0)) && ! TREE_CONSTANT_OVERFLOW (tem)) - return fold (build (code, type, TREE_OPERAND (arg0, 0), tem)); + return fold (build2 (code, type, TREE_OPERAND (arg0, 0), tem)); /* Likewise, we can simplify a comparison of a real constant with a MINUS_EXPR whose first operand is also a real constant, i.e. @@ -7252,8 +7323,8 @@ fold (tree expr) && 0 != (tem = const_binop (MINUS_EXPR, TREE_OPERAND (arg0, 0), arg1, 0)) && ! TREE_CONSTANT_OVERFLOW (tem)) - return fold (build (swap_tree_comparison (code), type, - TREE_OPERAND (arg0, 1), tem)); + return fold (build2 (swap_tree_comparison (code), type, + TREE_OPERAND (arg0, 1), tem)); /* Fold comparisons against built-in math functions. */ if (TREE_CODE (arg1) == REAL_CST @@ -7271,150 +7342,67 @@ fold (tree expr) } } - /* Convert foo++ == CONST into ++foo == CONST + INCR. - First, see if one arg is constant; find the constant arg - and the other one. */ - { - tree constop = 0, varop = NULL_TREE; - int constopnum = -1; + /* Convert foo++ == CONST into ++foo == CONST + INCR. */ + if (TREE_CONSTANT (arg1) + && (TREE_CODE (arg0) == POSTINCREMENT_EXPR + || TREE_CODE (arg0) == POSTDECREMENT_EXPR) + /* This optimization is invalid for ordered comparisons + if CONST+INCR overflows or if foo+incr might overflow. + This optimization is invalid for floating point due to rounding. + For pointer types we assume overflow doesn't happen. */ + && (POINTER_TYPE_P (TREE_TYPE (arg0)) + || (INTEGRAL_TYPE_P (TREE_TYPE (arg0)) + && (code == EQ_EXPR || code == NE_EXPR)))) + { + tree varop, newconst; - if (TREE_CONSTANT (arg1)) - constopnum = 1, constop = arg1, varop = arg0; - if (TREE_CONSTANT (arg0)) - constopnum = 0, constop = arg0, varop = arg1; + if (TREE_CODE (arg0) == POSTINCREMENT_EXPR) + { + newconst = fold (build2 (PLUS_EXPR, TREE_TYPE (arg0), + arg1, TREE_OPERAND (arg0, 1))); + varop = build2 (PREINCREMENT_EXPR, TREE_TYPE (arg0), + TREE_OPERAND (arg0, 0), + TREE_OPERAND (arg0, 1)); + } + else + { + newconst = fold (build2 (MINUS_EXPR, TREE_TYPE (arg0), + arg1, TREE_OPERAND (arg0, 1))); + varop = build2 (PREDECREMENT_EXPR, TREE_TYPE (arg0), + TREE_OPERAND (arg0, 0), + TREE_OPERAND (arg0, 1)); + } - if (constop && TREE_CODE (varop) == POSTINCREMENT_EXPR) - { - /* This optimization is invalid for ordered comparisons - if CONST+INCR overflows or if foo+incr might overflow. - This optimization is invalid for floating point due to rounding. - For pointer types we assume overflow doesn't happen. */ - if (POINTER_TYPE_P (TREE_TYPE (varop)) - || (! FLOAT_TYPE_P (TREE_TYPE (varop)) - && (code == EQ_EXPR || code == NE_EXPR))) - { - tree newconst - = fold (build (PLUS_EXPR, TREE_TYPE (varop), - constop, TREE_OPERAND (varop, 1))); - - /* Do not overwrite the current varop to be a preincrement, - create a new node so that we won't confuse our caller who - might create trees and throw them away, reusing the - arguments that they passed to build. This shows up in - the THEN or ELSE parts of ?: being postincrements. */ - varop = build (PREINCREMENT_EXPR, TREE_TYPE (varop), - TREE_OPERAND (varop, 0), - TREE_OPERAND (varop, 1)); - - /* If VAROP is a reference to a bitfield, we must mask - the constant by the width of the field. */ - if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF - && DECL_BIT_FIELD(TREE_OPERAND - (TREE_OPERAND (varop, 0), 1))) - { - int size - = TREE_INT_CST_LOW (DECL_SIZE - (TREE_OPERAND - (TREE_OPERAND (varop, 0), 1))); - tree mask, unsigned_type; - unsigned int precision; - tree folded_compare; - - /* First check whether the comparison would come out - always the same. If we don't do that we would - change the meaning with the masking. */ - if (constopnum == 0) - folded_compare = fold (build (code, type, constop, - TREE_OPERAND (varop, 0))); - else - folded_compare = fold (build (code, type, - TREE_OPERAND (varop, 0), - constop)); - if (integer_zerop (folded_compare) - || integer_onep (folded_compare)) - return omit_one_operand (type, folded_compare, varop); - - unsigned_type = (*lang_hooks.types.type_for_size)(size, 1); - precision = TYPE_PRECISION (unsigned_type); - mask = build_int_2 (~0, ~0); - TREE_TYPE (mask) = unsigned_type; - force_fit_type (mask, 0); - mask = const_binop (RSHIFT_EXPR, mask, - size_int (precision - size), 0); - newconst = fold (build (BIT_AND_EXPR, - TREE_TYPE (varop), newconst, - fold_convert (TREE_TYPE (varop), - mask))); - } - t = build (code, type, - (constopnum == 0) ? newconst : varop, - (constopnum == 1) ? newconst : varop); - return t; - } - } - else if (constop && TREE_CODE (varop) == POSTDECREMENT_EXPR) - { - if (POINTER_TYPE_P (TREE_TYPE (varop)) - || (! FLOAT_TYPE_P (TREE_TYPE (varop)) - && (code == EQ_EXPR || code == NE_EXPR))) - { - tree newconst - = fold (build (MINUS_EXPR, TREE_TYPE (varop), - constop, TREE_OPERAND (varop, 1))); - - /* Do not overwrite the current varop to be a predecrement, - create a new node so that we won't confuse our caller who - might create trees and throw them away, reusing the - arguments that they passed to build. This shows up in - the THEN or ELSE parts of ?: being postdecrements. */ - varop = build (PREDECREMENT_EXPR, TREE_TYPE (varop), - TREE_OPERAND (varop, 0), - TREE_OPERAND (varop, 1)); - - if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF - && DECL_BIT_FIELD(TREE_OPERAND - (TREE_OPERAND (varop, 0), 1))) - { - int size - = TREE_INT_CST_LOW (DECL_SIZE - (TREE_OPERAND - (TREE_OPERAND (varop, 0), 1))); - tree mask, unsigned_type; - unsigned int precision; - tree folded_compare; - - if (constopnum == 0) - folded_compare = fold (build (code, type, constop, - TREE_OPERAND (varop, 0))); - else - folded_compare = fold (build (code, type, - TREE_OPERAND (varop, 0), - constop)); - if (integer_zerop (folded_compare) - || integer_onep (folded_compare)) - return omit_one_operand (type, folded_compare, varop); - - unsigned_type = (*lang_hooks.types.type_for_size)(size, 1); - precision = TYPE_PRECISION (unsigned_type); - mask = build_int_2 (~0, ~0); - TREE_TYPE (mask) = TREE_TYPE (varop); - force_fit_type (mask, 0); - mask = const_binop (RSHIFT_EXPR, mask, - size_int (precision - size), 0); - newconst = fold (build (BIT_AND_EXPR, - TREE_TYPE (varop), newconst, - fold_convert (TREE_TYPE (varop), - mask))); - } + /* If VAROP is a reference to a bitfield, we must mask + the constant by the width of the field. */ + if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF + && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (varop, 0), 1))) + { + tree fielddecl = TREE_OPERAND (TREE_OPERAND (varop, 0), 1); + int size = TREE_INT_CST_LOW (DECL_SIZE (fielddecl)); + tree folded_compare, shift; + + /* First check whether the comparison would come out + always the same. If we don't do that we would + change the meaning with the masking. */ + folded_compare = fold (build2 (code, type, + TREE_OPERAND (varop, 0), + arg1)); + if (integer_zerop (folded_compare) + || integer_onep (folded_compare)) + return omit_one_operand (type, folded_compare, varop); + + shift = build_int_2 (TYPE_PRECISION (TREE_TYPE (varop)) - size, + 0); + newconst = fold (build2 (LSHIFT_EXPR, TREE_TYPE (varop), + newconst, shift)); + newconst = fold (build2 (RSHIFT_EXPR, TREE_TYPE (varop), + newconst, shift)); + } - t = build (code, type, - (constopnum == 0) ? newconst : varop, - (constopnum == 1) ? newconst : varop); - return t; - } - } - } + return fold (build2 (code, type, varop, newconst)); + } /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0. This transformation affects the cases which are handled in later @@ -7427,11 +7415,11 @@ fold (tree expr) { case GE_EXPR: arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0); - return fold (build (GT_EXPR, type, arg0, arg1)); + return fold (build2 (GT_EXPR, type, arg0, arg1)); case LT_EXPR: arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0); - return fold (build (LE_EXPR, type, arg0, arg1)); + return fold (build2 (LE_EXPR, type, arg0, arg1)); default: break; @@ -7439,7 +7427,11 @@ fold (tree expr) } /* Comparisons with the highest or lowest possible integer of - the specified size will have known values. */ + the specified size will have known values. + + This is quite similar to fold_relational_hi_lo; however, my + attempts to share the code have been nothing but trouble. + I give up for now. */ { int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1))); @@ -7454,7 +7446,7 @@ fold (tree expr) signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1; - if (TREE_UNSIGNED (TREE_TYPE (arg1))) + if (TYPE_UNSIGNED (TREE_TYPE (arg1))) { max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1; min = 0; @@ -7475,7 +7467,7 @@ fold (tree expr) integer_zero_node), arg0); case GE_EXPR: - return fold (build (EQ_EXPR, type, arg0, arg1)); + return fold (build2 (EQ_EXPR, type, arg0, arg1)); case LE_EXPR: return omit_one_operand (type, @@ -7483,7 +7475,7 @@ fold (tree expr) integer_one_node), arg0); case LT_EXPR: - return fold (build (NE_EXPR, type, arg0, arg1)); + return fold (build2 (NE_EXPR, type, arg0, arg1)); /* The GE_EXPR and LT_EXPR cases above are not normally reached because of previous transformations. */ @@ -7497,10 +7489,10 @@ fold (tree expr) { case GT_EXPR: arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0); - return fold (build (EQ_EXPR, type, arg0, arg1)); + return fold (build2 (EQ_EXPR, type, arg0, arg1)); case LE_EXPR: arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0); - return fold (build (NE_EXPR, type, arg0, arg1)); + return fold (build2 (NE_EXPR, type, arg0, arg1)); default: break; } @@ -7514,7 +7506,7 @@ fold (tree expr) integer_zero_node), arg0); case LE_EXPR: - return fold (build (EQ_EXPR, type, arg0, arg1)); + return fold (build2 (EQ_EXPR, type, arg0, arg1)); case GE_EXPR: return omit_one_operand (type, @@ -7522,7 +7514,7 @@ fold (tree expr) integer_one_node), arg0); case GT_EXPR: - return fold (build (NE_EXPR, type, arg0, arg1)); + return fold (build2 (NE_EXPR, type, arg0, arg1)); default: break; @@ -7533,17 +7525,18 @@ fold (tree expr) { case GE_EXPR: arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0); - return fold (build (NE_EXPR, type, arg0, arg1)); + return fold (build2 (NE_EXPR, type, arg0, arg1)); case LT_EXPR: arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0); - return fold (build (EQ_EXPR, type, arg0, arg1)); + return fold (build2 (EQ_EXPR, type, arg0, arg1)); default: break; } - else if (TREE_INT_CST_HIGH (arg1) == 0 + else if (!in_gimple_form + && TREE_INT_CST_HIGH (arg1) == 0 && TREE_INT_CST_LOW (arg1) == signed_max - && TREE_UNSIGNED (TREE_TYPE (arg1)) + && TYPE_UNSIGNED (TREE_TYPE (arg1)) /* signed_type does not work on pointer types. */ && INTEGRAL_TYPE_P (TREE_TYPE (arg1))) { @@ -7552,12 +7545,12 @@ fold (tree expr) if (code == LE_EXPR || code == GT_EXPR) { tree st0, st1; - st0 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg0)); - st1 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg1)); + st0 = lang_hooks.types.signed_type (TREE_TYPE (arg0)); + st1 = lang_hooks.types.signed_type (TREE_TYPE (arg1)); return fold - (build (code == LE_EXPR ? GE_EXPR: LT_EXPR, - type, fold_convert (st0, arg0), - fold_convert (st1, integer_zero_node))); + (build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR, + type, fold_convert (st0, arg0), + fold_convert (st1, integer_zero_node))); } } } @@ -7575,7 +7568,7 @@ fold (tree expr) ? MINUS_EXPR : PLUS_EXPR, arg1, TREE_OPERAND (arg0, 1), 0)) && ! TREE_CONSTANT_OVERFLOW (tem)) - return fold (build (code, type, TREE_OPERAND (arg0, 0), tem)); + return fold (build2 (code, type, TREE_OPERAND (arg0, 0), tem)); /* Similarly for a NEGATE_EXPR. */ else if ((code == EQ_EXPR || code == NE_EXPR) @@ -7584,14 +7577,14 @@ fold (tree expr) && 0 != (tem = negate_expr (arg1)) && TREE_CODE (tem) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (tem)) - return fold (build (code, type, TREE_OPERAND (arg0, 0), tem)); + return fold (build2 (code, type, TREE_OPERAND (arg0, 0), tem)); /* If we have X - Y == 0, we can convert that to X == Y and similarly for !=. Don't do this for ordered comparisons due to overflow. */ else if ((code == NE_EXPR || code == EQ_EXPR) && integer_zerop (arg1) && TREE_CODE (arg0) == MINUS_EXPR) - return fold (build (code, type, - TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1))); + return fold (build2 (code, type, + TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1))); /* If we are widening one operand of an integer comparison, see if the other operand is similarly being widened. Perhaps we @@ -7599,12 +7592,15 @@ fold (tree expr) else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE && TREE_CODE (arg0) == NOP_EXPR && (tem = get_unwidened (arg0, NULL_TREE)) != arg0 + && (code == EQ_EXPR || code == NE_EXPR + || TYPE_UNSIGNED (TREE_TYPE (arg0)) + == TYPE_UNSIGNED (TREE_TYPE (tem))) && (t1 = get_unwidened (arg1, TREE_TYPE (tem))) != 0 && (TREE_TYPE (t1) == TREE_TYPE (tem) || (TREE_CODE (t1) == INTEGER_CST && int_fits_type_p (t1, TREE_TYPE (tem))))) - return fold (build (code, type, tem, - fold_convert (TREE_TYPE (tem), t1))); + return fold (build2 (code, type, tem, + fold_convert (TREE_TYPE (tem), t1))); /* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a constant, we can simplify it. */ @@ -7625,10 +7621,11 @@ fold (tree expr) && (0 != (tem = negate_expr (arg1))) && TREE_CODE (tem) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (tem)) - return fold (build (TRUTH_ANDIF_EXPR, type, - build (GE_EXPR, type, TREE_OPERAND (arg0, 0), tem), - build (LE_EXPR, type, - TREE_OPERAND (arg0, 0), arg1))); + return fold (build2 (TRUTH_ANDIF_EXPR, type, + build2 (GE_EXPR, type, + TREE_OPERAND (arg0, 0), tem), + build2 (LE_EXPR, type, + TREE_OPERAND (arg0, 0), arg1))); /* If this is an EQ or NE comparison with zero and ARG0 is (1 << foo) & bar, convert it to (bar >> foo) & 1. Both require @@ -7638,30 +7635,28 @@ fold (tree expr) if (integer_zerop (arg1) && (code == EQ_EXPR || code == NE_EXPR) && TREE_CODE (arg0) == BIT_AND_EXPR) { - if (TREE_CODE (TREE_OPERAND (arg0, 0)) == LSHIFT_EXPR - && integer_onep (TREE_OPERAND (TREE_OPERAND (arg0, 0), 0))) + tree arg00 = TREE_OPERAND (arg0, 0); + tree arg01 = TREE_OPERAND (arg0, 1); + if (TREE_CODE (arg00) == LSHIFT_EXPR + && integer_onep (TREE_OPERAND (arg00, 0))) return - fold (build (code, type, - build (BIT_AND_EXPR, TREE_TYPE (arg0), - build (RSHIFT_EXPR, - TREE_TYPE (TREE_OPERAND (arg0, 0)), - TREE_OPERAND (arg0, 1), - TREE_OPERAND (TREE_OPERAND (arg0, 0), 1)), - fold_convert (TREE_TYPE (arg0), - integer_one_node)), - arg1)); + fold (build2 (code, type, + build2 (BIT_AND_EXPR, TREE_TYPE (arg0), + build2 (RSHIFT_EXPR, TREE_TYPE (arg00), + arg01, TREE_OPERAND (arg00, 1)), + fold_convert (TREE_TYPE (arg0), + integer_one_node)), + arg1)); else if (TREE_CODE (TREE_OPERAND (arg0, 1)) == LSHIFT_EXPR && integer_onep (TREE_OPERAND (TREE_OPERAND (arg0, 1), 0))) return - fold (build (code, type, - build (BIT_AND_EXPR, TREE_TYPE (arg0), - build (RSHIFT_EXPR, - TREE_TYPE (TREE_OPERAND (arg0, 1)), - TREE_OPERAND (arg0, 0), - TREE_OPERAND (TREE_OPERAND (arg0, 1), 1)), - fold_convert (TREE_TYPE (arg0), - integer_one_node)), - arg1)); + fold (build2 (code, type, + build2 (BIT_AND_EXPR, TREE_TYPE (arg0), + build2 (RSHIFT_EXPR, TREE_TYPE (arg01), + arg00, TREE_OPERAND (arg01, 1)), + fold_convert (TREE_TYPE (arg0), + integer_one_node)), + arg1)); } /* If this is an NE or EQ comparison of zero against the result of a @@ -7669,21 +7664,21 @@ fold (tree expr) the MOD operation unsigned since it is simpler and equivalent. */ if ((code == NE_EXPR || code == EQ_EXPR) && integer_zerop (arg1) - && ! TREE_UNSIGNED (TREE_TYPE (arg0)) + && !TYPE_UNSIGNED (TREE_TYPE (arg0)) && (TREE_CODE (arg0) == TRUNC_MOD_EXPR || TREE_CODE (arg0) == CEIL_MOD_EXPR || TREE_CODE (arg0) == FLOOR_MOD_EXPR || TREE_CODE (arg0) == ROUND_MOD_EXPR) && integer_pow2p (TREE_OPERAND (arg0, 1))) { - tree newtype = (*lang_hooks.types.unsigned_type) (TREE_TYPE (arg0)); - tree newmod = build (TREE_CODE (arg0), newtype, - fold_convert (newtype, - TREE_OPERAND (arg0, 0)), - fold_convert (newtype, - TREE_OPERAND (arg0, 1))); - - return build (code, type, newmod, fold_convert (newtype, arg1)); + tree newtype = lang_hooks.types.unsigned_type (TREE_TYPE (arg0)); + tree newmod = build2 (TREE_CODE (arg0), newtype, + fold_convert (newtype, + TREE_OPERAND (arg0, 0)), + fold_convert (newtype, + TREE_OPERAND (arg0, 1))); + + return build2 (code, type, newmod, fold_convert (newtype, arg1)); } /* If this is an NE comparison of zero with an AND of one, remove the @@ -7699,8 +7694,8 @@ fold (tree expr) && TREE_CODE (arg0) == BIT_AND_EXPR && integer_pow2p (TREE_OPERAND (arg0, 1)) && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0)) - return fold (build (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type, - arg0, integer_zero_node)); + return fold (build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type, + arg0, integer_zero_node)); /* If we have (A & C) != 0 or (A & C) == 0 and C is a power of 2, then fold the expression into shifts and logical operations. */ @@ -7716,10 +7711,10 @@ fold (tree expr) && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST) { tree dandnotc - = fold (build (BIT_AND_EXPR, TREE_TYPE (arg0), - arg1, build1 (BIT_NOT_EXPR, - TREE_TYPE (TREE_OPERAND (arg0, 1)), - TREE_OPERAND (arg0, 1)))); + = fold (build2 (BIT_AND_EXPR, TREE_TYPE (arg0), + arg1, build1 (BIT_NOT_EXPR, + TREE_TYPE (TREE_OPERAND (arg0, 1)), + TREE_OPERAND (arg0, 1)))); tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node; if (integer_nonzerop (dandnotc)) return omit_one_operand (type, rslt, arg0); @@ -7733,9 +7728,9 @@ fold (tree expr) && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST) { tree candnotd - = fold (build (BIT_AND_EXPR, TREE_TYPE (arg0), - TREE_OPERAND (arg0, 1), - build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1))); + = fold (build2 (BIT_AND_EXPR, TREE_TYPE (arg0), + TREE_OPERAND (arg0, 1), + build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1))); tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node; if (integer_nonzerop (candnotd)) return omit_one_operand (type, rslt, arg0); @@ -7744,27 +7739,27 @@ fold (tree expr) /* If X is unsigned, convert X < (1 << Y) into X >> Y == 0 and similarly for >= into !=. */ if ((code == LT_EXPR || code == GE_EXPR) - && TREE_UNSIGNED (TREE_TYPE (arg0)) + && TYPE_UNSIGNED (TREE_TYPE (arg0)) && TREE_CODE (arg1) == LSHIFT_EXPR && integer_onep (TREE_OPERAND (arg1, 0))) - return build (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type, - build (RSHIFT_EXPR, TREE_TYPE (arg0), arg0, - TREE_OPERAND (arg1, 1)), - fold_convert (TREE_TYPE (arg0), integer_zero_node)); + return build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type, + build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0, + TREE_OPERAND (arg1, 1)), + fold_convert (TREE_TYPE (arg0), integer_zero_node)); else if ((code == LT_EXPR || code == GE_EXPR) - && TREE_UNSIGNED (TREE_TYPE (arg0)) + && TYPE_UNSIGNED (TREE_TYPE (arg0)) && (TREE_CODE (arg1) == NOP_EXPR || TREE_CODE (arg1) == CONVERT_EXPR) && TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR && integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0))) return - build (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type, - fold_convert (TREE_TYPE (arg0), - build (RSHIFT_EXPR, TREE_TYPE (arg0), arg0, - TREE_OPERAND (TREE_OPERAND (arg1, 0), - 1))), - fold_convert (TREE_TYPE (arg0), integer_zero_node)); + build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type, + fold_convert (TREE_TYPE (arg0), + build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0, + TREE_OPERAND (TREE_OPERAND (arg1, 0), + 1))), + fold_convert (TREE_TYPE (arg0), integer_zero_node)); /* Simplify comparison of something with itself. (For IEEE floating-point, we can only do some of these simplifications.) */ @@ -7783,7 +7778,7 @@ fold (tree expr) if (! FLOAT_TYPE_P (TREE_TYPE (arg0)) || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))) return constant_boolean_node (1, type); - return fold (build (EQ_EXPR, type, arg0, arg1)); + return fold (build2 (EQ_EXPR, type, arg0, arg1)); case NE_EXPR: /* For NE, we can only do this simplification if integer @@ -7837,17 +7832,20 @@ fold (tree expr) was the same as ARG1. */ tree high_result - = fold (build (code, type, - eval_subst (arg0, cval1, maxval, cval2, minval), - arg1)); + = fold (build2 (code, type, + eval_subst (arg0, cval1, maxval, + cval2, minval), + arg1)); tree equal_result - = fold (build (code, type, - eval_subst (arg0, cval1, maxval, cval2, maxval), - arg1)); + = fold (build2 (code, type, + eval_subst (arg0, cval1, maxval, + cval2, maxval), + arg1)); tree low_result - = fold (build (code, type, - eval_subst (arg0, cval1, minval, cval2, maxval), - arg1)); + = fold (build2 (code, type, + eval_subst (arg0, cval1, minval, + cval2, maxval), + arg1)); /* All three of these results should be 0 or 1. Confirm they are. Then use those values to select the proper code @@ -7892,18 +7890,18 @@ fold (tree expr) return omit_one_operand (type, integer_one_node, arg0); } - t = build (code, type, cval1, cval2); + tem = build2 (code, type, cval1, cval2); if (save_p) - return save_expr (t); + return save_expr (tem); else - return fold (t); + return fold (tem); } } } /* If this is a comparison of a field, we may be able to simplify it. */ if (((TREE_CODE (arg0) == COMPONENT_REF - && (*lang_hooks.can_use_bit_fields_p) ()) + && lang_hooks.can_use_bit_fields_p ()) || TREE_CODE (arg0) == BIT_FIELD_REF) && (code == EQ_EXPR || code == NE_EXPR) /* Handle the constant case even without -O @@ -7936,11 +7934,11 @@ fold (tree expr) real1 = fold (build1 (REALPART_EXPR, subtype, arg1)); imag1 = fold (build1 (IMAGPART_EXPR, subtype, arg1)); - return fold (build ((code == EQ_EXPR ? TRUTH_ANDIF_EXPR - : TRUTH_ORIF_EXPR), - type, - fold (build (code, type, real0, real1)), - fold (build (code, type, imag0, imag1)))); + return fold (build2 ((code == EQ_EXPR ? TRUTH_ANDIF_EXPR + : TRUTH_ORIF_EXPR), + type, + fold (build2 (code, type, real0, real1)), + fold (build2 (code, type, imag0, imag1)))); } /* Optimize comparisons of strlen vs zero to a compare of the @@ -7963,98 +7961,29 @@ fold (tree expr) && (arglist = TREE_OPERAND (arg0, 1)) && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE && ! TREE_CHAIN (arglist)) - return fold (build (code, type, - build1 (INDIRECT_REF, char_type_node, - TREE_VALUE(arglist)), - integer_zero_node)); + return fold (build2 (code, type, + build1 (INDIRECT_REF, char_type_node, + TREE_VALUE(arglist)), + integer_zero_node)); } - /* From here on, the only cases we handle are when the result is - known to be a constant. - - To compute GT, swap the arguments and do LT. - To compute GE, do LT and invert the result. - To compute LE, swap the arguments, do LT and invert the result. - To compute NE, do EQ and invert the result. - - Therefore, the code below must handle only EQ and LT. */ - - if (code == LE_EXPR || code == GT_EXPR) - { - tem = arg0, arg0 = arg1, arg1 = tem; - code = swap_tree_comparison (code); - } - - /* Note that it is safe to invert for real values here because we - will check below in the one case that it matters. */ - - t1 = NULL_TREE; - invert = 0; - if (code == NE_EXPR || code == GE_EXPR) - { - invert = 1; - code = invert_tree_comparison (code); - } - - /* Compute a result for LT or EQ if args permit; - otherwise return T. */ - if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) + /* We can fold X/C1 op C2 where C1 and C2 are integer constants + into a single range test. */ + if (TREE_CODE (arg0) == TRUNC_DIV_EXPR + && TREE_CODE (arg1) == INTEGER_CST + && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST + && !integer_zerop (TREE_OPERAND (arg0, 1)) + && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1)) + && !TREE_OVERFLOW (arg1)) { - if (code == EQ_EXPR) - t1 = build_int_2 (tree_int_cst_equal (arg0, arg1), 0); - else - t1 = build_int_2 ((TREE_UNSIGNED (TREE_TYPE (arg0)) - ? INT_CST_LT_UNSIGNED (arg0, arg1) - : INT_CST_LT (arg0, arg1)), - 0); - } - -#if 0 /* This is no longer useful, but breaks some real code. */ - /* Assume a nonexplicit constant cannot equal an explicit one, - since such code would be undefined anyway. - Exception: on sysvr4, using #pragma weak, - a label can come out as 0. */ - else if (TREE_CODE (arg1) == INTEGER_CST - && !integer_zerop (arg1) - && TREE_CONSTANT (arg0) - && TREE_CODE (arg0) == ADDR_EXPR - && code == EQ_EXPR) - t1 = build_int_2 (0, 0); -#endif - /* Two real constants can be compared explicitly. */ - else if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST) - { - /* If either operand is a NaN, the result is false with two - exceptions: First, an NE_EXPR is true on NaNs, but that case - is already handled correctly since we will be inverting the - result for NE_EXPR. Second, if we had inverted a LE_EXPR - or a GE_EXPR into a LT_EXPR, we must return true so that it - will be inverted into false. */ - - if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg0)) - || REAL_VALUE_ISNAN (TREE_REAL_CST (arg1))) - t1 = build_int_2 (invert && code == LT_EXPR, 0); - - else if (code == EQ_EXPR) - t1 = build_int_2 (REAL_VALUES_EQUAL (TREE_REAL_CST (arg0), - TREE_REAL_CST (arg1)), - 0); - else - t1 = build_int_2 (REAL_VALUES_LESS (TREE_REAL_CST (arg0), - TREE_REAL_CST (arg1)), - 0); + t1 = fold_div_compare (code, type, arg0, arg1); + if (t1 != NULL_TREE) + return t1; } - if (t1 == NULL_TREE) - return t; - - if (invert) - TREE_INT_CST_LOW (t1) ^= 1; - - TREE_TYPE (t1) = type; - if (TREE_CODE (type) == BOOLEAN_TYPE) - return (*lang_hooks.truthvalue_conversion) (t1); - return t1; + /* Both ARG0 and ARG1 are known to be constants at this point. */ + t1 = fold_relational_const (code, type, arg0, arg1); + return (t1 == NULL_TREE ? t : t1); case COND_EXPR: /* Pedantic ANSI C says that a conditional expression is never an lvalue, @@ -8066,11 +7995,11 @@ fold (tree expr) 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))) + || VOID_TYPE_P (type)) return pedantic_non_lvalue (tem); return t; } - if (operand_equal_p (arg1, TREE_OPERAND (expr, 2), 0)) + if (operand_equal_p (arg1, TREE_OPERAND (t, 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 @@ -8122,15 +8051,15 @@ fold (tree expr) return pedantic_non_lvalue (fold_convert (type, arg1)); case GE_EXPR: case GT_EXPR: - if (TREE_UNSIGNED (TREE_TYPE (arg1))) - arg1 = fold_convert ((*lang_hooks.types.signed_type) + if (TYPE_UNSIGNED (TREE_TYPE (arg1))) + arg1 = fold_convert (lang_hooks.types.signed_type (TREE_TYPE (arg1)), arg1); arg1 = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1)); return pedantic_non_lvalue (fold_convert (type, arg1)); case LE_EXPR: case LT_EXPR: - if (TREE_UNSIGNED (TREE_TYPE (arg1))) - arg1 = fold_convert ((lang_hooks.types.signed_type) + if (TYPE_UNSIGNED (TREE_TYPE (arg1))) + arg1 = fold_convert (lang_hooks.types.signed_type (TREE_TYPE (arg1)), arg1); arg1 = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1)); arg1 = negate_expr (fold_convert (type, arg1)); @@ -8207,21 +8136,21 @@ fold (tree expr) corresponding COND_EXPR. */ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1)))) return pedantic_non_lvalue (fold_convert - (type, fold (build (MIN_EXPR, comp_type, - (comp_code == LE_EXPR - ? comp_op0 : comp_op1), - (comp_code == LE_EXPR - ? comp_op1 : comp_op0))))); + (type, fold (build2 (MIN_EXPR, comp_type, + (comp_code == LE_EXPR + ? comp_op0 : comp_op1), + (comp_code == LE_EXPR + ? comp_op1 : comp_op0))))); break; case GE_EXPR: case GT_EXPR: if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1)))) return pedantic_non_lvalue (fold_convert - (type, fold (build (MAX_EXPR, comp_type, - (comp_code == GE_EXPR - ? comp_op0 : comp_op1), - (comp_code == GE_EXPR - ? comp_op1 : comp_op0))))); + (type, fold (build2 (MAX_EXPR, comp_type, + (comp_code == GE_EXPR + ? comp_op0 : comp_op1), + (comp_code == GE_EXPR + ? comp_op1 : comp_op0))))); break; default: abort (); @@ -8242,47 +8171,55 @@ fold (tree expr) case EQ_EXPR: /* We can replace A with C1 in this case. */ arg1 = fold_convert (type, TREE_OPERAND (arg0, 1)); - return fold (build (code, type, TREE_OPERAND (t, 0), arg1, - TREE_OPERAND (t, 2))); + return fold (build3 (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 (! operand_equal_p (arg2, TYPE_MAX_VALUE (type), 1) + if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type), + OEP_ONLY_CONST) && operand_equal_p (TREE_OPERAND (arg0, 1), const_binop (PLUS_EXPR, arg2, - integer_one_node, 0), 1)) + integer_one_node, 0), + OEP_ONLY_CONST)) return pedantic_non_lvalue - (fold (build (MIN_EXPR, type, arg1, arg2))); + (fold (build2 (MIN_EXPR, type, arg1, arg2))); break; case LE_EXPR: /* If C1 is C2 - 1, this is min(A, C2). */ - if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type), 1) + if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type), + OEP_ONLY_CONST) && operand_equal_p (TREE_OPERAND (arg0, 1), const_binop (MINUS_EXPR, arg2, - integer_one_node, 0), 1)) + integer_one_node, 0), + OEP_ONLY_CONST)) return pedantic_non_lvalue - (fold (build (MIN_EXPR, type, arg1, arg2))); + (fold (build2 (MIN_EXPR, type, arg1, arg2))); break; case GT_EXPR: /* If C1 is C2 - 1, this is max(A, C2). */ - if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type), 1) + if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type), + OEP_ONLY_CONST) && operand_equal_p (TREE_OPERAND (arg0, 1), const_binop (MINUS_EXPR, arg2, - integer_one_node, 0), 1)) + integer_one_node, 0), + OEP_ONLY_CONST)) return pedantic_non_lvalue - (fold (build (MAX_EXPR, type, arg1, arg2))); + (fold (build2 (MAX_EXPR, type, arg1, arg2))); break; case GE_EXPR: /* If C1 is C2 + 1, this is max(A, C2). */ - if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type), 1) + if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type), + OEP_ONLY_CONST) && operand_equal_p (TREE_OPERAND (arg0, 1), const_binop (PLUS_EXPR, arg2, - integer_one_node, 0), 1)) + integer_one_node, 0), + OEP_ONLY_CONST)) return pedantic_non_lvalue - (fold (build (MAX_EXPR, type, arg1, arg2))); + (fold (build2 (MAX_EXPR, type, arg1, arg2))); break; case NE_EXPR: break; @@ -8302,8 +8239,8 @@ fold (tree expr) tem = invert_truthvalue (arg0); if (TREE_CODE (tem) != TRUTH_NOT_EXPR) - return fold (build (code, type, tem, - TREE_OPERAND (t, 2), TREE_OPERAND (t, 1))); + return fold (build3 (code, type, tem, + TREE_OPERAND (t, 2), TREE_OPERAND (t, 1))); } /* Convert A ? 1 : 0 to simply A. */ @@ -8333,7 +8270,7 @@ fold (tree expr) && integer_pow2p (arg1) && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1), - arg1, 1)) + arg1, OEP_ONLY_CONST)) return pedantic_non_lvalue (fold_convert (type, TREE_OPERAND (arg0, 0))); @@ -8341,8 +8278,8 @@ fold (tree expr) if (integer_zerop (TREE_OPERAND (t, 2)) && truth_value_p (TREE_CODE (arg0)) && truth_value_p (TREE_CODE (arg1))) - return pedantic_non_lvalue (fold (build (TRUTH_ANDIF_EXPR, type, - arg0, arg1))); + return pedantic_non_lvalue (fold (build2 (TRUTH_ANDIF_EXPR, type, + arg0, arg1))); /* Convert A ? B : 1 into !A || B if A and B are truth values. */ if (integer_onep (TREE_OPERAND (t, 2)) @@ -8352,8 +8289,8 @@ fold (tree expr) /* Only perform transformation if ARG0 is easily inverted. */ tem = invert_truthvalue (arg0); if (TREE_CODE (tem) != TRUTH_NOT_EXPR) - return pedantic_non_lvalue (fold (build (TRUTH_ORIF_EXPR, type, - tem, arg1))); + return pedantic_non_lvalue (fold (build2 (TRUTH_ORIF_EXPR, type, + tem, arg1))); } return t; @@ -8382,11 +8319,11 @@ fold (tree expr) else if (TREE_CODE (arg0) == COMPLEX_CST) return TREE_REALPART (arg0); else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) - return fold (build (TREE_CODE (arg0), type, - fold (build1 (REALPART_EXPR, type, - TREE_OPERAND (arg0, 0))), - fold (build1 (REALPART_EXPR, - type, TREE_OPERAND (arg0, 1))))); + return fold (build2 (TREE_CODE (arg0), type, + fold (build1 (REALPART_EXPR, type, + TREE_OPERAND (arg0, 0))), + fold (build1 (REALPART_EXPR, type, + TREE_OPERAND (arg0, 1))))); return t; case IMAGPART_EXPR: @@ -8398,11 +8335,11 @@ fold (tree expr) else if (TREE_CODE (arg0) == COMPLEX_CST) return TREE_IMAGPART (arg0); else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) - return fold (build (TREE_CODE (arg0), type, - fold (build1 (IMAGPART_EXPR, type, - TREE_OPERAND (arg0, 0))), - fold (build1 (IMAGPART_EXPR, type, - TREE_OPERAND (arg0, 1))))); + return fold (build2 (TREE_CODE (arg0), type, + fold (build1 (IMAGPART_EXPR, type, + TREE_OPERAND (arg0, 0))), + fold (build1 (IMAGPART_EXPR, type, + TREE_OPERAND (arg0, 1))))); return t; /* Pull arithmetic ops out of the CLEANUP_POINT_EXPR where @@ -8432,15 +8369,15 @@ fold (tree expr) if (TREE_CONSTANT (arg00) || ((code0 == TRUTH_ANDIF_EXPR || code0 == TRUTH_ORIF_EXPR) && ! has_cleanups (arg00))) - return fold (build (code0, type, arg00, - fold (build1 (CLEANUP_POINT_EXPR, - TREE_TYPE (arg01), arg01)))); + return fold (build2 (code0, type, arg00, + fold (build1 (CLEANUP_POINT_EXPR, + TREE_TYPE (arg01), arg01)))); if (TREE_CONSTANT (arg01)) - return fold (build (code0, type, - fold (build1 (CLEANUP_POINT_EXPR, - TREE_TYPE (arg00), arg00)), - arg01)); + return fold (build2 (code0, type, + fold (build1 (CLEANUP_POINT_EXPR, + TREE_TYPE (arg00), arg00)), + arg01)); } return t; @@ -8448,12 +8385,12 @@ fold (tree expr) 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)) + if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR + && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0)) == FUNCTION_DECL) - && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (expr, 0), 0))) + && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0))) { - tree tmp = fold_builtin (expr); + tree tmp = fold_builtin (t); if (tmp) return tmp; } @@ -8776,7 +8713,7 @@ multiple_of_p (tree type, tree top, tree bottom) case INTEGER_CST: if (TREE_CODE (bottom) != INTEGER_CST - || (TREE_UNSIGNED (type) + || (TYPE_UNSIGNED (type) && (tree_int_cst_sgn (top) < 0 || tree_int_cst_sgn (bottom) < 0))) return 0; @@ -8817,8 +8754,8 @@ tree_expr_nonnegative_p (tree t) { tree inner1 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0)); tree inner2 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0)); - if (TREE_CODE (inner1) == INTEGER_TYPE && TREE_UNSIGNED (inner1) - && TREE_CODE (inner2) == INTEGER_TYPE && TREE_UNSIGNED (inner2)) + if (TREE_CODE (inner1) == INTEGER_TYPE && TYPE_UNSIGNED (inner1) + && TREE_CODE (inner2) == INTEGER_TYPE && TYPE_UNSIGNED (inner2)) { unsigned int prec = MAX (TYPE_PRECISION (inner1), TYPE_PRECISION (inner2)) + 1; @@ -8845,8 +8782,8 @@ tree_expr_nonnegative_p (tree t) { tree inner1 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0)); tree inner2 = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0)); - if (TREE_CODE (inner1) == INTEGER_TYPE && TREE_UNSIGNED (inner1) - && TREE_CODE (inner2) == INTEGER_TYPE && TREE_UNSIGNED (inner2)) + if (TREE_CODE (inner1) == INTEGER_TYPE && TYPE_UNSIGNED (inner1) + && TREE_CODE (inner2) == INTEGER_TYPE && TYPE_UNSIGNED (inner2)) return TYPE_PRECISION (inner1) + TYPE_PRECISION (inner2) < TYPE_PRECISION (TREE_TYPE (t)); } @@ -8869,6 +8806,14 @@ tree_expr_nonnegative_p (tree t) return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)) && tree_expr_nonnegative_p (TREE_OPERAND (t, 1)); + case BIT_AND_EXPR: + return tree_expr_nonnegative_p (TREE_OPERAND (t, 1)) + || tree_expr_nonnegative_p (TREE_OPERAND (t, 0)); + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)) + && tree_expr_nonnegative_p (TREE_OPERAND (t, 1)); + case NOP_EXPR: { tree inner_type = TREE_TYPE (TREE_OPERAND (t, 0)); @@ -8880,7 +8825,7 @@ tree_expr_nonnegative_p (tree t) return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)); if (TREE_CODE (inner_type) == INTEGER_TYPE) { - if (TREE_UNSIGNED (inner_type)) + if (TYPE_UNSIGNED (inner_type)) return 1; return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)); } @@ -8891,7 +8836,7 @@ tree_expr_nonnegative_p (tree t) return tree_expr_nonnegative_p (TREE_OPERAND (t,0)); if (TREE_CODE (inner_type) == INTEGER_TYPE) return TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type) - && TREE_UNSIGNED (inner_type); + && TYPE_UNSIGNED (inner_type); } } break; @@ -8929,65 +8874,75 @@ tree_expr_nonnegative_p (tree t) && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD) switch (DECL_FUNCTION_CODE (fndecl)) { - case BUILT_IN_CABS: - case BUILT_IN_CABSL: - case BUILT_IN_CABSF: - 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: +#define CASE_BUILTIN_F(BUILT_IN_FN) \ + case BUILT_IN_FN: case BUILT_IN_FN##F: case BUILT_IN_FN##L: +#define CASE_BUILTIN_I(BUILT_IN_FN) \ + case BUILT_IN_FN: case BUILT_IN_FN##L: case BUILT_IN_FN##LL: + + CASE_BUILTIN_F (BUILT_IN_ACOS) + CASE_BUILTIN_F (BUILT_IN_ACOSH) + CASE_BUILTIN_F (BUILT_IN_CABS) + CASE_BUILTIN_F (BUILT_IN_COSH) + CASE_BUILTIN_F (BUILT_IN_ERFC) + CASE_BUILTIN_F (BUILT_IN_EXP) + CASE_BUILTIN_F (BUILT_IN_EXP10) + CASE_BUILTIN_F (BUILT_IN_EXP2) + CASE_BUILTIN_F (BUILT_IN_FABS) + CASE_BUILTIN_F (BUILT_IN_FDIM) + CASE_BUILTIN_F (BUILT_IN_FREXP) + CASE_BUILTIN_F (BUILT_IN_HYPOT) + CASE_BUILTIN_F (BUILT_IN_POW10) + CASE_BUILTIN_F (BUILT_IN_SQRT) + CASE_BUILTIN_I (BUILT_IN_FFS) + CASE_BUILTIN_I (BUILT_IN_PARITY) + CASE_BUILTIN_I (BUILT_IN_POPCOUNT) + /* Always true. */ return 1; - case BUILT_IN_ATAN: - case BUILT_IN_ATANF: - case BUILT_IN_ATANL: - case BUILT_IN_CEIL: - case BUILT_IN_CEILF: - case BUILT_IN_CEILL: - case BUILT_IN_FLOOR: - case BUILT_IN_FLOORF: - case BUILT_IN_FLOORL: - case BUILT_IN_NEARBYINT: - case BUILT_IN_NEARBYINTF: - case BUILT_IN_NEARBYINTL: - case BUILT_IN_ROUND: - case BUILT_IN_ROUNDF: - case BUILT_IN_ROUNDL: - case BUILT_IN_TRUNC: - case BUILT_IN_TRUNCF: - case BUILT_IN_TRUNCL: + CASE_BUILTIN_F (BUILT_IN_ASINH) + CASE_BUILTIN_F (BUILT_IN_ATAN) + CASE_BUILTIN_F (BUILT_IN_ATANH) + CASE_BUILTIN_F (BUILT_IN_CBRT) + CASE_BUILTIN_F (BUILT_IN_CEIL) + CASE_BUILTIN_F (BUILT_IN_ERF) + CASE_BUILTIN_F (BUILT_IN_EXPM1) + CASE_BUILTIN_F (BUILT_IN_FLOOR) + CASE_BUILTIN_F (BUILT_IN_FMOD) + CASE_BUILTIN_F (BUILT_IN_LDEXP) + CASE_BUILTIN_F (BUILT_IN_LLRINT) + CASE_BUILTIN_F (BUILT_IN_LLROUND) + CASE_BUILTIN_F (BUILT_IN_LRINT) + CASE_BUILTIN_F (BUILT_IN_LROUND) + CASE_BUILTIN_F (BUILT_IN_MODF) + CASE_BUILTIN_F (BUILT_IN_NEARBYINT) + CASE_BUILTIN_F (BUILT_IN_POW) + CASE_BUILTIN_F (BUILT_IN_RINT) + CASE_BUILTIN_F (BUILT_IN_ROUND) + CASE_BUILTIN_F (BUILT_IN_SIGNBIT) + CASE_BUILTIN_F (BUILT_IN_SINH) + CASE_BUILTIN_F (BUILT_IN_TANH) + CASE_BUILTIN_F (BUILT_IN_TRUNC) + /* True if the 1st argument is nonnegative. */ return tree_expr_nonnegative_p (TREE_VALUE (arglist)); - case BUILT_IN_POW: - case BUILT_IN_POWF: - case BUILT_IN_POWL: - return tree_expr_nonnegative_p (TREE_VALUE (arglist)); + CASE_BUILTIN_F(BUILT_IN_FMAX) + /* True if the 1st OR 2nd arguments are nonnegative. */ + return tree_expr_nonnegative_p (TREE_VALUE (arglist)) + || tree_expr_nonnegative_p (TREE_VALUE (TREE_CHAIN (arglist))); + + CASE_BUILTIN_F(BUILT_IN_FMIN) + /* True if the 1st AND 2nd arguments are nonnegative. */ + return tree_expr_nonnegative_p (TREE_VALUE (arglist)) + && tree_expr_nonnegative_p (TREE_VALUE (TREE_CHAIN (arglist))); + + CASE_BUILTIN_F(BUILT_IN_COPYSIGN) + /* True if the 2nd argument is nonnegative. */ + return tree_expr_nonnegative_p (TREE_VALUE (TREE_CHAIN (arglist))); default: break; +#undef CASE_BUILTIN_F +#undef CASE_BUILTIN_I } } @@ -9003,6 +8958,110 @@ tree_expr_nonnegative_p (tree t) return 0; } +/* Return true when T is an address and is known to be nonzero. + For floating point we further ensure that T is not denormal. + Similar logic is present in nonzero_address in rtlanal.h */ + +static bool +tree_expr_nonzero_p (tree t) +{ + tree type = TREE_TYPE (t); + + /* Doing something useful for floating point would need more work. */ + if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type)) + return false; + + switch (TREE_CODE (t)) + { + case ABS_EXPR: + if (!TYPE_UNSIGNED (type) && !flag_wrapv) + return tree_expr_nonzero_p (TREE_OPERAND (t, 0)); + + case INTEGER_CST: + return !integer_zerop (t); + + case PLUS_EXPR: + if (!TYPE_UNSIGNED (type) && !flag_wrapv) + { + /* With the presence of negative values it is hard + to say something. */ + if (!tree_expr_nonnegative_p (TREE_OPERAND (t, 0)) + || !tree_expr_nonnegative_p (TREE_OPERAND (t, 1))) + return false; + /* One of operands must be positive and the other non-negative. */ + return (tree_expr_nonzero_p (TREE_OPERAND (t, 0)) + || tree_expr_nonzero_p (TREE_OPERAND (t, 1))); + } + break; + + case MULT_EXPR: + if (!TYPE_UNSIGNED (type) && !flag_wrapv) + { + return (tree_expr_nonzero_p (TREE_OPERAND (t, 0)) + && tree_expr_nonzero_p (TREE_OPERAND (t, 1))); + } + break; + + case NOP_EXPR: + { + tree inner_type = TREE_TYPE (TREE_OPERAND (t, 0)); + tree outer_type = TREE_TYPE (t); + + return (TYPE_PRECISION (inner_type) >= TYPE_PRECISION (outer_type) + && tree_expr_nonzero_p (TREE_OPERAND (t, 0))); + } + break; + + case ADDR_EXPR: + /* Weak declarations may link to NULL. */ + if (DECL_P (TREE_OPERAND (t, 0))) + return !DECL_WEAK (TREE_OPERAND (t, 0)); + /* Constants and all other cases are never weak. */ + return true; + + case COND_EXPR: + return (tree_expr_nonzero_p (TREE_OPERAND (t, 1)) + && tree_expr_nonzero_p (TREE_OPERAND (t, 2))); + + case MIN_EXPR: + return (tree_expr_nonzero_p (TREE_OPERAND (t, 0)) + && tree_expr_nonzero_p (TREE_OPERAND (t, 1))); + + case MAX_EXPR: + if (tree_expr_nonzero_p (TREE_OPERAND (t, 0))) + { + /* When both operands are nonzero, then MAX must be too. */ + if (tree_expr_nonzero_p (TREE_OPERAND (t, 1))) + return true; + + /* MAX where operand 0 is positive is positive. */ + return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)); + } + /* MAX where operand 1 is positive is positive. */ + else if (tree_expr_nonzero_p (TREE_OPERAND (t, 1)) + && tree_expr_nonnegative_p (TREE_OPERAND (t, 1))) + return true; + break; + + case COMPOUND_EXPR: + case MODIFY_EXPR: + case BIND_EXPR: + return tree_expr_nonzero_p (TREE_OPERAND (t, 1)); + + case SAVE_EXPR: + case NON_LVALUE_EXPR: + return tree_expr_nonzero_p (TREE_OPERAND (t, 0)); + + case BIT_IOR_EXPR: + return tree_expr_nonzero_p (TREE_OPERAND (t, 1)) + || tree_expr_nonzero_p (TREE_OPERAND (t, 0)); + + default: + break; + } + return false; +} + /* Return true if `r' is known to be non-negative. Only handles constants at the moment. */ @@ -9046,4 +9105,776 @@ rtl_expr_nonnegative_p (rtx r) } } + +/* See if we are applying CODE, a relational to the highest or lowest + possible integer of TYPE. If so, then the result is a compile + time constant. */ + +static tree +fold_relational_hi_lo (enum tree_code *code_p, const tree type, tree *op0_p, + tree *op1_p) +{ + tree op0 = *op0_p; + tree op1 = *op1_p; + enum tree_code code = *code_p; + int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (op1))); + + if (TREE_CODE (op1) == INTEGER_CST + && ! TREE_CONSTANT_OVERFLOW (op1) + && width <= HOST_BITS_PER_WIDE_INT + && (INTEGRAL_TYPE_P (TREE_TYPE (op1)) + || POINTER_TYPE_P (TREE_TYPE (op1)))) + { + unsigned HOST_WIDE_INT signed_max; + unsigned HOST_WIDE_INT max, min; + + signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1; + + if (TYPE_UNSIGNED (TREE_TYPE (op1))) + { + max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1; + min = 0; + } + else + { + max = signed_max; + min = ((unsigned HOST_WIDE_INT) -1 << (width - 1)); + } + + if (TREE_INT_CST_HIGH (op1) == 0 + && TREE_INT_CST_LOW (op1) == max) + switch (code) + { + case GT_EXPR: + return omit_one_operand (type, + fold_convert (type, integer_zero_node), + op0); + case GE_EXPR: + *code_p = EQ_EXPR; + break; + case LE_EXPR: + return omit_one_operand (type, + fold_convert (type, integer_one_node), + op0); + case LT_EXPR: + *code_p = NE_EXPR; + break; + + /* The GE_EXPR and LT_EXPR cases above are not normally + reached because of previous transformations. */ + + default: + break; + } + else if (TREE_INT_CST_HIGH (op1) == 0 + && TREE_INT_CST_LOW (op1) == max - 1) + switch (code) + { + case GT_EXPR: + *code_p = EQ_EXPR; + *op1_p = const_binop (PLUS_EXPR, op1, integer_one_node, 0); + break; + case LE_EXPR: + *code_p = NE_EXPR; + *op1_p = const_binop (PLUS_EXPR, op1, integer_one_node, 0); + break; + default: + break; + } + else if (TREE_INT_CST_HIGH (op1) == (min ? -1 : 0) + && TREE_INT_CST_LOW (op1) == min) + switch (code) + { + case LT_EXPR: + return omit_one_operand (type, + fold_convert (type, integer_zero_node), + op0); + case LE_EXPR: + *code_p = EQ_EXPR; + break; + + case GE_EXPR: + return omit_one_operand (type, + fold_convert (type, integer_one_node), + op0); + case GT_EXPR: + *code_p = NE_EXPR; + break; + + default: + break; + } + else if (TREE_INT_CST_HIGH (op1) == (min ? -1 : 0) + && TREE_INT_CST_LOW (op1) == min + 1) + switch (code) + { + case GE_EXPR: + *code_p = NE_EXPR; + *op1_p = const_binop (MINUS_EXPR, op1, integer_one_node, 0); + break; + case LT_EXPR: + *code_p = EQ_EXPR; + *op1_p = const_binop (MINUS_EXPR, op1, integer_one_node, 0); + break; + default: + break; + } + + else if (TREE_INT_CST_HIGH (op1) == 0 + && TREE_INT_CST_LOW (op1) == signed_max + && TYPE_UNSIGNED (TREE_TYPE (op1)) + /* signed_type does not work on pointer types. */ + && INTEGRAL_TYPE_P (TREE_TYPE (op1))) + { + /* The following case also applies to X < signed_max+1 + and X >= signed_max+1 because previous transformations. */ + if (code == LE_EXPR || code == GT_EXPR) + { + tree st0, st1, exp, retval; + st0 = lang_hooks.types.signed_type (TREE_TYPE (op0)); + st1 = lang_hooks.types.signed_type (TREE_TYPE (op1)); + + exp = build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR, + type, + fold_convert (st0, op0), + fold_convert (st1, integer_zero_node)); + + retval + = nondestructive_fold_binary_to_constant (TREE_CODE (exp), + TREE_TYPE (exp), + TREE_OPERAND (exp, 0), + TREE_OPERAND (exp, 1)); + + /* If we are in gimple form, then returning EXP would create + non-gimple expressions. Clearing it is safe and insures + we do not allow a non-gimple expression to escape. */ + if (in_gimple_form) + exp = NULL; + + return (retval ? retval : exp); + } + } + } + + return NULL_TREE; +} + + +/* Given the components of a binary expression CODE, TYPE, OP0 and OP1, + attempt to fold the expression to a constant without modifying TYPE, + OP0 or OP1. + + If the expression could be simplified to a constant, then return + the constant. If the expression would not be simplified to a + constant, then return NULL_TREE. + + Note this is primarily designed to be called after gimplification + of the tree structures and when at least one operand is a constant. + As a result of those simplifying assumptions this routine is far + simpler than the generic fold routine. */ + +tree +nondestructive_fold_binary_to_constant (enum tree_code code, tree type, + tree op0, tree op1) +{ + int wins = 1; + tree subop0; + tree subop1; + tree tem; + + /* If this is a commutative operation, and ARG0 is a constant, move it + to ARG1 to reduce the number of tests below. */ + if (commutative_tree_code (code) + && (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST)) + { + tem = op0; + op0 = op1; + op1 = tem; + } + + /* If either operand is a complex type, extract its real component. */ + if (TREE_CODE (op0) == COMPLEX_CST) + subop0 = TREE_REALPART (op0); + else + subop0 = op0; + + if (TREE_CODE (op1) == COMPLEX_CST) + subop1 = TREE_REALPART (op1); + else + subop1 = op1; + + /* Note if either argument is not a real or integer constant. + With a few exceptions, simplification is limited to cases + where both arguments are constants. */ + if ((TREE_CODE (subop0) != INTEGER_CST + && TREE_CODE (subop0) != REAL_CST) + || (TREE_CODE (subop1) != INTEGER_CST + && TREE_CODE (subop1) != REAL_CST)) + wins = 0; + + switch (code) + { + case PLUS_EXPR: + /* (plus (address) (const_int)) is a constant. */ + if (TREE_CODE (op0) == PLUS_EXPR + && TREE_CODE (op1) == INTEGER_CST + && (TREE_CODE (TREE_OPERAND (op0, 0)) == ADDR_EXPR + || (TREE_CODE (TREE_OPERAND (op0, 0)) == NOP_EXPR + && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (op0, 0), 0)) + == ADDR_EXPR))) + && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST) + { + return build2 (PLUS_EXPR, type, TREE_OPERAND (op0, 0), + const_binop (PLUS_EXPR, op1, + TREE_OPERAND (op0, 1), 0)); + } + case BIT_XOR_EXPR: + + binary: + if (!wins) + return NULL_TREE; + + /* Both arguments are constants. Simplify. */ + tem = const_binop (code, op0, op1, 0); + if (tem != NULL_TREE) + { + /* The return value should always have the same type as + the original expression. */ + if (TREE_TYPE (tem) != type) + tem = fold_convert (type, tem); + + return tem; + } + return NULL_TREE; + + case MINUS_EXPR: + /* Fold &x - &x. This can happen from &x.foo - &x. + This is unsafe for certain floats even in non-IEEE formats. + In IEEE, it is unsafe because it does wrong for NaNs. + Also note that operand_equal_p is always false if an + operand is volatile. */ + if (! FLOAT_TYPE_P (type) && operand_equal_p (op0, op1, 0)) + return fold_convert (type, integer_zero_node); + + goto binary; + + case MULT_EXPR: + case BIT_AND_EXPR: + /* Special case multiplication or bitwise AND where one argument + is zero. */ + if (! FLOAT_TYPE_P (type) && integer_zerop (op1)) + return omit_one_operand (type, op1, op0); + else + if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (op0))) + && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op0))) + && real_zerop (op1)) + return omit_one_operand (type, op1, op0); + + goto binary; + + case BIT_IOR_EXPR: + /* Special case when we know the result will be all ones. */ + if (integer_all_onesp (op1)) + return omit_one_operand (type, op1, op0); + + goto binary; + + case TRUNC_DIV_EXPR: + case ROUND_DIV_EXPR: + case FLOOR_DIV_EXPR: + case CEIL_DIV_EXPR: + case EXACT_DIV_EXPR: + case TRUNC_MOD_EXPR: + case ROUND_MOD_EXPR: + case FLOOR_MOD_EXPR: + case CEIL_MOD_EXPR: + case RDIV_EXPR: + /* Division by zero is undefined. */ + if (integer_zerop (op1)) + return NULL_TREE; + + if (TREE_CODE (op1) == REAL_CST + && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (op1))) + && real_zerop (op1)) + return NULL_TREE; + + goto binary; + + case MIN_EXPR: + if (INTEGRAL_TYPE_P (type) + && operand_equal_p (op1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST)) + return omit_one_operand (type, op1, op0); + + goto binary; + + case MAX_EXPR: + if (INTEGRAL_TYPE_P (type) + && TYPE_MAX_VALUE (type) + && operand_equal_p (op1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST)) + return omit_one_operand (type, op1, op0); + + goto binary; + + case RSHIFT_EXPR: + /* Optimize -1 >> x for arithmetic right shifts. */ + if (integer_all_onesp (op0) && ! TYPE_UNSIGNED (type)) + return omit_one_operand (type, op0, op1); + /* ... fall through ... */ + + case LSHIFT_EXPR: + if (integer_zerop (op0)) + return omit_one_operand (type, op0, op1); + + /* Since negative shift count is not well-defined, don't + try to compute it in the compiler. */ + if (TREE_CODE (op1) == INTEGER_CST && tree_int_cst_sgn (op1) < 0) + return NULL_TREE; + + goto binary; + + case LROTATE_EXPR: + case RROTATE_EXPR: + /* -1 rotated either direction by any amount is still -1. */ + if (integer_all_onesp (op0)) + return omit_one_operand (type, op0, op1); + + /* 0 rotated either direction by any amount is still zero. */ + if (integer_zerop (op0)) + return omit_one_operand (type, op0, op1); + + goto binary; + + case COMPLEX_EXPR: + if (wins) + return build_complex (type, op0, op1); + return NULL_TREE; + + case LT_EXPR: + case LE_EXPR: + case GT_EXPR: + case GE_EXPR: + case EQ_EXPR: + case NE_EXPR: + /* If one arg is a real or integer constant, put it last. */ + if ((TREE_CODE (op0) == INTEGER_CST + && TREE_CODE (op1) != INTEGER_CST) + || (TREE_CODE (op0) == REAL_CST + && TREE_CODE (op0) != REAL_CST)) + { + tree temp; + + temp = op0; + op0 = op1; + op1 = temp; + code = swap_tree_comparison (code); + } + + /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0. + This transformation affects the cases which are handled in later + optimizations involving comparisons with non-negative constants. */ + if (TREE_CODE (op1) == INTEGER_CST + && TREE_CODE (op0) != INTEGER_CST + && tree_int_cst_sgn (op1) > 0) + { + switch (code) + { + case GE_EXPR: + code = GT_EXPR; + op1 = const_binop (MINUS_EXPR, op1, integer_one_node, 0); + break; + + case LT_EXPR: + code = LE_EXPR; + op1 = const_binop (MINUS_EXPR, op1, integer_one_node, 0); + break; + + default: + break; + } + } + + tem = fold_relational_hi_lo (&code, type, &op0, &op1); + if (tem) + return tem; + + if (!wins) + return NULL_TREE; + + return fold_relational_const (code, type, op0, op1); + + case RANGE_EXPR: + /* This could probably be handled. */ + return NULL_TREE; + + case TRUTH_AND_EXPR: + /* If second arg is constant zero, result is zero, but first arg + must be evaluated. */ + if (integer_zerop (op1)) + return omit_one_operand (type, op1, op0); + /* Likewise for first arg, but note that only the TRUTH_AND_EXPR + case will be handled here. */ + if (integer_zerop (op0)) + return omit_one_operand (type, op0, op1); + if (TREE_CODE (op0) == INTEGER_CST && TREE_CODE (op1) == INTEGER_CST) + { + int x1 = ! integer_zerop (op0); + int x2 = ! integer_zerop (op1); + + return ((x1 & x2) ? integer_one_node : integer_zero_node); + } + return NULL_TREE; + + case TRUTH_OR_EXPR: + /* If second arg is constant true, result is true, but we must + evaluate first arg. */ + if (TREE_CODE (op1) == INTEGER_CST && ! integer_zerop (op1)) + return omit_one_operand (type, op1, op0); + /* Likewise for first arg, but note this only occurs here for + TRUTH_OR_EXPR. */ + if (TREE_CODE (op0) == INTEGER_CST && ! integer_zerop (op0)) + return omit_one_operand (type, op0, op1); + if (TREE_CODE (op0) == INTEGER_CST && TREE_CODE (op1) == INTEGER_CST) + { + int x1 = ! integer_zerop (op0); + int x2 = ! integer_zerop (op1); + + return ((x1 | x2) ? integer_one_node : integer_zero_node); + } + return NULL_TREE; + + case TRUTH_XOR_EXPR: + if (TREE_CODE (op0) == INTEGER_CST && TREE_CODE (op1) == INTEGER_CST) + { + int x1 = ! integer_zerop (op0); + int x2 = ! integer_zerop (op1); + + return ((x1 ^ x2) ? integer_one_node : integer_zero_node); + } + return NULL_TREE; + + default: + return NULL_TREE; + } +} + +/* Given the components of a unary expression CODE, TYPE and OP0, + attempt to fold the expression to a constant without modifying + TYPE or OP0. + + If the expression could be simplified to a constant, then return + the constant. If the expression would not be simplified to a + constant, then return NULL_TREE. + + Note this is primarily designed to be called after gimplification + of the tree structures and when op0 is a constant. As a result + of those simplifying assumptions this routine is far simpler than + the generic fold routine. */ + +tree +nondestructive_fold_unary_to_constant (enum tree_code code, tree type, + tree op0) +{ + tree t; + + /* Make sure we have a suitable constant argument. */ + if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR) + { + tree subop; + + if (TREE_CODE (op0) == COMPLEX_CST) + subop = TREE_REALPART (op0); + else + subop = op0; + + if (TREE_CODE (subop) != INTEGER_CST && TREE_CODE (subop) != REAL_CST) + return NULL_TREE; + } + + switch (code) + { + case NOP_EXPR: + case FLOAT_EXPR: + case CONVERT_EXPR: + case FIX_TRUNC_EXPR: + case FIX_FLOOR_EXPR: + case FIX_CEIL_EXPR: + return fold_convert_const (code, type, op0); + + case NEGATE_EXPR: + if (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST) + return fold_negate_const (op0, type); + else + return NULL_TREE; + + case ABS_EXPR: + if (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST) + return fold_abs_const (op0, type); + else + return NULL_TREE; + + case BIT_NOT_EXPR: + if (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST) + { + t = build_int_2 (~ TREE_INT_CST_LOW (op0), ~ TREE_INT_CST_HIGH (op0)); + TREE_TYPE (t) = type; + force_fit_type (t, 0); + TREE_OVERFLOW (t) = TREE_OVERFLOW (op0); + TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (op0); + return t; + } + else + return NULL_TREE; + + case REALPART_EXPR: + if (TREE_CODE (op0) == COMPLEX_CST) + return TREE_REALPART (op0); + else + return NULL_TREE; + + case IMAGPART_EXPR: + if (TREE_CODE (op0) == COMPLEX_CST) + return TREE_IMAGPART (op0); + else + return NULL_TREE; + + case CONJ_EXPR: + if (TREE_CODE (op0) == COMPLEX_CST + && TREE_CODE (TREE_TYPE (op0)) == COMPLEX_TYPE) + return build_complex (type, TREE_REALPART (op0), + negate_expr (TREE_IMAGPART (op0))); + return NULL_TREE; + + default: + return NULL_TREE; + } +} + +/* If EXP represents referencing an element in a constant string + (either via pointer arithmetic or array indexing), return the + tree representing the value accessed, otherwise return NULL. */ + +tree +fold_read_from_constant_string (tree exp) +{ + if (TREE_CODE (exp) == INDIRECT_REF || TREE_CODE (exp) == ARRAY_REF) + { + tree exp1 = TREE_OPERAND (exp, 0); + tree index; + tree string; + + if (TREE_CODE (exp) == INDIRECT_REF) + { + string = string_constant (exp1, &index); + } + else + { + tree domain = TYPE_DOMAIN (TREE_TYPE (exp1)); + tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node; + index = fold_convert (sizetype, TREE_OPERAND (exp, 1)); + + /* Optimize the special-case of a zero lower bound. + + We convert the low_bound to sizetype to avoid some problems + with constant folding. (E.g. suppose the lower bound is 1, + and its mode is QI. Without the conversion,l (ARRAY + +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1)) + +INDEX), which becomes (ARRAY+255+INDEX). Opps!) */ + if (! integer_zerop (low_bound)) + index = size_diffop (index, fold_convert (sizetype, low_bound)); + + string = exp1; + } + + if (string + && TREE_CODE (string) == STRING_CST + && TREE_CODE (index) == INTEGER_CST + && compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0 + && (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_TYPE (string)))) + == MODE_INT) + && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (string)))) == 1)) + return build_int_2 ((TREE_STRING_POINTER (string) + [TREE_INT_CST_LOW (index)]), 0); + } + return NULL; +} + +/* Return the tree for neg (ARG0) when ARG0 is known to be either + an integer constant or real constant. + + TYPE is the type of the result. */ + +static tree +fold_negate_const (tree arg0, tree type) +{ + tree t = NULL_TREE; + + 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 && !TYPE_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))); +#ifdef ENABLE_CHECKING + else + abort (); +#endif + + return t; +} + +/* Return the tree for abs (ARG0) when ARG0 is known to be either + an integer constant or real constant. + + TYPE is the type of the result. */ + +static tree +fold_abs_const (tree arg0, tree type) +{ + tree t = NULL_TREE; + + if (TREE_CODE (arg0) == INTEGER_CST) + { + /* If the value is unsigned, then the absolute value is + the same as the ordinary value. */ + if (TYPE_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; + 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_CONSTANT_OVERFLOW (t) + = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0); + return t; + } + } + else if (TREE_CODE (arg0) == REAL_CST) + { + if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg0))) + return build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0))); + else + return arg0; + } +#ifdef ENABLE_CHECKING + else + abort (); +#endif + + return t; +} + +/* Given CODE, a relational operator, the target type, TYPE and two + constant operands OP0 and OP1, return the result of the + relational operation. If the result is not a compile time + constant, then return NULL_TREE. */ + +static tree +fold_relational_const (enum tree_code code, tree type, tree op0, tree op1) +{ + tree tem; + int invert; + + /* From here on, the only cases we handle are when the result is + known to be a constant. + + To compute GT, swap the arguments and do LT. + To compute GE, do LT and invert the result. + To compute LE, swap the arguments, do LT and invert the result. + To compute NE, do EQ and invert the result. + + Therefore, the code below must handle only EQ and LT. */ + + if (code == LE_EXPR || code == GT_EXPR) + { + tem = op0, op0 = op1, op1 = tem; + code = swap_tree_comparison (code); + } + + /* Note that it is safe to invert for real values here because we + will check below in the one case that it matters. */ + + tem = NULL_TREE; + invert = 0; + if (code == NE_EXPR || code == GE_EXPR) + { + invert = 1; + code = invert_tree_comparison (code); + } + + /* Compute a result for LT or EQ if args permit; + Otherwise return T. */ + if (TREE_CODE (op0) == INTEGER_CST && TREE_CODE (op1) == INTEGER_CST) + { + if (code == EQ_EXPR) + tem = build_int_2 (tree_int_cst_equal (op0, op1), 0); + else + tem = build_int_2 ((TYPE_UNSIGNED (TREE_TYPE (op0)) + ? INT_CST_LT_UNSIGNED (op0, op1) + : INT_CST_LT (op0, op1)), + 0); + } + + else if (code == EQ_EXPR && !TREE_SIDE_EFFECTS (op0) + && integer_zerop (op1) && tree_expr_nonzero_p (op0)) + tem = build_int_2 (0, 0); + + /* Two real constants can be compared explicitly. */ + else if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST) + { + /* If either operand is a NaN, the result is false with two + exceptions: First, an NE_EXPR is true on NaNs, but that case + is already handled correctly since we will be inverting the + result for NE_EXPR. Second, if we had inverted a LE_EXPR + or a GE_EXPR into a LT_EXPR, we must return true so that it + will be inverted into false. */ + + if (REAL_VALUE_ISNAN (TREE_REAL_CST (op0)) + || REAL_VALUE_ISNAN (TREE_REAL_CST (op1))) + tem = build_int_2 (invert && code == LT_EXPR, 0); + + else if (code == EQ_EXPR) + tem = build_int_2 (REAL_VALUES_EQUAL (TREE_REAL_CST (op0), + TREE_REAL_CST (op1)), + 0); + else + tem = build_int_2 (REAL_VALUES_LESS (TREE_REAL_CST (op0), + TREE_REAL_CST (op1)), + 0); + } + + if (tem == NULL_TREE) + return NULL_TREE; + + if (invert) + TREE_INT_CST_LOW (tem) ^= 1; + + TREE_TYPE (tem) = type; + if (TREE_CODE (type) == BOOLEAN_TYPE) + return lang_hooks.truthvalue_conversion (tem); + return tem; +} + #include "gt-fold-const.h"