diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 129 |
2 files changed, 109 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f0a7f15..d39c6d2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2005-05-02 Diego Novillo <dnovillo@redhat.com> + + * tree-vrp.c (set_value_range_to_nonnull): Declare inline. + (set_value_range_to_null): Likewise. + (set_value_range_to_varying): New function. Use it in all + call sites that used to call set_value_range (vr, VR_VARYING, ...). + (extract_range_from_assert): If the integral type has a + super-type, and LIMIT is not within MIN and MAX values of that + type, set the resulting range to VR_VARYING. + 2005-05-02 Hans-Peter Nilsson <hp@bitrange.com> * config/mmix/mmix.opt: New file. diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index e6cb017..e2f2a44 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -251,7 +251,7 @@ range_is_null (value_range *vr) /* Set value range VR to a non-NULL range of type TYPE. */ -static void +static inline void set_value_range_to_nonnull (value_range *vr, tree type) { tree zero = build_int_cst (type, 0); @@ -261,7 +261,7 @@ set_value_range_to_nonnull (value_range *vr, tree type) /* Set value range VR to a NULL range of type TYPE. */ -static void +static inline void set_value_range_to_null (value_range *vr, tree type) { tree zero = build_int_cst (type, 0); @@ -269,6 +269,15 @@ set_value_range_to_null (value_range *vr, tree type) } +/* Set value range VR to VR_VARYING. */ + +static inline void +set_value_range_to_varying (value_range *vr) +{ + set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); +} + + /* Compare two values VAL1 and VAL2. Return -2 if VAL1 and VAL2 cannot be compared at compile-time, @@ -477,9 +486,11 @@ extract_range_from_assert (value_range *vr_p, tree expr) { tree var, cond, limit, type; value_range *var_vr; + enum tree_code cond_code; var = ASSERT_EXPR_VAR (expr); cond = ASSERT_EXPR_COND (expr); + cond_code = TREE_CODE (cond); gcc_assert (COMPARISON_CLASS_P (cond)); @@ -493,12 +504,70 @@ extract_range_from_assert (value_range *vr_p, tree expr) (NE_EXPR). Notice that we don't need to handle EQ_EXPR in these cases because assertions with equalities are never generated. The assert pass generates straight assignments in those cases. */ - if (POINTER_TYPE_P (type) && TREE_CODE (cond) != NE_EXPR) + if (POINTER_TYPE_P (type) && cond_code != NE_EXPR) { - set_value_range (vr_p, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr_p); return; } + /* Special handling for integral types with super-types. Some FEs + construct integral types derived from other types and restrict + the range of values these new types may take. + + It may happen that LIMIT is actually smaller than TYPE's minimum + value. For instance, the Ada FE is generating code like this + during bootstrap: + + D.1480_32 = nam_30 - 300000361; + if (D.1480_32 <= 1) goto <L112>; else goto <L52>; + <L112>:; + D.1480_94 = ASSERT_EXPR <D.1480_32, D.1480_32 <= 1>; + + All the names are of type types__name_id___XDLU_300000000__399999999 + which has min == 300000000 and max == 399999999. This means that + the ASSERT_EXPR would try to create the range [3000000, 1] which + is invalid. + + The fact that the type specifies MIN and MAX values does not + automatically mean that every variable of that type will always + be within that range, so the predicate may well be true at run + time. If we had symbolic -INF and +INF values, we could + represent this range, but we currently represent -INF and +INF + using the type's min and max values. + + So, the only sensible thing we can do for now is set the + resulting range to VR_VARYING. TODO, would having symbolic -INF + and +INF values be worth the trouble? */ + if (TREE_TYPE (type)) + { + if (cond_code == LE_EXPR || cond_code == LT_EXPR) + { + tree type_min = TYPE_MIN_VALUE (type); + int cmp = compare_values (limit, type_min); + + /* For < or <= comparisons, if LIMIT is smaller than + TYPE_MIN, set the range to VR_VARYING. */ + if (cmp == -1 || cmp == 0) + { + set_value_range_to_varying (vr_p); + return; + } + } + else if (cond_code == GE_EXPR || cond_code == GT_EXPR) + { + tree type_max = TYPE_MIN_VALUE (type); + int cmp = compare_values (limit, type_max); + + /* For > or >= comparisons, if LIMIT is bigger than + TYPE_MAX, set the range to VR_VARYING. */ + if (cmp == 1 || cmp == 0) + { + set_value_range_to_varying (vr_p); + return; + } + } + } + if (TREE_CODE (cond) == NE_EXPR) set_value_range (vr_p, VR_ANTI_RANGE, limit, limit); else if (TREE_CODE (cond) == LE_EXPR) @@ -599,7 +668,7 @@ extract_range_from_binary_expr (value_range *vr, tree expr) && code != MIN_EXPR && code != MAX_EXPR) { - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); return; } @@ -613,7 +682,7 @@ extract_range_from_binary_expr (value_range *vr, tree expr) if (is_gimple_min_invariant (op0)) set_value_range (&vr0, VR_RANGE, op0, op0); else - set_value_range (&vr0, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (&vr0); } op1 = TREE_OPERAND (expr, 1); @@ -624,7 +693,7 @@ extract_range_from_binary_expr (value_range *vr, tree expr) if (is_gimple_min_invariant (op1)) set_value_range (&vr1, VR_RANGE, op1, op1); else - set_value_range (&vr1, VR_VARYING, 0, 0); + set_value_range_to_varying (&vr1); } /* If either range is UNDEFINED, so is the result. */ @@ -637,21 +706,21 @@ extract_range_from_binary_expr (value_range *vr, tree expr) /* If either range is VARYING, so is the result. */ if (vr0.type == VR_VARYING || vr1.type == VR_VARYING) { - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); return; } /* If the ranges are of different types, the result is VARYING. */ if (vr0.type != vr1.type) { - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); return; } /* TODO. Refuse to do any symbolic range operations for now. */ if (symbolic_range_p (&vr0) || symbolic_range_p (&vr1)) { - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); return; } @@ -676,7 +745,7 @@ extract_range_from_binary_expr (value_range *vr, tree expr) { /* Subtracting from a pointer, may yield 0, so just drop the resulting range to varying. */ - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); } return; @@ -710,7 +779,7 @@ extract_range_from_binary_expr (value_range *vr, tree expr) /* If the new range has its limits swapped around (MIN > MAX), then the operation caused one of them to wrap around, mark the new range VARYING. */ - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); } else set_value_range (vr, vr0.type, min, max); @@ -767,7 +836,7 @@ extract_range_from_unary_expr (value_range *vr, tree expr) if (is_gimple_min_invariant (op0)) set_value_range (&vr0, VR_RANGE, op0, op0); else - set_value_range (&vr0, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (&vr0); } /* If VR0 is UNDEFINED, so is the result. */ @@ -780,14 +849,14 @@ extract_range_from_unary_expr (value_range *vr, tree expr) /* If VR0 is VARYING, so is the result. */ if (vr0.type == VR_VARYING) { - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); return; } /* TODO. Refuse to do any symbolic range operations for now. */ if (symbolic_range_p (&vr0)) { - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); return; } @@ -796,7 +865,7 @@ extract_range_from_unary_expr (value_range *vr, tree expr) if (!INTEGRAL_TYPE_P (TREE_TYPE (op0)) && !POINTER_TYPE_P (TREE_TYPE (op0))) { - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); return; } @@ -809,7 +878,7 @@ extract_range_from_unary_expr (value_range *vr, tree expr) else if (range_is_null (&vr0)) set_value_range_to_null (vr, TREE_TYPE (expr)); else - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); return; } @@ -824,7 +893,7 @@ extract_range_from_unary_expr (value_range *vr, tree expr) int' and 'y_5 = (unsigned short) x_3', if x_3 is ~[0, 0], it is impossible to know at compile time whether y_5 will be ~[0, 0]. */ - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); return; } @@ -839,7 +908,7 @@ extract_range_from_unary_expr (value_range *vr, tree expr) /* If the new range has its limits swapped around (MIN > MAX), then the operation caused one of them to wrap around, mark the new range VARYING. */ - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); } else set_value_range (vr, vr0.type, min, max); @@ -867,7 +936,7 @@ extract_range_from_expr (value_range *vr, tree expr) else if (TREE_CODE (expr) == INTEGER_CST) set_value_range (vr, VR_RANGE, expr, expr); else - set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr); } @@ -1791,7 +1860,7 @@ vrp_initialize (void) if (!stmt_interesting_for_vrp (phi)) { tree lhs = PHI_RESULT (phi); - set_value_range (get_value_range (lhs), VR_VARYING, 0, 0); + set_value_range_to_varying (get_value_range (lhs)); DONT_SIMULATE_AGAIN (phi) = true; } else @@ -1807,7 +1876,7 @@ vrp_initialize (void) ssa_op_iter i; tree def; FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_DEF) - set_value_range (get_value_range (def), VR_VARYING, 0, 0); + set_value_range_to_varying (get_value_range (def)); DONT_SIMULATE_AGAIN (stmt) = true; } else @@ -1878,7 +1947,7 @@ vrp_visit_assignment (tree stmt, tree *output_p) /* Every other statements produces no useful ranges. */ FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF) - set_value_range (get_value_range (def), VR_VARYING, 0, 0); + set_value_range_to_varying (get_value_range (def)); return SSA_PROP_VARYING; } @@ -2021,7 +2090,7 @@ vrp_visit_stmt (tree stmt, edge *taken_edge_p, tree *output_p) /* All other statements produce nothing of interest for VRP, so mark their outputs varying and prevent further simulation. */ FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF) - set_value_range (get_value_range (def), VR_VARYING, 0, 0); + set_value_range_to_varying (get_value_range (def)); return SSA_PROP_VARYING; } @@ -2067,7 +2136,7 @@ vrp_meet (value_range *vr0, value_range *vr1) /* If either is a symbolic range, drop to VARYING. */ if (symbolic_range_p (vr0) || symbolic_range_p (vr1)) { - set_value_range (vr0, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr0); return; } @@ -2097,7 +2166,7 @@ vrp_meet (value_range *vr0, value_range *vr1) else { /* The two ranges don't intersect, set the result to VR_VARYING. */ - set_value_range (vr0, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr0); } } else if (vr0->type == VR_ANTI_RANGE && vr1->type == VR_ANTI_RANGE) @@ -2108,7 +2177,7 @@ vrp_meet (value_range *vr0, value_range *vr1) && compare_values (vr0->min, vr0->max) == 0) /* Nothing to do. */ ; else - set_value_range (vr0, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr0); } else if (vr0->type == VR_ANTI_RANGE || vr1->type == VR_ANTI_RANGE) { @@ -2121,7 +2190,7 @@ vrp_meet (value_range *vr0, value_range *vr1) *vr0 = *vr1; } else - set_value_range (vr0, VR_VARYING, NULL_TREE, NULL_TREE); + set_value_range_to_varying (vr0); } else gcc_unreachable (); @@ -2190,7 +2259,7 @@ vrp_visit_phi_node (tree phi) if (vr_result.type == VR_VARYING) { - set_value_range (lhs_vr, VR_VARYING, 0, 0); + set_value_range_to_varying (lhs_vr); return SSA_PROP_VARYING; } @@ -2222,7 +2291,7 @@ vrp_visit_phi_node (tree phi) if (vr_result.min == TYPE_MIN_VALUE (TREE_TYPE (vr_result.min)) && vr_result.max == TYPE_MAX_VALUE (TREE_TYPE (vr_result.max))) { - set_value_range (lhs_vr, VR_VARYING, 0, 0); + set_value_range_to_varying (lhs_vr); return SSA_PROP_VARYING; } } |