aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/tree-vrp.c129
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;
}
}