X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-vrp.c;h=8fcf629addecac26ba0e8ba1508321b3ee7c1a48;hb=a2145c8fcd31ec4449cfd8bf9375c269c4627948;hp=35d12b309ddb76a839ae2d4820f8bdc0ad33cf75;hpb=14f101cffa72ffaa29995b1e6a3597c676a7882a;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 35d12b309dd..8fcf629adde 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -1,5 +1,5 @@ /* Support routines for Value Range Propagation (VRP). - Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Diego Novillo . @@ -34,12 +34,12 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "gimple-pretty-print.h" #include "diagnostic-core.h" -#include "toplev.h" #include "intl.h" #include "cfgloop.h" #include "tree-scalar-evolution.h" #include "tree-ssa-propagate.h" #include "tree-chrec.h" +#include "gimple-fold.h" /* Type of value ranges. See value_range_d for a description of these @@ -243,9 +243,7 @@ supports_overflow_infinity (const_tree type) static inline tree make_overflow_infinity (tree val) { -#ifdef ENABLE_CHECKING - gcc_assert (val != NULL_TREE && CONSTANT_CLASS_P (val)); -#endif + gcc_checking_assert (val != NULL_TREE && CONSTANT_CLASS_P (val)); val = copy_node (val); TREE_OVERFLOW (val) = 1; return val; @@ -256,9 +254,7 @@ make_overflow_infinity (tree val) static inline tree negative_overflow_infinity (tree type) { -#ifdef ENABLE_CHECKING - gcc_assert (supports_overflow_infinity (type)); -#endif + gcc_checking_assert (supports_overflow_infinity (type)); return make_overflow_infinity (vrp_val_min (type)); } @@ -267,9 +263,7 @@ negative_overflow_infinity (tree type) static inline tree positive_overflow_infinity (tree type) { -#ifdef ENABLE_CHECKING - gcc_assert (supports_overflow_infinity (type)); -#endif + gcc_checking_assert (supports_overflow_infinity (type)); return make_overflow_infinity (vrp_val_max (type)); } @@ -332,9 +326,7 @@ avoid_overflow_infinity (tree val) return vrp_val_max (TREE_TYPE (val)); else { -#ifdef ENABLE_CHECKING - gcc_assert (vrp_val_is_min (val)); -#endif + gcc_checking_assert (vrp_val_is_min (val)); return vrp_val_min (TREE_TYPE (val)); } } @@ -480,8 +472,8 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t, if (tree_int_cst_lt (max, min)) { tree one = build_int_cst (TREE_TYPE (min), 1); - tree tmp = int_const_binop (PLUS_EXPR, max, one, 0); - max = int_const_binop (MINUS_EXPR, min, one, 0); + tree tmp = int_const_binop (PLUS_EXPR, max, one); + max = int_const_binop (MINUS_EXPR, min, one); min = tmp; /* There's one corner case, if we had [C+1, C] before we now have @@ -514,14 +506,14 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t, && integer_zerop (max))) { tree one = build_int_cst (TREE_TYPE (max), 1); - min = int_const_binop (PLUS_EXPR, max, one, 0); + min = int_const_binop (PLUS_EXPR, max, one); max = vrp_val_max (TREE_TYPE (max)); t = VR_RANGE; } else if (is_max) { tree one = build_int_cst (TREE_TYPE (min), 1); - max = int_const_binop (MINUS_EXPR, min, one, 0); + max = int_const_binop (MINUS_EXPR, min, one); min = vrp_val_min (TREE_TYPE (min)); t = VR_RANGE; } @@ -723,6 +715,8 @@ static inline bool vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2) { return (b1 == b2 + || ((!b1 || bitmap_empty_p (b1)) + && (!b2 || bitmap_empty_p (b2))) || (b1 && b2 && bitmap_equal_p (b1, b2))); } @@ -1532,7 +1526,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr) { min = fold_build1 (NEGATE_EXPR, TREE_TYPE (TREE_OPERAND (cond, 1)), TREE_OPERAND (cond, 1)); - max = int_const_binop (PLUS_EXPR, limit, min, 0); + max = int_const_binop (PLUS_EXPR, limit, min); cond = TREE_OPERAND (cond, 0); } else @@ -1960,7 +1954,7 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2) { tree res; - res = int_const_binop (code, val1, val2, 0); + res = int_const_binop (code, val1, val2); /* If we are using unsigned arithmetic, operate symbolically on -INF and +INF as int_const_binop only handles signed overflow. */ @@ -1987,7 +1981,7 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2) { tree tmp = int_const_binop (TRUNC_DIV_EXPR, res, - val1, 0); + val1); int check = compare_values (tmp, val2); if (check != 0) @@ -2364,17 +2358,27 @@ extract_range_from_binary_expr (value_range_t *vr, op0 + op1 == 0, so we cannot claim that the sum is in ~[0,0]. Note that we are guaranteed to have vr0.type == vr1.type at this point. */ - if (code == PLUS_EXPR && vr0.type == VR_ANTI_RANGE) + if (vr0.type == VR_ANTI_RANGE) { - set_value_range_to_varying (vr); - return; + if (code == PLUS_EXPR) + { + set_value_range_to_varying (vr); + return; + } + /* For MIN_EXPR and MAX_EXPR with two VR_ANTI_RANGEs, + the resulting VR_ANTI_RANGE is the same - intersection + of the two ranges. */ + min = vrp_int_const_binop (MAX_EXPR, vr0.min, vr1.min); + max = vrp_int_const_binop (MIN_EXPR, vr0.max, vr1.max); + } + else + { + /* For operations that make the resulting range directly + proportional to the original ranges, apply the operation to + the same end of each range. */ + min = vrp_int_const_binop (code, vr0.min, vr1.min); + max = vrp_int_const_binop (code, vr0.max, vr1.max); } - - /* For operations that make the resulting range directly - proportional to the original ranges, apply the operation to - the same end of each range. */ - min = vrp_int_const_binop (code, vr0.min, vr1.min); - max = vrp_int_const_binop (code, vr0.max, vr1.max); /* If both additions overflowed the range kind is still correct. This happens regularly with subtracting something in unsigned @@ -2464,6 +2468,22 @@ extract_range_from_binary_expr (value_range_t *vr, } } + /* For divisions, if flag_non_call_exceptions is true, we must + not eliminate a division by zero. */ + if ((code == TRUNC_DIV_EXPR + || code == FLOOR_DIV_EXPR + || code == CEIL_DIV_EXPR + || code == EXACT_DIV_EXPR + || code == ROUND_DIV_EXPR) + && cfun->can_throw_non_call_exceptions + && (vr1.type != VR_RANGE + || symbolic_range_p (&vr1) + || range_includes_zero_p (&vr1))) + { + set_value_range_to_varying (vr); + return; + } + /* For divisions, if op0 is VR_RANGE, we can deduce a range even if op1 is VR_VARYING, VR_ANTI_RANGE, symbolic or can include 0. */ @@ -2626,7 +2646,7 @@ extract_range_from_binary_expr (value_range_t *vr, max = fold_unary_to_constant (ABS_EXPR, TREE_TYPE (vr1.min), vr1.min); if (tree_int_cst_lt (max, vr1.max)) max = vr1.max; - max = int_const_binop (MINUS_EXPR, max, integer_one_node, 0); + max = int_const_binop (MINUS_EXPR, max, integer_one_node); /* If the dividend is non-negative the modulus will be non-negative as well. */ if (TYPE_UNSIGNED (TREE_TYPE (max)) @@ -2671,7 +2691,7 @@ extract_range_from_binary_expr (value_range_t *vr, type = VR_RANGE; if (vr0_int_cst_singleton_p && vr1_int_cst_singleton_p) - min = max = int_const_binop (code, vr0.max, vr1.max, 0); + min = max = int_const_binop (code, vr0.max, vr1.max); else if (!int_cst_range0 && !int_cst_range1) { set_value_range_to_varying (vr); @@ -2895,8 +2915,8 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code, && (TYPE_PRECISION (outer_type) >= TYPE_PRECISION (inner_type) || (vr0.type == VR_RANGE && integer_zerop (int_const_binop (RSHIFT_EXPR, - int_const_binop (MINUS_EXPR, vr0.max, vr0.min, 0), - size_int (TYPE_PRECISION (outer_type)), 0))))) + int_const_binop (MINUS_EXPR, vr0.max, vr0.min), + size_int (TYPE_PRECISION (outer_type))))))) { tree new_min, new_max; new_min = force_fit_type_double (outer_type, @@ -3063,7 +3083,7 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code, min = (vr0.min != type_min_value ? int_const_binop (PLUS_EXPR, type_min_value, - integer_one_node, 0) + integer_one_node) : type_min_value); } else @@ -3382,6 +3402,43 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, else tmax = TYPE_MAX_VALUE (type); + /* Try to use estimated number of iterations for the loop to constrain the + final value in the evolution. + We are interested in the number of executions of the latch, while + nb_iterations_upper_bound includes the last execution of the exit test. */ + if (TREE_CODE (step) == INTEGER_CST + && loop->any_upper_bound + && !double_int_zero_p (loop->nb_iterations_upper_bound) + && is_gimple_val (init) + && (TREE_CODE (init) != SSA_NAME + || get_value_range (init)->type == VR_RANGE)) + { + value_range_t maxvr = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }; + double_int dtmp; + bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (step)); + int overflow = 0; + + dtmp = double_int_mul_with_sign (tree_to_double_int (step), + double_int_sub ( + loop->nb_iterations_upper_bound, + double_int_one), + unsigned_p, &overflow); + tem = double_int_to_tree (TREE_TYPE (init), dtmp); + /* If the multiplication overflowed we can't do a meaningful + adjustment. */ + if (!overflow && double_int_equal_p (dtmp, tree_to_double_int (tem))) + { + extract_range_from_binary_expr (&maxvr, PLUS_EXPR, + TREE_TYPE (init), init, tem); + /* Likewise if the addition did. */ + if (maxvr.type == VR_RANGE) + { + tmin = maxvr.min; + tmax = maxvr.max; + } + } + } + if (vr->type == VR_VARYING || vr->type == VR_UNDEFINED) { min = tmin; @@ -3414,40 +3471,35 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, /* INIT is the maximum value. If INIT is lower than VR->MAX but no smaller than VR->MIN, set VR->MAX to INIT. */ if (compare_values (init, max) == -1) - { - max = init; - - /* If we just created an invalid range with the minimum - greater than the maximum, we fail conservatively. - This should happen only in unreachable - parts of code, or for invalid programs. */ - if (compare_values (min, max) == 1) - return; - } + max = init; /* According to the loop information, the variable does not overflow. If we think it does, probably because of an overflow due to arithmetic on a different INF value, reset now. */ - if (is_negative_overflow_infinity (min)) + if (is_negative_overflow_infinity (min) + || compare_values (min, tmin) == -1) min = tmin; + } else { /* If INIT is bigger than VR->MIN, set VR->MIN to INIT. */ if (compare_values (init, min) == 1) - { - min = init; - - /* Again, avoid creating invalid range by failing. */ - if (compare_values (min, max) == 1) - return; - } + min = init; - if (is_positive_overflow_infinity (max)) + if (is_positive_overflow_infinity (max) + || compare_values (tmax, max) == -1) max = tmax; } + /* If we just created an invalid range with the minimum + greater than the maximum, we fail conservatively. + This should happen only in unreachable + parts of code, or for invalid programs. */ + if (compare_values (min, max) == 1) + return; + set_value_range (vr, VR_RANGE, min, max, vr->equiv); } } @@ -4104,13 +4156,11 @@ register_new_assert_for (tree name, tree expr, assert_locus_t n, loc, last_loc; basic_block dest_bb; -#if defined ENABLE_CHECKING - gcc_assert (bb == NULL || e == NULL); + gcc_checking_assert (bb == NULL || e == NULL); if (e == NULL) - gcc_assert (gimple_code (gsi_stmt (si)) != GIMPLE_COND - && gimple_code (gsi_stmt (si)) != GIMPLE_SWITCH); -#endif + gcc_checking_assert (gimple_code (gsi_stmt (si)) != GIMPLE_COND + && gimple_code (gsi_stmt (si)) != GIMPLE_SWITCH); /* Never build an assert comparing against an integer constant with TREE_OVERFLOW set. This confuses our undefined overflow warning @@ -4623,28 +4673,35 @@ find_conditional_asserts (basic_block bb, gimple last) return need_assert; } -/* Compare two case labels sorting first by the destination label uid +struct case_info +{ + tree expr; + basic_block bb; +}; + +/* Compare two case labels sorting first by the destination bb index and then by the case value. */ static int compare_case_labels (const void *p1, const void *p2) { - const_tree const case1 = *(const_tree const*)p1; - const_tree const case2 = *(const_tree const*)p2; - unsigned int uid1 = DECL_UID (CASE_LABEL (case1)); - unsigned int uid2 = DECL_UID (CASE_LABEL (case2)); + const struct case_info *ci1 = (const struct case_info *) p1; + const struct case_info *ci2 = (const struct case_info *) p2; + int idx1 = ci1->bb->index; + int idx2 = ci2->bb->index; - if (uid1 < uid2) + if (idx1 < idx2) return -1; - else if (uid1 == uid2) + else if (idx1 == idx2) { /* Make sure the default label is first in a group. */ - if (!CASE_LOW (case1)) + if (!CASE_LOW (ci1->expr)) return -1; - else if (!CASE_LOW (case2)) + else if (!CASE_LOW (ci2->expr)) return 1; else - return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2)); + return tree_int_cst_compare (CASE_LOW (ci1->expr), + CASE_LOW (ci2->expr)); } else return 1; @@ -4665,8 +4722,8 @@ find_switch_asserts (basic_block bb, gimple last) gimple_stmt_iterator bsi; tree op; edge e; - tree vec2; - size_t n = gimple_switch_num_labels(last); + struct case_info *ci; + size_t n = gimple_switch_num_labels (last); #if GCC_VERSION >= 4000 unsigned int idx; #else @@ -4681,36 +4738,38 @@ find_switch_asserts (basic_block bb, gimple last) return false; /* Build a vector of case labels sorted by destination label. */ - vec2 = make_tree_vec (n); + ci = XNEWVEC (struct case_info, n); for (idx = 0; idx < n; ++idx) - TREE_VEC_ELT (vec2, idx) = gimple_switch_label (last, idx); - qsort (&TREE_VEC_ELT (vec2, 0), n, sizeof (tree), compare_case_labels); + { + ci[idx].expr = gimple_switch_label (last, idx); + ci[idx].bb = label_to_block (CASE_LABEL (ci[idx].expr)); + } + qsort (ci, n, sizeof (struct case_info), compare_case_labels); for (idx = 0; idx < n; ++idx) { tree min, max; - tree cl = TREE_VEC_ELT (vec2, idx); + tree cl = ci[idx].expr; + basic_block cbb = ci[idx].bb; min = CASE_LOW (cl); max = CASE_HIGH (cl); /* If there are multiple case labels with the same destination we need to combine them to a single value range for the edge. */ - if (idx + 1 < n - && CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx + 1))) + if (idx + 1 < n && cbb == ci[idx + 1].bb) { /* Skip labels until the last of the group. */ do { ++idx; - } while (idx < n - && CASE_LABEL (cl) == CASE_LABEL (TREE_VEC_ELT (vec2, idx))); + } while (idx < n && cbb == ci[idx].bb); --idx; /* Pick up the maximum of the case label range. */ - if (CASE_HIGH (TREE_VEC_ELT (vec2, idx))) - max = CASE_HIGH (TREE_VEC_ELT (vec2, idx)); + if (CASE_HIGH (ci[idx].expr)) + max = CASE_HIGH (ci[idx].expr); else - max = CASE_LOW (TREE_VEC_ELT (vec2, idx)); + max = CASE_LOW (ci[idx].expr); } /* Nothing to do if the range includes the default label until we @@ -4719,7 +4778,7 @@ find_switch_asserts (basic_block bb, gimple last) continue; /* Find the edge to register the assert expr on. */ - e = find_edge (bb, label_to_block (CASE_LABEL (cl))); + e = find_edge (bb, cbb); /* Register the necessary assertions for the operand in the SWITCH_EXPR. */ @@ -4737,6 +4796,7 @@ find_switch_asserts (basic_block bb, gimple last) } } + XDELETEVEC (ci); return need_assert; } @@ -5032,10 +5092,9 @@ process_assert_insertions_for (tree name, assert_locus_t loc) { /* We have been asked to insert the assertion on an edge. This is used only by COND_EXPR and SWITCH_EXPR assertions. */ -#if defined ENABLE_CHECKING - gcc_assert (gimple_code (gsi_stmt (loc->si)) == GIMPLE_COND - || gimple_code (gsi_stmt (loc->si)) == GIMPLE_SWITCH); -#endif + gcc_checking_assert (gimple_code (gsi_stmt (loc->si)) == GIMPLE_COND + || (gimple_code (gsi_stmt (loc->si)) + == GIMPLE_SWITCH)); gsi_insert_on_edge (loc->e, assert_stmt); return true; @@ -5209,7 +5268,7 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one) } low_bound = array_ref_low_bound (ref); - up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound, integer_one_node, 0); + up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound, integer_one_node); if (TREE_CODE (low_sub) == SSA_NAME) { @@ -5576,6 +5635,21 @@ vrp_initialize (void) } } +/* Return the singleton value-range for NAME or NAME. */ + +static inline tree +vrp_valueize (tree name) +{ + if (TREE_CODE (name) == SSA_NAME) + { + value_range_t *vr = get_value_range (name); + if (vr->type == VR_RANGE + && (vr->min == vr->max + || operand_equal_p (vr->min, vr->max, 0))) + return vr->min; + } + return name; +} /* Visit assignment STMT. If it produces an interesting range, record the SSA name in *OUTPUT_P. */ @@ -5599,7 +5673,12 @@ vrp_visit_assignment_or_call (gimple stmt, tree *output_p) { value_range_t new_vr = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }; - if (code == GIMPLE_CALL) + /* Try folding the statement to a constant first. */ + tree tem = gimple_fold_stmt_to_constant (stmt, vrp_valueize); + if (tem && !is_overflow_infinity (tem)) + set_value_range (&new_vr, VR_RANGE, tem, tem, NULL); + /* Then dispatch to value-range extracting functions. */ + else if (code == GIMPLE_CALL) extract_range_basic (&new_vr, stmt); else extract_range_from_assignment (&new_vr, stmt); @@ -6201,7 +6280,7 @@ find_case_label_range (gimple stmt, tree min, tree max, size_t *min_idx, for (k = i + 1; k <= j; ++k) { low = CASE_LOW (gimple_switch_label (stmt, k)); - if (!integer_onep (int_const_binop (MINUS_EXPR, low, high, 0))) + if (!integer_onep (int_const_binop (MINUS_EXPR, low, high))) { take_default = true; break; @@ -6328,7 +6407,6 @@ vrp_visit_stmt (gimple stmt, edge *taken_edge_p, tree *output_p) /* In general, assignments with virtual operands are not useful for deriving ranges, with the obvious exception of calls to builtin functions. */ - if ((is_gimple_call (stmt) && gimple_call_fndecl (stmt) != NULL_TREE && DECL_IS_BUILTIN (gimple_call_fndecl (stmt))) @@ -6509,8 +6587,6 @@ vrp_visit_phi_node (gimple phi) int edges, old_edges; struct loop *l; - copy_value_range (&vr_result, lhs_vr); - if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "\nVisiting PHI node: "); @@ -6571,13 +6647,6 @@ vrp_visit_phi_node (gimple phi) } } - /* If this is a loop PHI node SCEV may known more about its - value-range. */ - if (current_loops - && (l = loop_containing_stmt (phi)) - && l->header == gimple_bb (phi)) - adjust_range_with_scev (&vr_result, l, phi, lhs); - if (vr_result.type == VR_VARYING) goto varying; @@ -6589,61 +6658,64 @@ vrp_visit_phi_node (gimple phi) previous one. We don't do this if we have seen a new executable edge; this helps us avoid an overflow infinity for conditionals which are not in a loop. */ - if (lhs_vr->type == VR_RANGE && vr_result.type == VR_RANGE - && edges <= old_edges) - { - if (!POINTER_TYPE_P (TREE_TYPE (lhs))) - { - int cmp_min = compare_values (lhs_vr->min, vr_result.min); - int cmp_max = compare_values (lhs_vr->max, vr_result.max); - - /* If the new minimum is smaller or larger than the previous - one, go all the way to -INF. In the first case, to avoid - iterating millions of times to reach -INF, and in the - other case to avoid infinite bouncing between different - minimums. */ - if (cmp_min > 0 || cmp_min < 0) - { - /* If we will end up with a (-INF, +INF) range, set it to - VARYING. Same if the previous max value was invalid for - the type and we'd end up with vr_result.min > vr_result.max. */ - if (vrp_val_is_max (vr_result.max) - || compare_values (TYPE_MIN_VALUE (TREE_TYPE (vr_result.min)), - vr_result.max) > 0) - goto varying; - - if (!needs_overflow_infinity (TREE_TYPE (vr_result.min)) - || !vrp_var_may_overflow (lhs, phi)) - vr_result.min = TYPE_MIN_VALUE (TREE_TYPE (vr_result.min)); - else if (supports_overflow_infinity (TREE_TYPE (vr_result.min))) - vr_result.min = - negative_overflow_infinity (TREE_TYPE (vr_result.min)); - else - goto varying; - } - - /* Similarly, if the new maximum is smaller or larger than - the previous one, go all the way to +INF. */ - if (cmp_max < 0 || cmp_max > 0) - { - /* If we will end up with a (-INF, +INF) range, set it to - VARYING. Same if the previous min value was invalid for - the type and we'd end up with vr_result.max < vr_result.min. */ - if (vrp_val_is_min (vr_result.min) - || compare_values (TYPE_MAX_VALUE (TREE_TYPE (vr_result.max)), - vr_result.min) < 0) - goto varying; - - if (!needs_overflow_infinity (TREE_TYPE (vr_result.max)) - || !vrp_var_may_overflow (lhs, phi)) - vr_result.max = TYPE_MAX_VALUE (TREE_TYPE (vr_result.max)); - else if (supports_overflow_infinity (TREE_TYPE (vr_result.max))) - vr_result.max = - positive_overflow_infinity (TREE_TYPE (vr_result.max)); - else - goto varying; - } - } + if (edges > 0 + && gimple_phi_num_args (phi) > 1 + && edges == old_edges) + { + int cmp_min = compare_values (lhs_vr->min, vr_result.min); + int cmp_max = compare_values (lhs_vr->max, vr_result.max); + + /* For non VR_RANGE or for pointers fall back to varying if + the range changed. */ + if ((lhs_vr->type != VR_RANGE || vr_result.type != VR_RANGE + || POINTER_TYPE_P (TREE_TYPE (lhs))) + && (cmp_min != 0 || cmp_max != 0)) + goto varying; + + /* If the new minimum is smaller or larger than the previous + one, go all the way to -INF. In the first case, to avoid + iterating millions of times to reach -INF, and in the + other case to avoid infinite bouncing between different + minimums. */ + if (cmp_min > 0 || cmp_min < 0) + { + if (!needs_overflow_infinity (TREE_TYPE (vr_result.min)) + || !vrp_var_may_overflow (lhs, phi)) + vr_result.min = TYPE_MIN_VALUE (TREE_TYPE (vr_result.min)); + else if (supports_overflow_infinity (TREE_TYPE (vr_result.min))) + vr_result.min = + negative_overflow_infinity (TREE_TYPE (vr_result.min)); + } + + /* Similarly, if the new maximum is smaller or larger than + the previous one, go all the way to +INF. */ + if (cmp_max < 0 || cmp_max > 0) + { + if (!needs_overflow_infinity (TREE_TYPE (vr_result.max)) + || !vrp_var_may_overflow (lhs, phi)) + vr_result.max = TYPE_MAX_VALUE (TREE_TYPE (vr_result.max)); + else if (supports_overflow_infinity (TREE_TYPE (vr_result.max))) + vr_result.max = + positive_overflow_infinity (TREE_TYPE (vr_result.max)); + } + + /* If we dropped either bound to +-INF then if this is a loop + PHI node SCEV may known more about its value-range. */ + if ((cmp_min > 0 || cmp_min < 0 + || cmp_max < 0 || cmp_max > 0) + && current_loops + && (l = loop_containing_stmt (phi)) + && l->header == gimple_bb (phi)) + adjust_range_with_scev (&vr_result, l, phi, lhs); + + /* If we will end up with a (-INF, +INF) range, set it to + VARYING. Same if the previous max value was invalid for + the type and we end up with vr_result.min > vr_result.max. */ + if ((vrp_val_is_max (vr_result.max) + && vrp_val_is_min (vr_result.min)) + || compare_values (vr_result.min, + vr_result.max) > 0) + goto varying; } /* If the new range is different than the previous value, keep @@ -6857,7 +6929,7 @@ simplify_div_or_mod_using_ranges (gimple stmt) if (rhs_code == TRUNC_DIV_EXPR) { - t = build_int_cst (NULL_TREE, tree_log2 (op1)); + t = build_int_cst (integer_type_node, tree_log2 (op1)); gimple_assign_set_rhs_code (stmt, RSHIFT_EXPR); gimple_assign_set_rhs1 (stmt, op0); gimple_assign_set_rhs2 (stmt, t); @@ -6865,7 +6937,7 @@ simplify_div_or_mod_using_ranges (gimple stmt) else { t = build_int_cst (TREE_TYPE (op1), 1); - t = int_const_binop (MINUS_EXPR, op1, t, 0); + t = int_const_binop (MINUS_EXPR, op1, t); t = fold_convert (TREE_TYPE (op0), t); gimple_assign_set_rhs_code (stmt, BIT_AND_EXPR); @@ -7470,7 +7542,7 @@ identify_jump_threads (void) /* Do not thread across edges we are about to remove. Just marking them as EDGE_DFS_BACK will do. */ - for (i = 0; VEC_iterate (edge, to_remove_edges, i, e); ++i) + FOR_EACH_VEC_ELT (edge, to_remove_edges, i, e) e->flags |= EDGE_DFS_BACK; /* Allocate our unwinder stack to unwind any temporary equivalences @@ -7503,23 +7575,25 @@ identify_jump_threads (void) may be some value in handling SWITCH_EXPR here, I doubt it's terribly important. */ last = gsi_stmt (gsi_last_bb (bb)); - if (gimple_code (last) != GIMPLE_COND) - continue; - /* We're basically looking for any kind of conditional with - integral type arguments. */ - if (TREE_CODE (gimple_cond_lhs (last)) == SSA_NAME - && INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (last))) - && (TREE_CODE (gimple_cond_rhs (last)) == SSA_NAME - || is_gimple_min_invariant (gimple_cond_rhs (last))) - && INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_rhs (last)))) + /* We're basically looking for a switch or any kind of conditional with + integral or pointer type arguments. Note the type of the second + argument will be the same as the first argument, so no need to + check it explicitly. */ + if (gimple_code (last) == GIMPLE_SWITCH + || (gimple_code (last) == GIMPLE_COND + && TREE_CODE (gimple_cond_lhs (last)) == SSA_NAME + && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (last))) + || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (last)))) + && (TREE_CODE (gimple_cond_rhs (last)) == SSA_NAME + || is_gimple_min_invariant (gimple_cond_rhs (last))))) { edge_iterator ei; /* We've got a block with multiple predecessors and multiple - successors which also ends in a suitable conditional. For - each predecessor, see if we can thread it to a specific - successor. */ + successors which also ends in a suitable conditional or + switch statement. For each predecessor, see if we can thread + it to a specific successor. */ FOR_EACH_EDGE (e, ei, bb->preds) { /* Do not thread across back edges or abnormal edges @@ -7650,6 +7724,12 @@ execute_vrp (void) rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); scev_initialize (); + /* Estimate number of iterations - but do not use undefined behavior + for this. We can't do this lazily as other functions may compute + this using undefined behavior. */ + free_numbers_of_iterations_estimates (); + estimate_numbers_of_iterations (false); + insert_range_assertions (); to_remove_edges = VEC_alloc (edge, heap, 10); @@ -7676,10 +7756,10 @@ execute_vrp (void) /* Remove dead edges from SWITCH_EXPR optimization. This leaves the CFG in a broken state and requires a cfg_cleanup run. */ - for (i = 0; VEC_iterate (edge, to_remove_edges, i, e); ++i) + FOR_EACH_VEC_ELT (edge, to_remove_edges, i, e) remove_edge (e); /* Update SWITCH_EXPR case label vector. */ - for (i = 0; VEC_iterate (switch_update, to_update_switch_stmts, i, su); ++i) + FOR_EACH_VEC_ELT (switch_update, to_update_switch_stmts, i, su) { size_t j; size_t n = TREE_VEC_LENGTH (su->vec); @@ -7729,9 +7809,10 @@ struct gimple_opt_pass pass_vrp = 0, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_cleanup_cfg - | TODO_ggc_collect + | TODO_update_ssa | TODO_verify_ssa + | TODO_verify_flow | TODO_dump_func - | TODO_update_ssa /* todo_flags_finish */ + | TODO_ggc_collect /* todo_flags_finish */ } };