X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ffold-const.c;h=6f829adfa7714a6772cc49a549c14ece905a5460;hb=61631574d437729dc9b0648d83b50bc6faabf9d2;hp=383bd670d1d4211916a0836d525cf8f74d9c1894;hpb=ba04ccb0240001f36c0cbf154d2c0d37001019da;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 383bd670d1d..6f829adfa77 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -2019,7 +2019,7 @@ fold_convert (tree type, tree arg) gcc_assert (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig))); gcc_assert (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig) || TREE_CODE (orig) == VECTOR_TYPE); - return fold_build1 (NOP_EXPR, type, arg); + return fold_build1 (VIEW_CONVERT_EXPR, type, arg); case VOID_TYPE: return fold_build1 (CONVERT_EXPR, type, fold_ignored_result (arg)); @@ -3025,9 +3025,18 @@ invert_truthvalue (tree arg) return TREE_OPERAND (arg, 0); case COND_EXPR: - return build3 (COND_EXPR, type, TREE_OPERAND (arg, 0), - invert_truthvalue (TREE_OPERAND (arg, 1)), - invert_truthvalue (TREE_OPERAND (arg, 2))); + { + tree arg1 = TREE_OPERAND (arg, 1); + tree arg2 = TREE_OPERAND (arg, 2); + /* A COND_EXPR may have a throw as one operand, which + then has void type. Just leave void operands + as they are. */ + return build3 (COND_EXPR, type, TREE_OPERAND (arg, 0), + VOID_TYPE_P (TREE_TYPE (arg1)) + ? arg1 : invert_truthvalue (arg1), + VOID_TYPE_P (TREE_TYPE (arg2)) + ? arg2 : invert_truthvalue (arg2)); + } case COMPOUND_EXPR: return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0), @@ -3340,11 +3349,11 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type, TREE_THIS_VOLATILE (lhs) = 1; } - rhs = fold (const_binop (BIT_AND_EXPR, - const_binop (LSHIFT_EXPR, - fold_convert (unsigned_type, rhs), - size_int (lbitpos), 0), - mask, 0)); + rhs = const_binop (BIT_AND_EXPR, + const_binop (LSHIFT_EXPR, + fold_convert (unsigned_type, rhs), + size_int (lbitpos), 0), + mask, 0); return build2 (code, compare_type, build2 (BIT_AND_EXPR, unsigned_type, lhs, mask), @@ -3929,6 +3938,15 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high) tree etype = TREE_TYPE (exp); tree value; +#ifdef HAVE_canonicalize_funcptr_for_compare + /* Disable this optimization for function pointer expressions + on targets that require function pointer canonicalization. */ + if (HAVE_canonicalize_funcptr_for_compare + && TREE_CODE (etype) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (etype)) == FUNCTION_TYPE) + return NULL_TREE; +#endif + if (! in_p) { value = build_range_check (type, exp, 1, low, high); @@ -3996,7 +4014,8 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high) } value = const_binop (MINUS_EXPR, high, low, 0); - if (value != 0 && TREE_OVERFLOW (value) && ! TYPE_UNSIGNED (etype)) + if (value != 0 && (!flag_wrapv || TREE_OVERFLOW (value)) + && ! TYPE_UNSIGNED (etype)) { tree utype, minv, maxv; @@ -4007,6 +4026,11 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high) case INTEGER_TYPE: case ENUMERAL_TYPE: case CHAR_TYPE: + /* There is no requirement that LOW be within the range of ETYPE + if the latter is a subtype. It must, however, be within the base + type of ETYPE. So be sure we do the subtraction in that type. */ + if (TREE_TYPE (etype)) + etype = TREE_TYPE (etype); utype = lang_hooks.types.unsigned_type (etype); maxv = fold_convert (utype, TYPE_MAX_VALUE (etype)); maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1, @@ -6241,8 +6265,6 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1) return NULL_TREE; arg1_unw = get_unwidened (arg1, shorter_type); - if (!arg1_unw) - return NULL_TREE; /* If possible, express the comparison in the shorter mode. */ if ((code == EQ_EXPR || code == NE_EXPR @@ -6255,7 +6277,9 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1) return fold_build2 (code, type, arg0_unw, fold_convert (shorter_type, arg1_unw)); - if (TREE_CODE (arg1_unw) != INTEGER_CST) + if (TREE_CODE (arg1_unw) != INTEGER_CST + || TREE_CODE (shorter_type) != INTEGER_TYPE + || !int_fits_type_p (arg1_unw, shorter_type)) return NULL_TREE; /* If we are comparing with the integer that does not fit into the range @@ -6459,7 +6483,7 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree op1) TREE_OPERAND (pos, 1)), fold_convert (itype, delta)); - return build1 (ADDR_EXPR, TREE_TYPE (addr), ret); + return fold_build1 (ADDR_EXPR, TREE_TYPE (addr), ret); } @@ -7104,26 +7128,18 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) return fold_convert (type, tem); } - if (TREE_CODE_CLASS (code) == tcc_comparison - && TREE_CODE (arg0) == COMPOUND_EXPR) - return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), - fold_build2 (code, type, TREE_OPERAND (arg0, 1), arg1)); - else if (TREE_CODE_CLASS (code) == tcc_comparison - && TREE_CODE (arg1) == COMPOUND_EXPR) - return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0), - fold_build2 (code, type, arg0, TREE_OPERAND (arg1, 1))); - else if (TREE_CODE_CLASS (code) == tcc_binary - || TREE_CODE_CLASS (code) == tcc_comparison) + if (TREE_CODE_CLASS (code) == tcc_binary + || TREE_CODE_CLASS (code) == tcc_comparison) { if (TREE_CODE (arg0) == COMPOUND_EXPR) return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), - fold_build2 (code, type, TREE_OPERAND (arg0, 1), - arg1)); + fold_build2 (code, type, + TREE_OPERAND (arg0, 1), op1)); if (TREE_CODE (arg1) == COMPOUND_EXPR && 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))); + op0, TREE_OPERAND (arg1, 1))); if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0)) { @@ -7296,13 +7312,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) { tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1); if (tem) - return fold_convert (type, fold (tem)); + return fold_convert (type, tem); } else if (TREE_CODE (arg1) == ADDR_EXPR) { tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0); if (tem) - return fold_convert (type, fold (tem)); + return fold_convert (type, tem); } } else @@ -7721,7 +7737,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) { tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1); if (tem) - return fold_convert (type, fold (tem)); + return fold_convert (type, tem); } if (flag_unsafe_math_optimizations @@ -9276,7 +9292,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) return omit_one_operand (type, integer_one_node, arg0); case GT_EXPR: - return fold_build2 (NE_EXPR, type, arg0, arg1); + return fold_build2 (NE_EXPR, type, op0, op1); default: break; @@ -9310,10 +9326,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) tree st0, st1; st0 = lang_hooks.types.signed_type (TREE_TYPE (arg0)); st1 = lang_hooks.types.signed_type (TREE_TYPE (arg1)); - return fold - (build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR, - type, fold_convert (st0, arg0), - fold_convert (st1, integer_zero_node))); + return fold_build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR, + type, fold_convert (st0, arg0), + build_int_cst (st1, 0)); } } } @@ -9998,7 +10013,8 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2) /* If the second operand is simpler than the third, swap them since that produces better jump optimization results. */ - if (tree_swap_operands_p (op1, op2, false)) + if (truth_value_p (TREE_CODE (arg0)) + && tree_swap_operands_p (op1, op2, false)) { /* See if this can be inverted. If it can't, possibly because it was a floating-point inequality comparison, don't do @@ -10107,13 +10123,7 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2) if (TREE_CODE (op0) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (op0, 0)) == FUNCTION_DECL && DECL_BUILT_IN (TREE_OPERAND (op0, 0))) - { - tree fndecl = TREE_OPERAND (op0, 0); - tree arglist = op1; - tree tmp = fold_builtin (fndecl, arglist, false); - if (tmp) - return tmp; - } + return fold_builtin (TREE_OPERAND (op0, 0), op1, false); return NULL_TREE; case BIT_FIELD_REF: @@ -10275,14 +10285,14 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht) { void **slot; enum tree_code code; - char buf[sizeof (struct tree_decl_non_common)]; + char buf[sizeof (struct tree_function_decl)]; int i, len; recursive_label: gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree) - <= sizeof (struct tree_decl_non_common)) - && sizeof (struct tree_type) <= sizeof (struct tree_decl_non_common)); + <= sizeof (struct tree_function_decl)) + && sizeof (struct tree_type) <= sizeof (struct tree_function_decl)); if (expr == NULL) return; slot = htab_find_slot (ht, expr, INSERT); @@ -10373,13 +10383,18 @@ recursive_label: fold_checksum_tree (DECL_SIZE_UNIT (expr), ctx, ht); fold_checksum_tree (DECL_NAME (expr), ctx, ht); fold_checksum_tree (DECL_CONTEXT (expr), ctx, ht); - fold_checksum_tree (DECL_ARGUMENTS (expr), ctx, ht); - fold_checksum_tree (DECL_RESULT_FLD (expr), ctx, ht); fold_checksum_tree (DECL_INITIAL (expr), ctx, ht); fold_checksum_tree (DECL_ABSTRACT_ORIGIN (expr), ctx, ht); - fold_checksum_tree (DECL_SECTION_NAME (expr), ctx, ht); fold_checksum_tree (DECL_ATTRIBUTES (expr), ctx, ht); - fold_checksum_tree (DECL_VINDEX (expr), ctx, ht); + if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_WITH_VIS)) + fold_checksum_tree (DECL_SECTION_NAME (expr), ctx, ht); + + if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_NON_COMMON)) + { + fold_checksum_tree (DECL_VINDEX (expr), ctx, ht); + fold_checksum_tree (DECL_RESULT_FLD (expr), ctx, ht); + fold_checksum_tree (DECL_ARGUMENT_FLD (expr), ctx, ht); + } break; case tcc_type: if (TREE_CODE (expr) == ENUMERAL_TYPE) @@ -10569,33 +10584,65 @@ fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2 } /* Perform constant folding and related simplification of initializer - expression EXPR. This behaves identically to "fold" but ignores + expression EXPR. These behave identically to "fold_buildN" but ignore potential run-time traps and exceptions that fold must preserve. */ +#define START_FOLD_INIT \ + int saved_signaling_nans = flag_signaling_nans;\ + int saved_trapping_math = flag_trapping_math;\ + int saved_rounding_math = flag_rounding_math;\ + int saved_trapv = flag_trapv;\ + flag_signaling_nans = 0;\ + flag_trapping_math = 0;\ + flag_rounding_math = 0;\ + flag_trapv = 0 + +#define END_FOLD_INIT \ + flag_signaling_nans = saved_signaling_nans;\ + flag_trapping_math = saved_trapping_math;\ + flag_rounding_math = saved_rounding_math;\ + flag_trapv = saved_trapv + tree -fold_initializer (tree expr) +fold_build1_initializer (enum tree_code code, tree type, tree op) { - int saved_signaling_nans = flag_signaling_nans; - int saved_trapping_math = flag_trapping_math; - int saved_rounding_math = flag_rounding_math; - int saved_trapv = flag_trapv; tree result; + START_FOLD_INIT; - flag_signaling_nans = 0; - flag_trapping_math = 0; - flag_rounding_math = 0; - flag_trapv = 0; + result = fold_build1 (code, type, op); - result = fold (expr); + END_FOLD_INIT; + return result; +} + +tree +fold_build2_initializer (enum tree_code code, tree type, tree op0, tree op1) +{ + tree result; + START_FOLD_INIT; + + result = fold_build2 (code, type, op0, op1); + + END_FOLD_INIT; + return result; +} - flag_signaling_nans = saved_signaling_nans; - flag_trapping_math = saved_trapping_math; - flag_rounding_math = saved_rounding_math; - flag_trapv = saved_trapv; +tree +fold_build3_initializer (enum tree_code code, tree type, tree op0, tree op1, + tree op2) +{ + tree result; + START_FOLD_INIT; + result = fold_build3 (code, type, op0, op1, op2); + + END_FOLD_INIT; return result; } +#undef START_FOLD_INIT +#undef END_FOLD_INIT + /* Determine if first argument is a multiple of second argument. Return 0 if it is not, or we cannot easily determined it to be. @@ -10780,6 +10827,15 @@ tree_expr_nonnegative_p (tree t) } return 0; + case BIT_AND_EXPR: + case MAX_EXPR: + return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)) + || tree_expr_nonnegative_p (TREE_OPERAND (t, 1)); + + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case MIN_EXPR: + case RDIV_EXPR: case TRUNC_DIV_EXPR: case CEIL_DIV_EXPR: case FLOOR_DIV_EXPR: @@ -10791,19 +10847,21 @@ tree_expr_nonnegative_p (tree t) case CEIL_MOD_EXPR: case FLOOR_MOD_EXPR: case ROUND_MOD_EXPR: + case SAVE_EXPR: + case NON_LVALUE_EXPR: + case FLOAT_EXPR: return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)); - case RDIV_EXPR: - return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)) - && tree_expr_nonnegative_p (TREE_OPERAND (t, 1)); + case COMPOUND_EXPR: + case MODIFY_EXPR: + return tree_expr_nonnegative_p (TREE_OPERAND (t, 1)); - case BIT_AND_EXPR: + case BIND_EXPR: + return tree_expr_nonnegative_p (expr_last (TREE_OPERAND (t, 1))); + + case COND_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)); + && tree_expr_nonnegative_p (TREE_OPERAND (t, 2)); case NOP_EXPR: { @@ -10832,28 +10890,6 @@ tree_expr_nonnegative_p (tree t) } break; - case COND_EXPR: - return tree_expr_nonnegative_p (TREE_OPERAND (t, 1)) - && tree_expr_nonnegative_p (TREE_OPERAND (t, 2)); - case COMPOUND_EXPR: - return tree_expr_nonnegative_p (TREE_OPERAND (t, 1)); - case MIN_EXPR: - return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)) - && tree_expr_nonnegative_p (TREE_OPERAND (t, 1)); - case MAX_EXPR: - return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)) - || tree_expr_nonnegative_p (TREE_OPERAND (t, 1)); - case MODIFY_EXPR: - return tree_expr_nonnegative_p (TREE_OPERAND (t, 1)); - case BIND_EXPR: - return tree_expr_nonnegative_p (expr_last (TREE_OPERAND (t, 1))); - case SAVE_EXPR: - return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)); - case NON_LVALUE_EXPR: - return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)); - case FLOAT_EXPR: - return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)); - case TARGET_EXPR: { tree temp = TARGET_EXPR_SLOT (t); @@ -11736,10 +11772,10 @@ ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff) toffset2 = fold_convert (type, toffset2); tdiff = fold_build2 (MINUS_EXPR, type, toffset1, toffset2); - if (!host_integerp (tdiff, 0)) + if (!cst_and_fits_in_hwi (tdiff)) return false; - *diff = tree_low_cst (tdiff, 0); + *diff = int_cst_value (tdiff); } else if (toffset1 || toffset2) {